From 995863cc8e3e2ab08a8ff18dc937c7a32a7479e0 Mon Sep 17 00:00:00 2001 From: Kuppuswamy Sathyanarayanan Date: Tue, 16 Sep 2014 04:54:00 +0100 Subject: iio: jsa1212: Add JSA1212 proximity/ALS sensor This patch adds a new driver for solteam opto JSA1212 proximity and ambient light sensor. Basic details of the chip can be found here. http://www.solteamopto.com.tw/detail.php?ms=3&po_unit=2&pt_unit=29&p_unit=120 Signed-off-by: Kuppuswamy Sathyanarayanan Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 5bea821..2e2ba12 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -109,6 +109,16 @@ config HID_SENSOR_PROX To compile this driver as a module, choose M here: the module will be called hid-sensor-prox. +config JSA1212 + tristate "JSA1212 ALS and proximity sensor driver" + depends on I2C + help + Say Y here if you want to build a IIO driver for JSA1212 + proximity & ALS sensor device. + + To compile this driver as a module, choose M here: + the module will be called jsa1212. + config SENSORS_LM3533 tristate "LM3533 ambient light sensor" depends on MFD_LM3533 diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 47877a3..74656c1 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o obj-$(CONFIG_ISL29125) += isl29125.o +obj-$(CONFIG_JSA1212) += jsa1212.o obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o obj-$(CONFIG_LTR501) += ltr501.o obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c new file mode 100644 index 0000000..29de7e7 --- /dev/null +++ b/drivers/iio/light/jsa1212.c @@ -0,0 +1,471 @@ +/* + * JSA1212 Ambient Light & Proximity Sensor Driver + * + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * JSA1212 I2C slave address: 0x44(ADDR tied to GND), 0x45(ADDR tied to VDD) + * + * TODO: Interrupt support, thresholds, range support. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* JSA1212 reg address */ +#define JSA1212_CONF_REG 0x01 +#define JSA1212_INT_REG 0x02 +#define JSA1212_PXS_LT_REG 0x03 +#define JSA1212_PXS_HT_REG 0x04 +#define JSA1212_ALS_TH1_REG 0x05 +#define JSA1212_ALS_TH2_REG 0x06 +#define JSA1212_ALS_TH3_REG 0x07 +#define JSA1212_PXS_DATA_REG 0x08 +#define JSA1212_ALS_DT1_REG 0x09 +#define JSA1212_ALS_DT2_REG 0x0A +#define JSA1212_ALS_RNG_REG 0x0B +#define JSA1212_MAX_REG 0x0C + +/* JSA1212 reg masks */ +#define JSA1212_CONF_MASK 0xFF +#define JSA1212_INT_MASK 0xFF +#define JSA1212_PXS_LT_MASK 0xFF +#define JSA1212_PXS_HT_MASK 0xFF +#define JSA1212_ALS_TH1_MASK 0xFF +#define JSA1212_ALS_TH2_LT_MASK 0x0F +#define JSA1212_ALS_TH2_HT_MASK 0xF0 +#define JSA1212_ALS_TH3_MASK 0xFF +#define JSA1212_PXS_DATA_MASK 0xFF +#define JSA1212_ALS_DATA_MASK 0x0FFF +#define JSA1212_ALS_DT1_MASK 0xFF +#define JSA1212_ALS_DT2_MASK 0x0F +#define JSA1212_ALS_RNG_MASK 0x07 + +/* JSA1212 CONF REG bits */ +#define JSA1212_CONF_PXS_MASK 0x80 +#define JSA1212_CONF_PXS_ENABLE 0x80 +#define JSA1212_CONF_PXS_DISABLE 0x00 +#define JSA1212_CONF_ALS_MASK 0x04 +#define JSA1212_CONF_ALS_ENABLE 0x04 +#define JSA1212_CONF_ALS_DISABLE 0x00 +#define JSA1212_CONF_IRDR_MASK 0x08 +/* Proxmity sensing IRDR current sink settings */ +#define JSA1212_CONF_IRDR_200MA 0x08 +#define JSA1212_CONF_IRDR_100MA 0x00 +#define JSA1212_CONF_PXS_SLP_MASK 0x70 +#define JSA1212_CONF_PXS_SLP_0MS 0x70 +#define JSA1212_CONF_PXS_SLP_12MS 0x60 +#define JSA1212_CONF_PXS_SLP_50MS 0x50 +#define JSA1212_CONF_PXS_SLP_75MS 0x40 +#define JSA1212_CONF_PXS_SLP_100MS 0x30 +#define JSA1212_CONF_PXS_SLP_200MS 0x20 +#define JSA1212_CONF_PXS_SLP_400MS 0x10 +#define JSA1212_CONF_PXS_SLP_800MS 0x00 + +/* JSA1212 INT REG bits */ +#define JSA1212_INT_CTRL_MASK 0x01 +#define JSA1212_INT_CTRL_EITHER 0x00 +#define JSA1212_INT_CTRL_BOTH 0x01 +#define JSA1212_INT_ALS_PRST_MASK 0x06 +#define JSA1212_INT_ALS_PRST_1CONV 0x00 +#define JSA1212_INT_ALS_PRST_4CONV 0x02 +#define JSA1212_INT_ALS_PRST_8CONV 0x04 +#define JSA1212_INT_ALS_PRST_16CONV 0x06 +#define JSA1212_INT_ALS_FLAG_MASK 0x08 +#define JSA1212_INT_ALS_FLAG_CLR 0x00 +#define JSA1212_INT_PXS_PRST_MASK 0x60 +#define JSA1212_INT_PXS_PRST_1CONV 0x00 +#define JSA1212_INT_PXS_PRST_4CONV 0x20 +#define JSA1212_INT_PXS_PRST_8CONV 0x40 +#define JSA1212_INT_PXS_PRST_16CONV 0x60 +#define JSA1212_INT_PXS_FLAG_MASK 0x80 +#define JSA1212_INT_PXS_FLAG_CLR 0x00 + +/* JSA1212 ALS RNG REG bits */ +#define JSA1212_ALS_RNG_0_2048 0x00 +#define JSA1212_ALS_RNG_0_1024 0x01 +#define JSA1212_ALS_RNG_0_512 0x02 +#define JSA1212_ALS_RNG_0_256 0x03 +#define JSA1212_ALS_RNG_0_128 0x04 + +/* JSA1212 INT threshold range */ +#define JSA1212_ALS_TH_MIN 0x0000 +#define JSA1212_ALS_TH_MAX 0x0FFF +#define JSA1212_PXS_TH_MIN 0x00 +#define JSA1212_PXS_TH_MAX 0xFF + +#define JSA1212_ALS_DELAY_MS 200 +#define JSA1212_PXS_DELAY_MS 100 + +#define JSA1212_DRIVER_NAME "jsa1212" +#define JSA1212_REGMAP_NAME "jsa1212_regmap" + +enum jsa1212_op_mode { + JSA1212_OPMODE_ALS_EN, + JSA1212_OPMODE_PXS_EN, +}; + +struct jsa1212_data { + struct i2c_client *client; + struct mutex lock; + u8 als_rng_idx; + bool als_en; /* ALS enable status */ + bool pxs_en; /* proximity enable status */ + struct regmap *regmap; +}; + +/* ALS range idx to val mapping */ +static const int jsa1212_als_range_val[] = {2048, 1024, 512, 256, 128, + 128, 128, 128}; + +/* Enables or disables ALS function based on status */ +static int jsa1212_als_enable(struct jsa1212_data *data, u8 status) +{ + int ret; + + ret = regmap_update_bits(data->regmap, JSA1212_CONF_REG, + JSA1212_CONF_ALS_MASK, + status); + if (ret < 0) + return ret; + + data->als_en = !!status; + + return 0; +} + +/* Enables or disables PXS function based on status */ +static int jsa1212_pxs_enable(struct jsa1212_data *data, u8 status) +{ + int ret; + + ret = regmap_update_bits(data->regmap, JSA1212_CONF_REG, + JSA1212_CONF_PXS_MASK, + status); + if (ret < 0) + return ret; + + data->pxs_en = !!status; + + return 0; +} + +static int jsa1212_read_als_data(struct jsa1212_data *data, + unsigned int *val) +{ + int ret; + __le16 als_data; + + ret = jsa1212_als_enable(data, JSA1212_CONF_ALS_ENABLE); + if (ret < 0) + return ret; + + /* Delay for data output */ + msleep(JSA1212_ALS_DELAY_MS); + + /* Read 12 bit data */ + ret = regmap_bulk_read(data->regmap, JSA1212_ALS_DT1_REG, &als_data, 2); + if (ret < 0) { + dev_err(&data->client->dev, "als data read err\n"); + goto als_data_read_err; + } + + *val = le16_to_cpu(als_data); + +als_data_read_err: + return jsa1212_als_enable(data, JSA1212_CONF_ALS_DISABLE); +} + +static int jsa1212_read_pxs_data(struct jsa1212_data *data, + unsigned int *val) +{ + int ret; + unsigned int pxs_data; + + ret = jsa1212_pxs_enable(data, JSA1212_CONF_PXS_ENABLE); + if (ret < 0) + return ret; + + /* Delay for data output */ + msleep(JSA1212_PXS_DELAY_MS); + + /* Read out all data */ + ret = regmap_read(data->regmap, JSA1212_PXS_DATA_REG, &pxs_data); + if (ret < 0) { + dev_err(&data->client->dev, "pxs data read err\n"); + goto pxs_data_read_err; + } + + *val = pxs_data & JSA1212_PXS_DATA_MASK; + +pxs_data_read_err: + return jsa1212_pxs_enable(data, JSA1212_CONF_PXS_DISABLE); +} + +static int jsa1212_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + int ret; + struct jsa1212_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&data->lock); + switch (chan->type) { + case IIO_LIGHT: + ret = jsa1212_read_als_data(data, val); + break; + case IIO_PROXIMITY: + ret = jsa1212_read_pxs_data(data, val); + break; + default: + ret = -EINVAL; + break; + } + mutex_unlock(&data->lock); + return ret < 0 ? ret : IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_LIGHT: + *val = jsa1212_als_range_val[data->als_rng_idx]; + *val2 = BIT(12); /* Max 12 bit value */ + return IIO_VAL_FRACTIONAL; + default: + break; + } + break; + default: + break; + } + + return -EINVAL; +} + +static const struct iio_chan_spec jsa1212_channels[] = { + { + .type = IIO_LIGHT, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + }, + { + .type = IIO_PROXIMITY, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + } +}; + +static const struct iio_info jsa1212_info = { + .driver_module = THIS_MODULE, + .read_raw = &jsa1212_read_raw, +}; + +static int jsa1212_chip_init(struct jsa1212_data *data) +{ + int ret; + + ret = regmap_write(data->regmap, JSA1212_CONF_REG, + (JSA1212_CONF_PXS_SLP_50MS | + JSA1212_CONF_IRDR_200MA)); + if (ret < 0) + return ret; + + ret = regmap_write(data->regmap, JSA1212_INT_REG, + JSA1212_INT_ALS_PRST_4CONV); + if (ret < 0) + return ret; + + data->als_rng_idx = JSA1212_ALS_RNG_0_2048; + + return 0; +} + +static bool jsa1212_is_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case JSA1212_PXS_DATA_REG: + case JSA1212_ALS_DT1_REG: + case JSA1212_ALS_DT2_REG: + case JSA1212_INT_REG: + return true; + default: + return false; + } +} + +static struct regmap_config jsa1212_regmap_config = { + .name = JSA1212_REGMAP_NAME, + .reg_bits = 8, + .val_bits = 8, + .max_register = JSA1212_MAX_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = jsa1212_is_volatile_reg, +}; + +static int jsa1212_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct jsa1212_data *data; + struct iio_dev *indio_dev; + struct regmap *regmap; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + regmap = devm_regmap_init_i2c(client, &jsa1212_regmap_config); + if (IS_ERR(regmap)) { + dev_err(&client->dev, "Regmap initialization failed.\n"); + return PTR_ERR(regmap); + } + + data = iio_priv(indio_dev); + + i2c_set_clientdata(client, indio_dev); + data->client = client; + data->regmap = regmap; + + mutex_init(&data->lock); + + ret = jsa1212_chip_init(data); + if (ret < 0) + return ret; + + indio_dev->dev.parent = &client->dev; + indio_dev->channels = jsa1212_channels; + indio_dev->num_channels = ARRAY_SIZE(jsa1212_channels); + indio_dev->name = JSA1212_DRIVER_NAME; + indio_dev->modes = INDIO_DIRECT_MODE; + + indio_dev->info = &jsa1212_info; + + ret = iio_device_register(indio_dev); + if (ret < 0) + dev_err(&client->dev, "%s: register device failed\n", __func__); + + return ret; +} + + /* power off the device */ +static int jsa1212_power_off(struct jsa1212_data *data) +{ + int ret; + + mutex_lock(&data->lock); + + ret = regmap_update_bits(data->regmap, JSA1212_CONF_REG, + JSA1212_CONF_ALS_MASK | + JSA1212_CONF_PXS_MASK, + JSA1212_CONF_ALS_DISABLE | + JSA1212_CONF_PXS_DISABLE); + + if (ret < 0) + dev_err(&data->client->dev, "power off cmd failed\n"); + + mutex_unlock(&data->lock); + + return ret; +} + +static int jsa1212_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct jsa1212_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + return jsa1212_power_off(data); +} + +#ifdef CONFIG_PM_SLEEP +static int jsa1212_suspend(struct device *dev) +{ + struct jsa1212_data *data; + + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + return jsa1212_power_off(data); +} + +static int jsa1212_resume(struct device *dev) +{ + int ret = 0; + struct jsa1212_data *data; + + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + mutex_lock(&data->lock); + + if (data->als_en) { + ret = jsa1212_als_enable(data, JSA1212_CONF_ALS_ENABLE); + if (ret < 0) { + dev_err(dev, "als resume failed\n"); + goto unlock_and_ret; + } + } + + if (data->pxs_en) { + ret = jsa1212_pxs_enable(data, JSA1212_CONF_PXS_ENABLE); + if (ret < 0) + dev_err(dev, "pxs resume failed\n"); + } + +unlock_and_ret: + mutex_unlock(&data->lock); + return ret; +} + +static SIMPLE_DEV_PM_OPS(jsa1212_pm_ops, jsa1212_suspend, jsa1212_resume); + +#define JSA1212_PM_OPS (&jsa1212_pm_ops) +#else +#define JSA1212_PM_OPS NULL +#endif + +static const struct acpi_device_id jsa1212_acpi_match[] = { + {"JSA1212", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, jsa1212_acpi_match); + +static const struct i2c_device_id jsa1212_id[] = { + { JSA1212_DRIVER_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, jsa1212_id); + +static struct i2c_driver jsa1212_driver = { + .driver = { + .name = JSA1212_DRIVER_NAME, + .pm = JSA1212_PM_OPS, + .owner = THIS_MODULE, + .acpi_match_table = ACPI_PTR(jsa1212_acpi_match), + }, + .probe = jsa1212_probe, + .remove = jsa1212_remove, + .id_table = jsa1212_id, +}; +module_i2c_driver(jsa1212_driver); + +MODULE_AUTHOR("Sathya Kuppuswamy "); +MODULE_DESCRIPTION("JSA1212 proximity/ambient light sensor driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 3bfa74f86006ff8cc1c3cf71f3bdaa885e952f39 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Sun, 11 May 2014 22:09:00 +0100 Subject: iio:kxcjk-1013: Add support for SMO8500 device The Onda v975w tablet contains an accelerometer that's advertised over ACPI as SMO8500. This device is however a KXCJ9 accelerometer as can be seen in the Windows driver's INF file, and from the etching on the chipset ("KXCJ9 41566 0414"). This patch also removes the attempt to get the IRQ for the "data ready" signal, as it does not seem to be supported by this device on this platform. Signed-off-by: Bastien Nocera Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 98909a9..1720e9a 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -108,6 +108,7 @@ struct kxcjk1013_data { bool motion_trigger_on; int64_t timestamp; enum kx_chipset chipset; + bool is_smo8500_device; }; enum kxcjk1013_axis { @@ -1129,12 +1130,15 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private) } static const char *kxcjk1013_match_acpi_device(struct device *dev, - enum kx_chipset *chipset) + enum kx_chipset *chipset, + bool *is_smo8500_device) { const struct acpi_device_id *id; id = acpi_match_device(dev->driver->acpi_match_table, dev); if (!id) return NULL; + if (strcmp(id->id, "SMO8500") == 0) + *is_smo8500_device = true; *chipset = (enum kx_chipset)id->driver_data; return dev_name(dev); @@ -1149,6 +1153,8 @@ static int kxcjk1013_gpio_probe(struct i2c_client *client, if (!client) return -EINVAL; + if (data->is_smo8500_device) + return -ENOTSUPP; dev = &client->dev; @@ -1198,7 +1204,8 @@ static int kxcjk1013_probe(struct i2c_client *client, name = id->name; } else if (ACPI_HANDLE(&client->dev)) { name = kxcjk1013_match_acpi_device(&client->dev, - &data->chipset); + &data->chipset, + &data->is_smo8500_device); } else return -ENODEV; @@ -1397,6 +1404,7 @@ static const struct acpi_device_id kx_acpi_match[] = { {"KXCJ1013", KXCJK1013}, {"KXCJ1008", KXCJ91008}, {"KXTJ1009", KXTJ21009}, + {"SMO8500", KXCJ91008}, { }, }; MODULE_DEVICE_TABLE(acpi, kx_acpi_match); @@ -1405,6 +1413,7 @@ static const struct i2c_device_id kxcjk1013_id[] = { {"kxcjk1013", KXCJK1013}, {"kxcj91008", KXCJ91008}, {"kxtj21009", KXTJ21009}, + {"SMO8500", KXCJ91008}, {} }; -- cgit v0.10.2 From 11c2f16d1daf64bd0b2d4ce919c2b4f6690fb79a Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 11 Nov 2014 14:36:00 +0000 Subject: MAINTAINERS: Add IIO include files Files under include/linux/iio were not reported as part of the IIO subsystem. Reported-by: Cristina Ciocan Signed-off-by: Daniel Baluta Reviewed-by: Jingoo Han Signed-off-by: Jonathan Cameron diff --git a/MAINTAINERS b/MAINTAINERS index df2aecf..264f3cc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4707,6 +4707,7 @@ L: linux-iio@vger.kernel.org S: Maintained F: drivers/iio/ F: drivers/staging/iio/ +F: include/linux/iio/ IKANOS/ADI EAGLE ADSL USB DRIVER M: Matthieu Castet -- cgit v0.10.2 From d7d787d29148cde12958c2e3765ad3a55dc55eaf Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 18 Nov 2014 18:47:55 +0200 Subject: iio: imu: Add support for Kionix KMX61 sensor Minimal implementation for KMX61 6-axis accelerometer/magnetometer. It exports raw accel/magn readings together with scale and sampling frequency. Datasheet will be available at: http://www.kionix.com/6-axis-accelerometer-magnetometer/kmx61 Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index 2b0e451..d675f43 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -25,6 +25,15 @@ config ADIS16480 Say yes here to build support for Analog Devices ADIS16375, ADIS16480, ADIS16485, ADIS16488 inertial sensors. +config KMX61 + tristate "Kionix KMX61 6-axis accelerometer and magnetometer" + depends on I2C + help + Say Y here if you want to build a driver for Kionix KMX61 6-axis accelerometer + and magnetometer. + To compile this driver as module, choose M here: the module will be called + kmx61. + source "drivers/iio/imu/inv_mpu6050/Kconfig" endmenu diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 114d2c1..e1e6e3d 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -14,3 +14,5 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o obj-y += inv_mpu6050/ + +obj-$(CONFIG_KMX61) += kmx61.o diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c new file mode 100644 index 0000000..f68b3ef --- /dev/null +++ b/drivers/iio/imu/kmx61.c @@ -0,0 +1,766 @@ +/* + * KMX61 - Kionix 6-axis Accelerometer/Magnetometer + * + * Copyright (c) 2014, Intel Corporation. + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F). + * + * TODO: buffer, interrupt, thresholds, acpi, temperature sensor + * + */ + +#include +#include +#include +#include +#include +#include + +#define KMX61_DRV_NAME "kmx61" + +#define KMX61_REG_WHO_AM_I 0x00 + +/* + * three 16-bit accelerometer output registers for X/Y/Z axis + * we use only XOUT_L as a base register, all other addresses + * can be obtained by applying an offset and are provided here + * only for clarity. + */ +#define KMX61_ACC_XOUT_L 0x0A +#define KMX61_ACC_XOUT_H 0x0B +#define KMX61_ACC_YOUT_L 0x0C +#define KMX61_ACC_YOUT_H 0x0D +#define KMX61_ACC_ZOUT_L 0x0E +#define KMX61_ACC_ZOUT_H 0x0F + +/* + * one 16-bit temperature output register + */ +#define KMX61_TEMP_L 0x10 +#define KMX61_TEMP_H 0x11 + +/* + * three 16-bit magnetometer output registers for X/Y/Z axis + */ +#define KMX61_MAG_XOUT_L 0x12 +#define KMX61_MAG_XOUT_H 0x13 +#define KMX61_MAG_YOUT_L 0x14 +#define KMX61_MAG_YOUT_H 0x15 +#define KMX61_MAG_ZOUT_L 0x16 +#define KMX61_MAG_ZOUT_H 0x17 + +#define KMX61_REG_ODCNTL 0x2C +#define KMX61_REG_STBY 0x29 +#define KMX61_REG_CTRL1 0x2A + +#define KMX61_ACC_STBY_BIT BIT(0) +#define KMX61_MAG_STBY_BIT BIT(1) +#define KMX61_ACT_STBY_BIT BIT(7) + +#define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT) + +#define KMX61_REG_CTRL1_GSEL0_SHIFT 0 +#define KMX61_REG_CTRL1_GSEL1_SHIFT 1 +#define KMX61_REG_CTRL1_GSEL0_MASK 0x01 +#define KMX61_REG_CTRL1_GSEL1_MASK 0x02 + +#define KMX61_REG_CTRL1_BIT_RES BIT(4) + +#define KMX61_ACC_ODR_SHIFT 0 +#define KMX61_MAG_ODR_SHIFT 4 +#define KMX61_ACC_ODR_MASK 0x0F +#define KMX61_MAG_ODR_MASK 0xF0 + +#define KMX61_SLEEP_DELAY_MS 2000 + +#define KMX61_CHIP_ID 0x12 + +struct kmx61_data { + struct i2c_client *client; + + /* serialize access to non-atomic ops, e.g set_mode */ + struct mutex lock; + u8 range; + u8 odr_bits; + + /* standby state */ + u8 acc_stby; + u8 mag_stby; + + /* power state */ + bool acc_ps; + bool mag_ps; +}; + +enum kmx61_range { + KMX61_RANGE_2G, + KMX61_RANGE_4G, + KMX61_RANGE_8G, +}; + +enum kmx61_scan { + KMX61_SCAN_ACC_X, + KMX61_SCAN_ACC_Y, + KMX61_SCAN_ACC_Z, + KMX61_SCAN_TEMP, + KMX61_SCAN_MAG_X, + KMX61_SCAN_MAG_Y, + KMX61_SCAN_MAG_Z, +}; + +static const struct { + u16 uscale; + u8 gsel0; + u8 gsel1; +} kmx61_scale_table[] = { + {9582, 0, 0}, + {19163, 1, 0}, + {38326, 0, 1}, +}; + +/* KMX61 devices */ +#define KMX61_ACC 0x01 +#define KMX61_MAG 0x02 + +static const struct { + int val; + int val2; + u8 odr_bits; +} kmx61_samp_freq_table[] = { {12, 500000, 0x00}, + {25, 0, 0x01}, + {50, 0, 0x02}, + {100, 0, 0x03}, + {200, 0, 0x04}, + {400, 0, 0x05}, + {800, 0, 0x06}, + {1600, 0, 0x07}, + {0, 781000, 0x08}, + {1, 563000, 0x09}, + {3, 125000, 0x0A}, + {6, 250000, 0x0B} }; + +static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326"); +static IIO_CONST_ATTR(magn_scale_available, "0.001465"); +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( + "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800"); + +static struct attribute *kmx61_attributes[] = { + &iio_const_attr_accel_scale_available.dev_attr.attr, + &iio_const_attr_magn_scale_available.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group kmx61_attribute_group = { + .attrs = kmx61_attributes, +}; + +#define KMX61_ACC_CHAN(_axis, _index) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_ ## _axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = KMX61_ACC, \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_LE, \ + }, \ +} + +#define KMX61_MAG_CHAN(_axis, _index) { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_ ## _axis, \ + .address = KMX61_MAG, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 14, \ + .storagebits = 16, \ + .shift = 2, \ + .endianness = IIO_LE, \ + }, \ +} + +static const struct iio_chan_spec kmx61_channels[] = { + KMX61_ACC_CHAN(X, KMX61_SCAN_ACC_X), + KMX61_ACC_CHAN(Y, KMX61_SCAN_ACC_Y), + KMX61_ACC_CHAN(Z, KMX61_SCAN_ACC_Z), + KMX61_MAG_CHAN(X, KMX61_SCAN_MAG_X), + KMX61_MAG_CHAN(Y, KMX61_SCAN_MAG_Y), + KMX61_MAG_CHAN(Z, KMX61_SCAN_MAG_Z), +}; + +static int kmx61_convert_freq_to_bit(int val, int val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) + if (val == kmx61_samp_freq_table[i].val && + val2 == kmx61_samp_freq_table[i].val2) + return kmx61_samp_freq_table[i].odr_bits; + return -EINVAL; +} +/** + * kmx61_set_mode() - set KMX61 device operating mode + * @data - kmx61 device private data pointer + * @mode - bitmask, indicating operating mode for @device + * @device - bitmask, indicating device for which @mode needs to be set + * @update - update stby bits stored in device's private @data + * + * For each sensor (accelerometer/magnetometer) there are two operating modes + * STANDBY and OPERATION. Neither accel nor magn can be disabled independently + * if they are both enabled. Internal sensors state is saved in acc_stby and + * mag_stby members of driver's private @data. + */ +static int kmx61_set_mode(struct kmx61_data *data, u8 mode, u8 device, + bool update) +{ + int ret; + int acc_stby = -1, mag_stby = -1; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_stby\n"); + return ret; + } + if (device & KMX61_ACC) { + if (mode & KMX61_ACC_STBY_BIT) { + ret |= KMX61_ACC_STBY_BIT; + acc_stby = 1; + } else { + ret &= ~KMX61_ACC_STBY_BIT; + acc_stby = 0; + } + } + + if (device & KMX61_MAG) { + if (mode & KMX61_MAG_STBY_BIT) { + ret |= KMX61_MAG_STBY_BIT; + mag_stby = 1; + } else { + ret &= ~KMX61_MAG_STBY_BIT; + mag_stby = 0; + } + } + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_STBY, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_stby\n"); + return ret; + } + + if (acc_stby != -1 && update) + data->acc_stby = !!acc_stby; + if (mag_stby != -1 && update) + data->mag_stby = !!mag_stby; + + return ret; +} + +static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_stby\n"); + return ret; + } + *mode = 0; + + if (device & KMX61_ACC) { + if (ret & KMX61_ACC_STBY_BIT) + *mode |= KMX61_ACC_STBY_BIT; + else + *mode &= ~KMX61_ACC_STBY_BIT; + } + + if (device & KMX61_MAG) { + if (ret & KMX61_MAG_STBY_BIT) + *mode |= KMX61_MAG_STBY_BIT; + else + *mode &= ~KMX61_MAG_STBY_BIT; + } + + return 0; +} + +static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) +{ + int ret; + u8 mode; + int lodr_bits, odr_bits; + + ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + lodr_bits = kmx61_convert_freq_to_bit(val, val2); + if (lodr_bits < 0) + return lodr_bits; + + /* To change ODR, accel and magn must be in STDBY */ + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, + true); + if (ret < 0) + return ret; + + odr_bits = 0; + if (device & KMX61_ACC) + odr_bits |= lodr_bits; + if (device & KMX61_MAG) + odr_bits |= (lodr_bits << KMX61_MAG_ODR_SHIFT); + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_ODCNTL, + odr_bits); + if (ret < 0) + return ret; + + ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + data->odr_bits = lodr_bits; + + return 0; +} + +static +int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2, u8 device) +{ int i; + u8 lodr_bits; + + if (device & KMX61_ACC) + lodr_bits = (data->odr_bits >> KMX61_ACC_ODR_SHIFT) & + KMX61_ACC_ODR_MASK; + else if (device & KMX61_MAG) + lodr_bits = (data->odr_bits >> KMX61_MAG_ODR_SHIFT) & + KMX61_MAG_ODR_MASK; + else + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) + if (lodr_bits == kmx61_samp_freq_table[i].odr_bits) { + *val = kmx61_samp_freq_table[i].val; + *val2 = kmx61_samp_freq_table[i].val2; + return 0; + } + return -EINVAL; +} + +static int kmx61_set_range(struct kmx61_data *data, int range) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + ret &= ~(KMX61_REG_CTRL1_GSEL0_MASK | KMX61_REG_CTRL1_GSEL1_MASK); + ret |= kmx61_scale_table[range].gsel0 << KMX61_REG_CTRL1_GSEL0_SHIFT; + ret |= kmx61_scale_table[range].gsel1 << KMX61_REG_CTRL1_GSEL1_SHIFT; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); + return ret; + } + + data->range = range; + + return 0; +} + +static int kmx61_set_scale(struct kmx61_data *data, int uscale) +{ + int ret, i; + u8 mode; + + for (i = 0; i < ARRAY_SIZE(kmx61_scale_table); i++) { + if (kmx61_scale_table[i].uscale == uscale) { + ret = kmx61_get_mode(data, &mode, + KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + ret = kmx61_set_mode(data, KMX61_ALL_STBY, + KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + ret = kmx61_set_range(data, i); + if (ret < 0) + return ret; + + return kmx61_set_mode(data, mode, + KMX61_ACC | KMX61_MAG, true); + } + } + return -EINVAL; +} + +static int kmx61_chip_init(struct kmx61_data *data) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading who_am_i\n"); + return ret; + } + + if (ret != KMX61_CHIP_ID) { + dev_err(&data->client->dev, + "Wrong chip id, got %x expected %x\n", + ret, KMX61_CHIP_ID); + return -EINVAL; + } + + /* set accel 12bit, 4g range */ + ret = kmx61_set_range(data, KMX61_RANGE_4G); + if (ret < 0) + return ret; + + /* set acc/magn to OPERATION mode */ + ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + return 0; +} +/** + * kmx61_set_power_state() - set power state for kmx61 @device + * @data - kmx61 device private pointer + * @on - power state to be set for @device + * @device - bitmask indicating device for which @on state needs to be set + * + * Notice that when ACC power state needs to be set to ON and MAG is in + * OPERATION then we know that kmx61_runtime_resume was already called + * so we must set ACC OPERATION mode here. The same happens when MAG power + * state needs to be set to ON and ACC is in OPERATION. + */ +static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) +{ +#ifdef CONFIG_PM_RUNTIME + int ret; + + if (device & KMX61_ACC) { + if (on && !data->acc_ps && !data->mag_stby) + kmx61_set_mode(data, 0, KMX61_ACC, true); + data->acc_ps = on; + } + if (device & KMX61_MAG) { + if (on && !data->mag_ps && !data->acc_stby) + kmx61_set_mode(data, 0, KMX61_MAG, true); + data->mag_ps = on; + } + + if (on) { + ret = pm_runtime_get_sync(&data->client->dev); + } else { + pm_runtime_mark_last_busy(&data->client->dev); + ret = pm_runtime_put_autosuspend(&data->client->dev); + } + if (ret < 0) { + dev_err(&data->client->dev, + "Failed: kmx61_set_power_state for %d, ret %d\n", + on, ret); + return ret; + } +#endif + return 0; +} + +static int kmx61_read_measurement(struct kmx61_data *data, int base, int offset) +{ + int ret; + u8 reg = base + offset * 2; + + ret = i2c_smbus_read_word_data(data->client, reg); + if (ret < 0) { + dev_err(&data->client->dev, "failed to read reg at %x\n", reg); + return ret; + } + + return ret; +} + +static int kmx61_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct kmx61_data *data = iio_priv(indio_dev); + int ret; + u8 base_reg; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_ACCEL: + case IIO_MAGN: + base_reg = KMX61_ACC_XOUT_L; + break; + default: + return -EINVAL; + } + mutex_lock(&data->lock); + + kmx61_set_power_state(data, true, chan->address); + ret = kmx61_read_measurement(data, base_reg, chan->scan_index); + if (ret < 0) { + kmx61_set_power_state(data, false, chan->address); + mutex_unlock(&data->lock); + return ret; + } + *val = sign_extend32(ret >> chan->scan_type.shift, + chan->scan_type.realbits - 1); + kmx61_set_power_state(data, false, chan->address); + + mutex_unlock(&data->lock); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + *val = 0; + *val2 = kmx61_scale_table[data->range].uscale; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_MAGN: + /* 14 bits res, 1465 microGauss per magn count */ + *val = 0; + *val2 = 1465; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SAMP_FREQ: + if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) + return -EINVAL; + + mutex_lock(&data->lock); + ret = kmx61_get_odr(data, val, val2, chan->address); + mutex_unlock(&data->lock); + if (ret) + return -EINVAL; + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + +static int kmx61_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + struct kmx61_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) + return -EINVAL; + + mutex_lock(&data->lock); + ret = kmx61_set_odr(data, val, val2, chan->address); + mutex_unlock(&data->lock); + return ret; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + if (val != 0) + return -EINVAL; + mutex_lock(&data->lock); + ret = kmx61_set_scale(data, val2); + mutex_unlock(&data->lock); + return ret; + default: + return -EINVAL; + } + return ret; + default: + return -EINVAL; + } + return ret; +} + +static const struct iio_info kmx61_info = { + .driver_module = THIS_MODULE, + .read_raw = kmx61_read_raw, + .write_raw = kmx61_write_raw, + .attrs = &kmx61_attribute_group, +}; + +static int kmx61_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct kmx61_data *data; + struct iio_dev *indio_dev; + int ret; + const char *name = NULL; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + if (id) + name = id->name; + + indio_dev->dev.parent = &client->dev; + indio_dev->channels = kmx61_channels; + indio_dev->num_channels = ARRAY_SIZE(kmx61_channels); + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &kmx61_info; + + mutex_init(&data->lock); + + ret = kmx61_chip_init(data); + if (ret < 0) + return ret; + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "Failed to register iio device\n"); + goto err_iio_device_register; + } + + ret = pm_runtime_set_active(&client->dev); + if (ret < 0) + goto err_pm_runtime_set_active; + + pm_runtime_enable(&client->dev); + pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS); + pm_runtime_use_autosuspend(&client->dev); + + return 0; + +err_pm_runtime_set_active: + iio_device_unregister(indio_dev); +err_iio_device_register: + kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + return ret; +} + +static int kmx61_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct kmx61_data *data = iio_priv(indio_dev); + int ret; + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + + iio_device_unregister(indio_dev); + + mutex_lock(&data->lock); + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + mutex_unlock(&data->lock); + + return ret; +} + +#ifdef CONFIG_PM_SLEEP +static int kmx61_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct kmx61_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, + false); + mutex_unlock(&data->lock); + + return ret; +} + +static int kmx61_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct kmx61_data *data = iio_priv(indio_dev); + u8 stby = 0; + + if (data->acc_stby) + stby |= KMX61_ACC_STBY_BIT; + if (data->mag_stby) + stby |= KMX61_MAG_STBY_BIT; + + return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); +} +#endif + +#ifdef CONFIG_PM_RUNTIME +static int kmx61_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct kmx61_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + mutex_unlock(&data->lock); + + return ret; +} + +static int kmx61_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct kmx61_data *data = iio_priv(indio_dev); + u8 stby = 0; + + if (!data->acc_ps) + stby |= KMX61_ACC_STBY_BIT; + if (!data->mag_ps) + stby |= KMX61_MAG_STBY_BIT; + + return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); +} +#endif + +static const struct dev_pm_ops kmx61_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(kmx61_suspend, kmx61_resume) + SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL) +}; + +static const struct i2c_device_id kmx61_id[] = { + {"kmx611021", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, kmx61_id); + +static struct i2c_driver kmx61_driver = { + .driver = { + .name = KMX61_DRV_NAME, + .pm = &kmx61_pm_ops, + }, + .probe = kmx61_probe, + .remove = kmx61_remove, + .id_table = kmx61_id, +}; + +module_i2c_driver(kmx61_driver); + +MODULE_AUTHOR("Daniel Baluta "); +MODULE_DESCRIPTION("KMX61 accelerometer/magnetometer driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 356ae946f9945997213b19279bc2e84bb61cc26a Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 10 Nov 2014 14:45:29 +0200 Subject: iio: dummy: Add virtual registers for dummy device We need a way to store events generated by iio_dummy_evgen module, in order to correctly process IRQs in iio_simple_dummy_events. For the moment, we add two registers: * id_reg - ID register, stores the source of the event * id_data - DATA register, stores the type of the event e.g echo 4 > /sys/bus/iio/devices/iio_evgen/poke2 id_reg 0x02, id_data 0x04 This means, event of type 4 was generated by fake device 2. We currently use a hardcoded mapping of virtual events to IIO events. Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c index 5a804f1..59ad5a3 100644 --- a/drivers/staging/iio/iio_dummy_evgen.c +++ b/drivers/staging/iio/iio_dummy_evgen.c @@ -33,6 +33,7 @@ * @base: base of irq range * @enabled: mask of which irqs are enabled * @inuse: mask of which irqs are connected + * @regs: irq regs we are faking * @lock: protect the evgen state */ struct iio_dummy_eventgen { @@ -40,6 +41,7 @@ struct iio_dummy_eventgen { int base; bool enabled[IIO_EVENTGEN_NO]; bool inuse[IIO_EVENTGEN_NO]; + struct iio_dummy_regs regs[IIO_EVENTGEN_NO]; struct mutex lock; }; @@ -136,6 +138,12 @@ int iio_dummy_evgen_release_irq(int irq) } EXPORT_SYMBOL_GPL(iio_dummy_evgen_release_irq); +struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq) +{ + return &iio_evgen->regs[irq - iio_evgen->base]; +} +EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_regs); + static void iio_dummy_evgen_free(void) { irq_free_descs(iio_evgen->base, IIO_EVENTGEN_NO); @@ -153,6 +161,15 @@ static ssize_t iio_evgen_poke(struct device *dev, size_t len) { struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); + unsigned long event; + int ret; + + ret = kstrtoul(buf, 10, &event); + if (ret) + return ret; + + iio_evgen->regs[this_attr->address].reg_id = this_attr->address; + iio_evgen->regs[this_attr->address].reg_data = event; if (iio_evgen->enabled[this_attr->address]) handle_nested_irq(iio_evgen->base + this_attr->address); diff --git a/drivers/staging/iio/iio_dummy_evgen.h b/drivers/staging/iio/iio_dummy_evgen.h index 3a18081..2ac293a 100644 --- a/drivers/staging/iio/iio_dummy_evgen.h +++ b/drivers/staging/iio/iio_dummy_evgen.h @@ -1,6 +1,12 @@ #ifndef _IIO_DUMMY_EVGEN_H_ #define _IIO_DUMMY_EVGEN_H_ +struct iio_dummy_regs { + u32 reg_id; + u32 reg_data; +}; + +struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq); int iio_dummy_evgen_get_irq(void); int iio_dummy_evgen_release_irq(int irq); diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h index 3027aed..ad89842 100644 --- a/drivers/staging/iio/iio_simple_dummy.h +++ b/drivers/staging/iio/iio_simple_dummy.h @@ -13,6 +13,7 @@ #include struct iio_dummy_accel_calibscale; +struct iio_dummy_regs; /** * struct iio_dummy_state - device instance specific state. @@ -35,6 +36,7 @@ struct iio_dummy_state { int accel_calibbias; const struct iio_dummy_accel_calibscale *accel_calibscale; struct mutex lock; + struct iio_dummy_regs *regs; #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS int event_irq; int event_val; diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c index 64b45b0..719dfa5 100644 --- a/drivers/staging/iio/iio_simple_dummy_events.c +++ b/drivers/staging/iio/iio_simple_dummy_events.c @@ -148,12 +148,23 @@ int iio_simple_dummy_write_event_value(struct iio_dev *indio_dev, static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) { struct iio_dev *indio_dev = private; + struct iio_dummy_state *st = iio_priv(indio_dev); + + dev_dbg(&indio_dev->dev, "id %x event %x\n", + st->regs->reg_id, st->regs->reg_data); + + switch (st->regs->reg_data) { + case 0: + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, + IIO_EV_DIR_RISING, + IIO_EV_TYPE_THRESH, 0, 0, 0), + iio_get_time_ns()); + break; + default: + break; + } - iio_push_event(indio_dev, - IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0, - IIO_EV_DIR_RISING, - IIO_EV_TYPE_THRESH, 0, 0, 0), - iio_get_time_ns()); return IRQ_HANDLED; } @@ -179,6 +190,8 @@ int iio_simple_dummy_events_register(struct iio_dev *indio_dev) ret = st->event_irq; goto error_ret; } + st->regs = iio_dummy_evgen_get_regs(st->event_irq); + ret = request_threaded_irq(st->event_irq, NULL, &iio_simple_dummy_event_handler, -- cgit v0.10.2 From 55aebeb926b6f93a540328e7ac770ef536b09b77 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 10 Nov 2014 14:45:30 +0200 Subject: iio: core: Introduce IIO_ACTIVITY channel This channel will be used for exposing information about activity composite sensors. Activities supported so far: * running * jogging * walking * still THRESHOLD event is used to signal a change in the activity state. We associate a confidence interval for each activity expressed as a percentage from 0 to 100. * 0, means the sensor IS NOT reporting that activity. * 100, means the sensor IS reporting that activity. Users of this interface have two possible means to gather information about the ongoing activities. 1. Event based, via event file descriptor * sensor may report an event when ENTERING an activity or LEAVING an activity based on a threshold value. * drivers will wake up applications waiting data on the event fd 2. Polling, by reading the sysfs associated attribute files: * /sys/bus/iio/devices/iio:device0/in_activity_running_input expressed as percentage confidence value from 0 to 100. This will offer an interface for Android significant motion composite sensor defined here: http://source.android.com/devices/sensors/composite_sensors.html Activities listed above are supported by Freescale's MMA9553 sensor: http://freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 117521d..7bf49ad 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -790,6 +790,40 @@ Description: met before an event is generated. If direction is not specified then this period applies to both directions. +What: /sys/.../events/in_activity_still_thresh_rising_en +What: /sys/.../events/in_activity_still_thresh_falling_en +What: /sys/.../events/in_activity_walking_thresh_rising_en +What: /sys/.../events/in_activity_walking_thresh_falling_en +What: /sys/.../events/in_activity_jogging_thresh_rising_en +What: /sys/.../events/in_activity_jogging_thresh_falling_en +What: /sys/.../events/in_activity_running_thresh_rising_en +What: /sys/.../events/in_activity_running_thresh_falling_en +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Enables or disables activitity events. Depending on direction + an event is generated when sensor ENTERS or LEAVES a given state. + +What: /sys/.../events/in_activity_still_thresh_rising_value +What: /sys/.../events/in_activity_still_thresh_falling_value +What: /sys/.../events/in_activity_walking_thresh_rising_value +What: /sys/.../events/in_activity_walking_thresh_falling_value +What: /sys/.../events/in_activity_jogging_thresh_rising_value +What: /sys/.../events/in_activity_jogging_thresh_falling_value +What: /sys/.../events/in_activity_running_thresh_rising_value +What: /sys/.../events/in_activity_running_thresh_falling_value +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Confidence value (in units as percentage) to be used + for deciding when an event should be generated. E.g for + running: If the confidence value reported by the sensor + is greater than in_activity_running_thresh_rising_value + then the sensor ENTERS running state. Conversely, if the + confidence value reported by the sensor is lower than + in_activity_running_thresh_falling_value then the sensor + is LEAVING running state. + What: /sys/.../iio:deviceX/events/in_accel_mag_en What: /sys/.../iio:deviceX/events/in_accel_mag_rising_en What: /sys/.../iio:deviceX/events/in_accel_mag_falling_en @@ -956,6 +990,16 @@ Description: and the relevant _type attributes to establish the data storage format. +What: /sys/.../iio:deviceX/in_activity_still_input +What: /sys/.../iio:deviceX/in_activity_walking_input +What: /sys/.../iio:deviceX/in_activity_jogging_input +What: /sys/.../iio:deviceX/in_activity_running_input +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + This attribute is used to read the confidence for an activity + expressed in units as percentage. + What: /sys/.../iio:deviceX/in_anglvel_z_quadrature_correction_raw KernelVersion: 2.6.38 Contact: linux-iio@vger.kernel.org diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index af3e76d..e453ef9 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -70,6 +70,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CCT] = "cct", [IIO_PRESSURE] = "pressure", [IIO_HUMIDITYRELATIVE] = "humidityrelative", + [IIO_ACTIVITY] = "activity", }; static const char * const iio_modifier_names[] = { @@ -91,6 +92,10 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_NORTH_TRUE] = "from_north_true", [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp", [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp", + [IIO_MOD_RUNNING] = "running", + [IIO_MOD_JOGGING] = "jogging", + [IIO_MOD_WALKING] = "walking", + [IIO_MOD_STILL] = "still", }; /* relies on pairs of these shared then separate */ diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 4a2af8a..b3a241d 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -30,6 +30,7 @@ enum iio_chan_type { IIO_CCT, IIO_PRESSURE, IIO_HUMIDITYRELATIVE, + IIO_ACTIVITY, }; enum iio_modifier { @@ -59,7 +60,11 @@ enum iio_modifier { IIO_MOD_NORTH_MAGN, IIO_MOD_NORTH_TRUE, IIO_MOD_NORTH_MAGN_TILT_COMP, - IIO_MOD_NORTH_TRUE_TILT_COMP + IIO_MOD_NORTH_TRUE_TILT_COMP, + IIO_MOD_RUNNING, + IIO_MOD_JOGGING, + IIO_MOD_WALKING, + IIO_MOD_STILL, }; enum iio_event_type { -- cgit v0.10.2 From 1843c2f3def16740eb6d129a9790c32dd21aa5ea Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 10 Nov 2014 14:45:31 +0200 Subject: iio: core: Introduce IIO_EV_DIR_NONE For some events (e.g.: step detector) a direction does not make sense. Add IIO_EV_DIR_NONE to be used with such events and generate sysfs event attributes that do not contain direction. Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 0c1e37e..1290290 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -327,9 +327,15 @@ static int iio_device_add_event(struct iio_dev *indio_dev, for_each_set_bit(i, mask, sizeof(*mask)*8) { if (i >= ARRAY_SIZE(iio_ev_info_text)) return -EINVAL; - postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", - iio_ev_type_text[type], iio_ev_dir_text[dir], - iio_ev_info_text[i]); + if (dir != IIO_EV_DIR_NONE) + postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", + iio_ev_type_text[type], + iio_ev_dir_text[dir], + iio_ev_info_text[i]); + else + postfix = kasprintf(GFP_KERNEL, "%s_%s", + iio_ev_type_text[type], + iio_ev_info_text[i]); if (postfix == NULL) return -ENOMEM; diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index b3a241d..52cb532 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -86,6 +86,7 @@ enum iio_event_direction { IIO_EV_DIR_EITHER, IIO_EV_DIR_RISING, IIO_EV_DIR_FALLING, + IIO_EV_DIR_NONE, }; #define IIO_VAL_INT 1 -- cgit v0.10.2 From a88bfe78583026eb9f21d4014ba481b22b66cee3 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 10 Nov 2014 14:45:32 +0200 Subject: iio: core: Introduce STEPS channel, ENABLE mask and INSTANCE event These changes are needed to support the functionality of a pedometer. A pedometer has two basic functionalities: step counter and step detector. The step counter needs to be enabled and then it will count the steps in its hardware register. Whenever the application needs to check the step count, it will read the step counter register. To support the step counter a new channel type STEPS is added. Since the pedometer needs to be enabled first so that the hardware can count and store the steps, we need a specific ENABLE channel info mask. The step detector will generate an interrupt each time a step is detected. To support this functionality we add a new event type INSTANCE. For more information on the Android requirements for step counter and step detector see: http://source.android.com/devices/sensors/composite_sensors.html#counter and http://source.android.com/devices/sensors/composite_sensors.html#detector. A device that has the pedometer functionality this interface needs to support is Freescale's MMA9553L: http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 7bf49ad..c60b0a1 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -856,6 +856,13 @@ Description: number or direction is not specified, applies to all channels of this type. +What: /sys/.../events/in_steps_instance_en +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Enables or disables step detection. Each time the user takes a step an + event of this type will be generated. + What: /sys/bus/iio/devices/iio:deviceX/trigger/current_trigger KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org @@ -1095,3 +1102,18 @@ Description: after application of scale and offset. If no offset or scale is present, output should be considered as processed with the unit in milliamps. + +What: /sys/.../iio:deviceX/in_steps_en +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Activates the step counter. After activation, the number of steps + taken by the user will be counted in hardware and exported through + in_steps_input. + +What: /sys/.../iio:deviceX/in_steps_input +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + This attribute is used to read the number of steps taken by the user + since the last reboot while activated. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index e453ef9..1e060f3 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -71,6 +71,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_PRESSURE] = "pressure", [IIO_HUMIDITYRELATIVE] = "humidityrelative", [IIO_ACTIVITY] = "activity", + [IIO_STEPS] = "steps", }; static const char * const iio_modifier_names[] = { @@ -118,6 +119,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain", [IIO_CHAN_INFO_HYSTERESIS] = "hysteresis", [IIO_CHAN_INFO_INT_TIME] = "integration_time", + [IIO_CHAN_INFO_ENABLE] = "en", }; /** diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 1290290..3f5cee0 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -197,6 +197,7 @@ static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_ROC] = "roc", [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", + [IIO_EV_TYPE_INSTANCE] = "instance", }; static const char * const iio_ev_dir_text[] = { diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 3642ce7..f45a400 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -38,6 +38,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_HARDWAREGAIN, IIO_CHAN_INFO_HYSTERESIS, IIO_CHAN_INFO_INT_TIME, + IIO_CHAN_INFO_ENABLE, }; enum iio_shared_by { diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 52cb532..904dcbb 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -31,6 +31,7 @@ enum iio_chan_type { IIO_PRESSURE, IIO_HUMIDITYRELATIVE, IIO_ACTIVITY, + IIO_STEPS, }; enum iio_modifier { @@ -73,6 +74,7 @@ enum iio_event_type { IIO_EV_TYPE_ROC, IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_TYPE_MAG_ADAPTIVE, + IIO_EV_TYPE_INSTANCE, }; enum iio_event_info { -- cgit v0.10.2 From bcdf28fb1b8badf3cdba18d349f6251057e36a45 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Mon, 10 Nov 2014 14:45:33 +0200 Subject: iio: core: Introduce IIO_CHAN_INFO_CALIBHEIGHT Some devices need the height of the user to compute various parameters. One of this devices is Freescale's MMA9553L (http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf) that needs the height of the user to compute the stride length which is used further to determine distance, speed and activity type. Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index c60b0a1..4a9e29a 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -323,6 +323,14 @@ Description: production inaccuracies). If shared across all channels, _calibscale is used. +What: /sys/bus/iio/devices/iio:deviceX/in_steps_calibheight +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + Height of the user (in centimeters) used by some pedometers + to compute the stride length, distance, speed and activity + type. + What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale_available What: /sys/.../iio:deviceX/in_voltageX_scale_available What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 1e060f3..45bb3a4 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -120,6 +120,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_HYSTERESIS] = "hysteresis", [IIO_CHAN_INFO_INT_TIME] = "integration_time", [IIO_CHAN_INFO_ENABLE] = "en", + [IIO_CHAN_INFO_CALIBHEIGHT] = "calibheight", }; /** diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index f45a400..878d861 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -39,6 +39,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_HYSTERESIS, IIO_CHAN_INFO_INT_TIME, IIO_CHAN_INFO_ENABLE, + IIO_CHAN_INFO_CALIBHEIGHT, }; enum iio_shared_by { -- cgit v0.10.2 From 3e34e650db19708b1c27421e8d3d749a09adbb0c Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 10 Nov 2014 14:45:34 +0200 Subject: iio: dummy: Demonstrate the usage of new channel types Adds support for the new channel types in the dummy driver: * a new channel IIO_ACTIVITY * two state transition events (running and walking) * a new channel IIO_STEPS and support for reading and writing pedometer step counter * step detect event * a new IIO_CHAN_INFO_CALIBHEIGHT mask bit for reading and writing user's height. Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index bf78e6f..10a9e08 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -69,6 +69,34 @@ static const struct iio_event_spec iio_dummy_event = { .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), }; +/* + * simple step detect event - triggered when a step is detected + */ +static const struct iio_event_spec step_detect_event = { + .type = IIO_EV_TYPE_INSTANCE, + .dir = IIO_EV_DIR_NONE, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), +}; + +/* + * simple transition event - triggered when the reported running confidence + * value rises above a threshold value + */ +static const struct iio_event_spec iio_running_event = { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), +}; + +/* + * simple transition event - triggered when the reported walking confidence + * value falls under a threshold value + */ +static const struct iio_event_spec iio_walking_event = { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), +}; #endif /* @@ -215,6 +243,37 @@ static const struct iio_chan_spec iio_dummy_channels[] = { .indexed = 1, .channel = 0, }, + { + .type = IIO_STEPS, + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_ENABLE) | + BIT(IIO_CHAN_INFO_CALIBHEIGHT), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = -1, +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + .event_spec = &step_detect_event, + .num_event_specs = 1, +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ + }, + { + .type = IIO_ACTIVITY, + .modified = 1, + .channel2 = IIO_MOD_RUNNING, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + .event_spec = &iio_running_event, + .num_event_specs = 1, +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ + }, + { + .type = IIO_ACTIVITY, + .modified = 1, + .channel2 = IIO_MOD_WALKING, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), +#ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS + .event_spec = &iio_walking_event, + .num_event_specs = 1, +#endif /* CONFIG_IIO_SIMPLE_DUMMY_EVENTS */ + }, }; /** @@ -263,24 +322,55 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, break; } break; + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_STEPS: + *val = st->steps; + ret = IIO_VAL_INT; + break; + case IIO_ACTIVITY: + switch (chan->channel2) { + case IIO_MOD_RUNNING: + *val = st->activity_running; + ret = IIO_VAL_INT; + break; + case IIO_MOD_WALKING: + *val = st->activity_walking; + ret = IIO_VAL_INT; + break; + default: + break; + } + break; + default: + break; + } + break; case IIO_CHAN_INFO_OFFSET: /* only single ended adc -> 7 */ *val = 7; ret = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: - switch (chan->differential) { - case 0: - /* only single ended adc -> 0.001333 */ - *val = 0; - *val2 = 1333; - ret = IIO_VAL_INT_PLUS_MICRO; + switch (chan->type) { + case IIO_VOLTAGE: + switch (chan->differential) { + case 0: + /* only single ended adc -> 0.001333 */ + *val = 0; + *val2 = 1333; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + case 1: + /* all differential adc channels -> + * 0.000001344 */ + *val = 0; + *val2 = 1344; + ret = IIO_VAL_INT_PLUS_NANO; + } + break; + default: break; - case 1: - /* all differential adc channels -> 0.000001344 */ - *val = 0; - *val2 = 1344; - ret = IIO_VAL_INT_PLUS_NANO; } break; case IIO_CHAN_INFO_CALIBBIAS: @@ -298,6 +388,27 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, *val2 = 33; ret = IIO_VAL_INT_PLUS_NANO; break; + case IIO_CHAN_INFO_ENABLE: + switch (chan->type) { + case IIO_STEPS: + *val = st->steps_enabled; + ret = IIO_VAL_INT; + break; + default: + break; + } + break; + case IIO_CHAN_INFO_CALIBHEIGHT: + switch (chan->type) { + case IIO_STEPS: + *val = st->height; + ret = IIO_VAL_INT; + break; + default: + break; + } + break; + default: break; } @@ -330,14 +441,45 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - if (chan->output == 0) + switch (chan->type) { + case IIO_VOLTAGE: + if (chan->output == 0) + return -EINVAL; + + /* Locking not required as writing single value */ + mutex_lock(&st->lock); + st->dac_val = val; + mutex_unlock(&st->lock); + return 0; + default: return -EINVAL; - - /* Locking not required as writing single value */ - mutex_lock(&st->lock); - st->dac_val = val; - mutex_unlock(&st->lock); - return 0; + } + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_STEPS: + mutex_lock(&st->lock); + st->steps = val; + mutex_unlock(&st->lock); + return 0; + case IIO_ACTIVITY: + if (val < 0) + val = 0; + if (val > 100) + val = 100; + switch (chan->channel2) { + case IIO_MOD_RUNNING: + st->activity_running = val; + return 0; + case IIO_MOD_WALKING: + st->activity_walking = val; + return 0; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } case IIO_CHAN_INFO_CALIBSCALE: mutex_lock(&st->lock); /* Compare against table - hard matching here */ @@ -356,6 +498,24 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, st->accel_calibbias = val; mutex_unlock(&st->lock); return 0; + case IIO_CHAN_INFO_ENABLE: + switch (chan->type) { + case IIO_STEPS: + mutex_lock(&st->lock); + st->steps_enabled = val; + mutex_unlock(&st->lock); + return 0; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_CALIBHEIGHT: + switch (chan->type) { + case IIO_STEPS: + st->height = val; + return 0; + default: + return -EINVAL; + } default: return -EINVAL; @@ -395,6 +555,9 @@ static int iio_dummy_init_device(struct iio_dev *indio_dev) st->accel_val = 34; st->accel_calibbias = -7; st->accel_calibscale = &dummy_scales[0]; + st->steps = 47; + st->activity_running = 98; + st->activity_walking = 4; return 0; } diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h index ad89842..3b714b4 100644 --- a/drivers/staging/iio/iio_simple_dummy.h +++ b/drivers/staging/iio/iio_simple_dummy.h @@ -34,9 +34,14 @@ struct iio_dummy_state { int differential_adc_val[2]; int accel_val; int accel_calibbias; + int activity_running; + int activity_walking; const struct iio_dummy_accel_calibscale *accel_calibscale; struct mutex lock; struct iio_dummy_regs *regs; + int steps_enabled; + int steps; + int height; #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS int event_irq; int event_val; diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c index 719dfa5..ac15a44 100644 --- a/drivers/staging/iio/iio_simple_dummy_events.c +++ b/drivers/staging/iio/iio_simple_dummy_events.c @@ -72,6 +72,22 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, st->event_en = state; else return -EINVAL; + default: + return -EINVAL; + } + break; + case IIO_ACTIVITY: + switch (type) { + case IIO_EV_TYPE_THRESH: + st->event_en = state; + break; + default: + return -EINVAL; + } + case IIO_STEPS: + switch (type) { + case IIO_EV_TYPE_INSTANCE: + st->event_en = state; break; default: return -EINVAL; @@ -161,6 +177,33 @@ static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) IIO_EV_TYPE_THRESH, 0, 0, 0), iio_get_time_ns()); break; + case 1: + if (st->activity_running > st->event_val) + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_ACTIVITY, 0, + IIO_MOD_RUNNING, + IIO_EV_DIR_RISING, + IIO_EV_TYPE_THRESH, + 0, 0, 0), + iio_get_time_ns()); + break; + case 2: + if (st->activity_walking < st->event_val) + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_ACTIVITY, 0, + IIO_MOD_WALKING, + IIO_EV_DIR_FALLING, + IIO_EV_TYPE_THRESH, + 0, 0, 0), + iio_get_time_ns()); + break; + case 3: + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, + IIO_EV_DIR_NONE, + IIO_EV_TYPE_INSTANCE, 0, 0, 0), + iio_get_time_ns()); + break; default: break; } -- cgit v0.10.2 From 282a5663930ba79af9ec38884580c140fedf8aaa Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Mon, 10 Nov 2014 14:45:35 +0200 Subject: iio: event_monitor: Add support for new channel types We have the following testing scenario: $ insmod iio_dummy_evgen.ko $ insmod iio_dummy.ko ./iio_event_monitor /dev/iio:device0 Event: time: 1412786467971335337, type: activity(running), channel: 0, evtype: thresh, direction: rising Event: time: 1412786530792974091, type: activity(walking), channel: 0, evtype: thresh, direction: falling Event: time: 1412764319184761765, type: steps, channel: 0, evtype: instance $ echo 1 > /sys/bus/iio/devices/iio_evgen/poke_ev0 $ echo 2 > /sys/bus/iio/devices/iio_evgen/poke_ev0 $ echo 3 > /sys/bus/iio/devices/iio_evgen/poke_ev0 Signed-off-by: Irina Tirdea Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c index 940ed23..def236a 100644 --- a/drivers/staging/iio/Documentation/iio_event_monitor.c +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -49,6 +49,8 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_CCT] = "cct", [IIO_PRESSURE] = "pressure", [IIO_HUMIDITYRELATIVE] = "humidityrelative", + [IIO_ACTIVITY] = "activity", + [IIO_STEPS] = "steps", }; static const char * const iio_ev_type_text[] = { @@ -57,6 +59,7 @@ static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_ROC] = "roc", [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", + [IIO_EV_TYPE_INSTANCE] = "instance", }; static const char * const iio_ev_dir_text[] = { @@ -92,6 +95,10 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_NORTH_TRUE] = "from_north_true", [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp", [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp", + [IIO_MOD_RUNNING] = "running", + [IIO_MOD_JOGGING] = "jogging", + [IIO_MOD_WALKING] = "walking", + [IIO_MOD_STILL] = "still", }; static bool event_is_known(struct iio_event_data *event) @@ -121,6 +128,8 @@ static bool event_is_known(struct iio_event_data *event) case IIO_CCT: case IIO_PRESSURE: case IIO_HUMIDITYRELATIVE: + case IIO_ACTIVITY: + case IIO_STEPS: break; default: return false; @@ -154,6 +163,10 @@ static bool event_is_known(struct iio_event_data *event) case IIO_MOD_NORTH_TRUE: case IIO_MOD_NORTH_MAGN_TILT_COMP: case IIO_MOD_NORTH_TRUE_TILT_COMP: + case IIO_MOD_RUNNING: + case IIO_MOD_JOGGING: + case IIO_MOD_WALKING: + case IIO_MOD_STILL: break; default: return false; @@ -165,6 +178,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_EV_TYPE_ROC: case IIO_EV_TYPE_THRESH_ADAPTIVE: case IIO_EV_TYPE_MAG_ADAPTIVE: + case IIO_EV_TYPE_INSTANCE: break; default: return false; @@ -174,6 +188,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_EV_DIR_EITHER: case IIO_EV_DIR_RISING: case IIO_EV_DIR_FALLING: + case IIO_EV_DIR_NONE: break; default: return false; @@ -214,9 +229,11 @@ static void print_event(struct iio_event_data *event) else if (chan >= 0) printf("channel: %d, ", chan); - printf("evtype: %s, direction: %s\n", - iio_ev_type_text[ev_type], - iio_ev_dir_text[dir]); + printf("evtype: %s", iio_ev_type_text[ev_type]); + + if (dir != IIO_EV_DIR_NONE) + printf(", direction: %s", iio_ev_dir_text[dir]); + printf("\n"); } int main(int argc, char **argv) -- cgit v0.10.2 From 56ae98a20591fcb45c6161fc80cf213e47b8ac04 Mon Sep 17 00:00:00 2001 From: Zachary Warren Date: Sat, 22 Nov 2014 22:19:31 +1100 Subject: drivers:staging:iio: fix checkpatch complaint about space before comma Fixes: drivers/staging/iio/adc/ad7192.c:615: ERROR: space prohibited before that ',' drivers/staging/iio/meter/ade7759.c:119: ERROR: space prohibited before that ',' Signed-off-by: Zachary Warren Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index f6526aa..6f8ce6c 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -612,7 +612,7 @@ static int ad7192_probe(struct spi_device *spi) const struct ad7192_platform_data *pdata = spi->dev.platform_data; struct ad7192_state *st; struct iio_dev *indio_dev; - int ret , voltage_uv = 0; + int ret, voltage_uv = 0; if (!pdata) { dev_err(&spi->dev, "no platform data?\n"); diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index 7d21743..b0c7dbc 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -116,7 +116,7 @@ static int ade7759_spi_read_reg_40(struct device *dev, mutex_lock(&st->buf_lock); st->tx[0] = ADE7759_READ_REG(reg_address); - memset(&st->tx[1], 0 , 5); + memset(&st->tx[1], 0, 5); ret = spi_sync_transfer(st->us, xfers, ARRAY_SIZE(xfers)); if (ret) { -- cgit v0.10.2 From 71222bf5412c78d96bf73d09475d3077ce0789f8 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 21 Nov 2014 10:45:47 -0800 Subject: iio: ak8975: minor fixes Fixes code duplication, return of function. Check client->irq properly when setting up optional irq handler. Signed-off-by: Gwendal Grignou Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index bf5ef07..4e69480 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -64,10 +64,10 @@ #define AK8975_REG_CNTL 0x0A #define AK8975_REG_CNTL_MODE_SHIFT 0 #define AK8975_REG_CNTL_MODE_MASK (0xF << AK8975_REG_CNTL_MODE_SHIFT) -#define AK8975_REG_CNTL_MODE_POWER_DOWN 0 -#define AK8975_REG_CNTL_MODE_ONCE 1 -#define AK8975_REG_CNTL_MODE_SELF_TEST 8 -#define AK8975_REG_CNTL_MODE_FUSE_ROM 0xF +#define AK8975_REG_CNTL_MODE_POWER_DOWN 0x00 +#define AK8975_REG_CNTL_MODE_ONCE 0x01 +#define AK8975_REG_CNTL_MODE_SELF_TEST 0x08 +#define AK8975_REG_CNTL_MODE_FUSE_ROM 0x0F #define AK8975_REG_RSVC 0x0B #define AK8975_REG_ASTC 0x0C @@ -166,8 +166,8 @@ static int ak8975_setup_irq(struct ak8975_data *data) irq = gpio_to_irq(data->eoc_gpio); rc = devm_request_irq(&client->dev, irq, ak8975_irq_handler, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - dev_name(&client->dev), data); + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + dev_name(&client->dev), data); if (rc < 0) { dev_err(&client->dev, "irq %d request failed, (gpio %d): %d\n", @@ -231,8 +231,12 @@ static int ak8975_setup(struct i2c_client *client) AK8975_REG_CNTL_MODE_POWER_DOWN, AK8975_REG_CNTL_MODE_MASK, AK8975_REG_CNTL_MODE_SHIFT); + if (ret < 0) { + dev_err(&client->dev, "Error in setting power-down mode\n"); + return ret; + } - if (data->eoc_gpio > 0 || client->irq) { + if (data->eoc_gpio > 0 || client->irq > 0) { ret = ak8975_setup_irq(data); if (ret < 0) { dev_err(&client->dev, @@ -241,11 +245,6 @@ static int ak8975_setup(struct i2c_client *client) } } - if (ret < 0) { - dev_err(&client->dev, "Error in setting power-down mode\n"); - return ret; - } - /* * Precalculate scale factor (in Gauss units) for each axis and * store in the device data. @@ -550,24 +549,18 @@ static int ak8975_probe(struct i2c_client *client, /* Perform some basic start-of-day setup of the device. */ err = ak8975_setup(client); if (err < 0) { - dev_err(&client->dev, "AK8975 initialization fails\n"); + dev_err(&client->dev, "%s initialization fails\n", name); return err; } - data->client = client; mutex_init(&data->lock); - data->eoc_gpio = eoc_gpio; indio_dev->dev.parent = &client->dev; indio_dev->channels = ak8975_channels; indio_dev->num_channels = ARRAY_SIZE(ak8975_channels); indio_dev->info = &ak8975_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->name = name; - err = devm_iio_device_register(&client->dev, indio_dev); - if (err < 0) - return err; - - return 0; + return devm_iio_device_register(&client->dev, indio_dev); } static const struct i2c_device_id ak8975_id[] = { @@ -588,7 +581,7 @@ MODULE_DEVICE_TABLE(of, ak8975_of_match); static struct i2c_driver ak8975_driver = { .driver = { .name = "ak8975", - .of_match_table = ak8975_of_match, + .of_match_table = of_match_ptr(ak8975_of_match), .acpi_match_table = ACPI_PTR(ak_acpi_match), }, .probe = ak8975_probe, -- cgit v0.10.2 From 286f74c2533ac44419819bb3c885ab9f6291d2c3 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 21 Nov 2014 10:45:48 -0800 Subject: iio: ak8975: add definition structure per compass type For each type of compass supported (AK8975 and AK8963), add a definition structure for register masks, important registers, raw data interpretation. This change will make integrating new type of devices easier. Remove i2c register cache. It is only used for one single register. Signed-off-by: Gwendal Grignou Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 4e69480..0f86a8e 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -86,13 +86,155 @@ #define AK8975_MAX_CONVERSION_TIMEOUT 500 #define AK8975_CONVERSION_DONE_POLL_TIME 10 #define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000) -#define RAW_TO_GAUSS_8975(asa) ((((asa) + 128) * 3000) / 256) -#define RAW_TO_GAUSS_8963(asa) ((((asa) + 128) * 6000) / 256) + +/* + * Precalculate scale factor (in Gauss units) for each axis and + * store in the device data. + * + * This scale factor is axis-dependent, and is derived from 3 calibration + * factors ASA(x), ASA(y), and ASA(z). + * + * These ASA values are read from the sensor device at start of day, and + * cached in the device context struct. + * + * Adjusting the flux value with the sensitivity adjustment value should be + * done via the following formula: + * + * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 ) + * where H is the raw value, ASA is the sensitivity adjustment, and Hadj + * is the resultant adjusted value. + * + * We reduce the formula to: + * + * Hadj = H * (ASA + 128) / 256 + * + * H is in the range of -4096 to 4095. The magnetometer has a range of + * +-1229uT. To go from the raw value to uT is: + * + * HuT = H * 1229/4096, or roughly, 3/10. + * + * Since 1uT = 0.01 gauss, our final scale factor becomes: + * + * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100 + * Hadj = H * ((ASA + 128) * 0.003) / 256 + * + * Since ASA doesn't change, we cache the resultant scale factor into the + * device context in ak8975_setup(). + * + * Given we use IIO_VAL_INT_PLUS_MICRO bit when displaying the scale, we + * multiply the stored scale value by 1e6. + */ +static long ak8975_raw_to_gauss(u16 data) +{ + return (((long)data + 128) * 3000) / 256; +} + +/* + * For AK8963, same calculation, but the device is less sensitive: + * + * H is in the range of +-8190. The magnetometer has a range of + * +-4912uT. To go from the raw value to uT is: + * + * HuT = H * 4912/8190, or roughly, 6/10, instead of 3/10. + */ +static long ak8963_raw_to_gauss(u16 data) +{ + return (((long)data + 128) * 6000) / 256; +} /* Compatible Asahi Kasei Compass parts */ enum asahi_compass_chipset { AK8975, AK8963, + AK_MAX_TYPE +}; + +enum ak_ctrl_reg_addr { + ST1, + ST2, + CNTL, + ASA_BASE, + MAX_REGS, + REGS_END, +}; + +enum ak_ctrl_reg_mask { + ST1_DRDY, + ST2_HOFL, + ST2_DERR, + CNTL_MODE, + MASK_END, +}; + +enum ak_ctrl_mode { + POWER_DOWN, + MODE_ONCE, + SELF_TEST, + FUSE_ROM, + MODE_END, +}; + +struct ak_def { + enum asahi_compass_chipset type; + long (*raw_to_gauss)(u16 data); + u16 range; + u8 ctrl_regs[REGS_END]; + u8 ctrl_masks[MASK_END]; + u8 ctrl_modes[MODE_END]; + u8 data_regs[3]; +}; + +static struct ak_def ak_def_array[AK_MAX_TYPE] = { + { + .type = AK8975, + .raw_to_gauss = ak8975_raw_to_gauss, + .range = 4096, + .ctrl_regs = { + AK8975_REG_ST1, + AK8975_REG_ST2, + AK8975_REG_CNTL, + AK8975_REG_ASAX, + AK8975_MAX_REGS}, + .ctrl_masks = { + AK8975_REG_ST1_DRDY_MASK, + AK8975_REG_ST2_HOFL_MASK, + AK8975_REG_ST2_DERR_MASK, + AK8975_REG_CNTL_MODE_MASK}, + .ctrl_modes = { + AK8975_REG_CNTL_MODE_POWER_DOWN, + AK8975_REG_CNTL_MODE_ONCE, + AK8975_REG_CNTL_MODE_SELF_TEST, + AK8975_REG_CNTL_MODE_FUSE_ROM}, + .data_regs = { + AK8975_REG_HXL, + AK8975_REG_HYL, + AK8975_REG_HZL}, + }, + { + .type = AK8963, + .raw_to_gauss = ak8963_raw_to_gauss, + .range = 8190, + .ctrl_regs = { + AK8975_REG_ST1, + AK8975_REG_ST2, + AK8975_REG_CNTL, + AK8975_REG_ASAX, + AK8975_MAX_REGS}, + .ctrl_masks = { + AK8975_REG_ST1_DRDY_MASK, + AK8975_REG_ST2_HOFL_MASK, + 0, + AK8975_REG_CNTL_MODE_MASK}, + .ctrl_modes = { + AK8975_REG_CNTL_MODE_POWER_DOWN, + AK8975_REG_CNTL_MODE_ONCE, + AK8975_REG_CNTL_MODE_SELF_TEST, + AK8975_REG_CNTL_MODE_FUSE_ROM}, + .data_regs = { + AK8975_REG_HXL, + AK8975_REG_HYL, + AK8975_REG_HZL}, + }, }; /* @@ -100,40 +242,36 @@ enum asahi_compass_chipset { */ struct ak8975_data { struct i2c_client *client; + struct ak_def *def; struct attribute_group attrs; struct mutex lock; u8 asa[3]; long raw_to_gauss[3]; - u8 reg_cache[AK8975_MAX_REGS]; int eoc_gpio; int eoc_irq; wait_queue_head_t data_ready_queue; unsigned long flags; - enum asahi_compass_chipset chipset; -}; - -static const int ak8975_index_to_reg[] = { - AK8975_REG_HXL, AK8975_REG_HYL, AK8975_REG_HZL, + u8 cntl_cache; }; /* - * Helper function to write to the I2C device's registers. + * Helper function to write to CNTL register. */ -static int ak8975_write_data(struct i2c_client *client, - u8 reg, u8 val, u8 mask, u8 shift) +static int ak8975_set_mode(struct ak8975_data *data, enum ak_ctrl_mode mode) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ak8975_data *data = iio_priv(indio_dev); u8 regval; int ret; - regval = (data->reg_cache[reg] & ~mask) | (val << shift); - ret = i2c_smbus_write_byte_data(client, reg, regval); + regval = (data->cntl_cache & ~data->def->ctrl_masks[CNTL_MODE]) | + data->def->ctrl_modes[mode]; + ret = i2c_smbus_write_byte_data(data->client, + data->def->ctrl_regs[CNTL], regval); if (ret < 0) { - dev_err(&client->dev, "Write to device fails status %x\n", ret); return ret; } - data->reg_cache[reg] = regval; + data->cntl_cache = regval; + /* After mode change wait atleast 100us */ + usleep_range(100, 500); return 0; } @@ -207,18 +345,15 @@ static int ak8975_setup(struct i2c_client *client) } /* Write the fused rom access mode. */ - ret = ak8975_write_data(client, - AK8975_REG_CNTL, - AK8975_REG_CNTL_MODE_FUSE_ROM, - AK8975_REG_CNTL_MODE_MASK, - AK8975_REG_CNTL_MODE_SHIFT); + ret = ak8975_set_mode(data, FUSE_ROM); if (ret < 0) { dev_err(&client->dev, "Error in setting fuse access mode\n"); return ret; } /* Get asa data and store in the device data. */ - ret = i2c_smbus_read_i2c_block_data(client, AK8975_REG_ASAX, + ret = i2c_smbus_read_i2c_block_data(client, + data->def->ctrl_regs[ASA_BASE], 3, data->asa); if (ret < 0) { dev_err(&client->dev, "Not able to read asa data\n"); @@ -226,11 +361,7 @@ static int ak8975_setup(struct i2c_client *client) } /* After reading fuse ROM data set power-down mode */ - ret = ak8975_write_data(client, - AK8975_REG_CNTL, - AK8975_REG_CNTL_MODE_POWER_DOWN, - AK8975_REG_CNTL_MODE_MASK, - AK8975_REG_CNTL_MODE_SHIFT); + ret = ak8975_set_mode(data, POWER_DOWN); if (ret < 0) { dev_err(&client->dev, "Error in setting power-down mode\n"); return ret; @@ -245,56 +376,9 @@ static int ak8975_setup(struct i2c_client *client) } } -/* - * Precalculate scale factor (in Gauss units) for each axis and - * store in the device data. - * - * This scale factor is axis-dependent, and is derived from 3 calibration - * factors ASA(x), ASA(y), and ASA(z). - * - * These ASA values are read from the sensor device at start of day, and - * cached in the device context struct. - * - * Adjusting the flux value with the sensitivity adjustment value should be - * done via the following formula: - * - * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 ) - * - * where H is the raw value, ASA is the sensitivity adjustment, and Hadj - * is the resultant adjusted value. - * - * We reduce the formula to: - * - * Hadj = H * (ASA + 128) / 256 - * - * H is in the range of -4096 to 4095. The magnetometer has a range of - * +-1229uT. To go from the raw value to uT is: - * - * HuT = H * 1229/4096, or roughly, 3/10. - * - * Since 1uT = 0.01 gauss, our final scale factor becomes: - * - * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100 - * Hadj = H * ((ASA + 128) * 0.003) / 256 - * - * Since ASA doesn't change, we cache the resultant scale factor into the - * device context in ak8975_setup(). - */ - if (data->chipset == AK8963) { - /* - * H range is +-8190 and magnetometer range is +-4912. - * So HuT using the above explanation for 8975, - * 4912/8190 = ~ 6/10. - * So the Hadj should use 6/10 instead of 3/10. - */ - data->raw_to_gauss[0] = RAW_TO_GAUSS_8963(data->asa[0]); - data->raw_to_gauss[1] = RAW_TO_GAUSS_8963(data->asa[1]); - data->raw_to_gauss[2] = RAW_TO_GAUSS_8963(data->asa[2]); - } else { - data->raw_to_gauss[0] = RAW_TO_GAUSS_8975(data->asa[0]); - data->raw_to_gauss[1] = RAW_TO_GAUSS_8975(data->asa[1]); - data->raw_to_gauss[2] = RAW_TO_GAUSS_8975(data->asa[2]); - } + data->raw_to_gauss[0] = data->def->raw_to_gauss(data->asa[0]); + data->raw_to_gauss[1] = data->def->raw_to_gauss(data->asa[1]); + data->raw_to_gauss[2] = data->def->raw_to_gauss(data->asa[2]); return 0; } @@ -317,7 +401,7 @@ static int wait_conversion_complete_gpio(struct ak8975_data *data) return -EINVAL; } - ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1); + ret = i2c_smbus_read_byte_data(client, data->def->ctrl_regs[ST1]); if (ret < 0) dev_err(&client->dev, "Error in reading ST1\n"); @@ -334,7 +418,8 @@ static int wait_conversion_complete_polled(struct ak8975_data *data) /* Wait for the conversion to complete. */ while (timeout_ms) { msleep(AK8975_CONVERSION_DONE_POLL_TIME); - ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1); + ret = i2c_smbus_read_byte_data(client, + data->def->ctrl_regs[ST1]); if (ret < 0) { dev_err(&client->dev, "Error in reading ST1\n"); return ret; @@ -377,11 +462,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) mutex_lock(&data->lock); /* Set up the device for taking a sample. */ - ret = ak8975_write_data(client, - AK8975_REG_CNTL, - AK8975_REG_CNTL_MODE_ONCE, - AK8975_REG_CNTL_MODE_MASK, - AK8975_REG_CNTL_MODE_SHIFT); + ret = ak8975_set_mode(data, MODE_ONCE); if (ret < 0) { dev_err(&client->dev, "Error in setting operating mode\n"); goto exit; @@ -398,14 +479,15 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) goto exit; /* This will be executed only for non-interrupt based waiting case */ - if (ret & AK8975_REG_ST1_DRDY_MASK) { - ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST2); + if (ret & data->def->ctrl_masks[ST1_DRDY]) { + ret = i2c_smbus_read_byte_data(client, + data->def->ctrl_regs[ST2]); if (ret < 0) { dev_err(&client->dev, "Error in reading ST2\n"); goto exit; } - if (ret & (AK8975_REG_ST2_DERR_MASK | - AK8975_REG_ST2_HOFL_MASK)) { + if (ret & (data->def->ctrl_masks[ST2_DERR] | + data->def->ctrl_masks[ST2_HOFL])) { dev_err(&client->dev, "ST2 status error 0x%x\n", ret); ret = -EINVAL; goto exit; @@ -414,7 +496,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) /* Read the flux value from the appropriate register (the register is specified in the iio device attributes). */ - ret = i2c_smbus_read_word_data(client, ak8975_index_to_reg[index]); + ret = i2c_smbus_read_word_data(client, data->def->data_regs[index]); if (ret < 0) { dev_err(&client->dev, "Read axis data fails\n"); goto exit; @@ -423,7 +505,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) mutex_unlock(&data->lock); /* Clamp to valid range. */ - *val = clamp_t(s16, ret, -4096, 4095); + *val = clamp_t(s16, ret, -data->def->range, data->def->range); return IIO_VAL_INT; exit: @@ -497,6 +579,7 @@ static int ak8975_probe(struct i2c_client *client, int eoc_gpio; int err; const char *name = NULL; + enum asahi_compass_chipset chipset; /* Grab and set up the supplied GPIO. */ if (client->dev.platform_data) @@ -536,14 +619,20 @@ static int ak8975_probe(struct i2c_client *client, /* id will be NULL when enumerated via ACPI */ if (id) { - data->chipset = - (enum asahi_compass_chipset)(id->driver_data); + chipset = (enum asahi_compass_chipset)(id->driver_data); name = id->name; } else if (ACPI_HANDLE(&client->dev)) - name = ak8975_match_acpi_device(&client->dev, &data->chipset); + name = ak8975_match_acpi_device(&client->dev, &chipset); else return -ENOSYS; + if (chipset >= AK_MAX_TYPE) { + dev_err(&client->dev, "AKM device type unsupported: %d\n", + chipset); + return -ENODEV; + } + + data->def = &ak_def_array[chipset]; dev_dbg(&client->dev, "Asahi compass chip %s\n", name); /* Perform some basic start-of-day setup of the device. */ @@ -574,7 +663,9 @@ MODULE_DEVICE_TABLE(i2c, ak8975_id); static const struct of_device_id ak8975_of_match[] = { { .compatible = "asahi-kasei,ak8975", }, { .compatible = "ak8975", }, - { } + { .compatible = "asahi-kasei,ak8963", }, + { .compatible = "ak8963", }, + {} }; MODULE_DEVICE_TABLE(of, ak8975_of_match); -- cgit v0.10.2 From 57e73a423b1e85f9b1b0f58e10d38ec00d0c8489 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 21 Nov 2014 10:45:49 -0800 Subject: iio: ak8975: add ak09911 and ak09912 support Add 2 new definition entries to support ak0991x compass. Add a more advanced function to check we are dealing with the expected device. Remove standalone driver for ak09911. Signed-off-by: Gwendal Grignou Tested-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index b2dba9e..4c7a4c5 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig @@ -6,26 +6,21 @@ menu "Magnetometer sensors" config AK8975 - tristate "Asahi Kasei AK8975 3-Axis Magnetometer" + tristate "Asahi Kasei AK 3-Axis Magnetometer" depends on I2C depends on GPIOLIB help - Say yes here to build support for Asahi Kasei AK8975 3-Axis - Magnetometer. This driver can also support AK8963, if i2c - device name is identified as ak8963. + Say yes here to build support for Asahi Kasei AK8975, AK8963, + AK09911 or AK09912 3-Axis Magnetometer. To compile this driver as a module, choose M here: the module will be called ak8975. config AK09911 tristate "Asahi Kasei AK09911 3-axis Compass" - depends on I2C + select AK8975 help - Say yes here to build support for Asahi Kasei AK09911 3-Axis - Magnetometer. - - To compile this driver as a module, choose M here: the module - will be called ak09911. + Deprecated: AK09911 is now supported by AK8975 driver. config MAG3110 tristate "Freescale MAG3110 3-Axis Magnetometer" diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile index b91315e..0f5d3c9 100644 --- a/drivers/iio/magnetometer/Makefile +++ b/drivers/iio/magnetometer/Makefile @@ -3,7 +3,6 @@ # # When adding new entries keep the list in alphabetical order -obj-$(CONFIG_AK09911) += ak09911.o obj-$(CONFIG_AK8975) += ak8975.o obj-$(CONFIG_MAG3110) += mag3110.o obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o diff --git a/drivers/iio/magnetometer/ak09911.c b/drivers/iio/magnetometer/ak09911.c deleted file mode 100644 index b2bc942..0000000 --- a/drivers/iio/magnetometer/ak09911.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * AK09911 3-axis compass driver - * Copyright (c) 2014, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define AK09911_REG_WIA1 0x00 -#define AK09911_REG_WIA2 0x01 -#define AK09911_WIA1_VALUE 0x48 -#define AK09911_WIA2_VALUE 0x05 - -#define AK09911_REG_ST1 0x10 -#define AK09911_REG_HXL 0x11 -#define AK09911_REG_HXH 0x12 -#define AK09911_REG_HYL 0x13 -#define AK09911_REG_HYH 0x14 -#define AK09911_REG_HZL 0x15 -#define AK09911_REG_HZH 0x16 - -#define AK09911_REG_ASAX 0x60 -#define AK09911_REG_ASAY 0x61 -#define AK09911_REG_ASAZ 0x62 - -#define AK09911_REG_CNTL1 0x30 -#define AK09911_REG_CNTL2 0x31 -#define AK09911_REG_CNTL3 0x32 - -#define AK09911_MODE_SNG_MEASURE 0x01 -#define AK09911_MODE_SELF_TEST 0x10 -#define AK09911_MODE_FUSE_ACCESS 0x1F -#define AK09911_MODE_POWERDOWN 0x00 -#define AK09911_RESET_DATA 0x01 - -#define AK09911_REG_CNTL1 0x30 -#define AK09911_REG_CNTL2 0x31 -#define AK09911_REG_CNTL3 0x32 - -#define AK09911_RAW_TO_GAUSS(asa) ((((asa) + 128) * 6000) / 256) - -#define AK09911_MAX_CONVERSION_TIMEOUT_MS 500 -#define AK09911_CONVERSION_DONE_POLL_TIME_MS 10 - -struct ak09911_data { - struct i2c_client *client; - struct mutex lock; - u8 asa[3]; - long raw_to_gauss[3]; -}; - -static const int ak09911_index_to_reg[] = { - AK09911_REG_HXL, AK09911_REG_HYL, AK09911_REG_HZL, -}; - -static int ak09911_set_mode(struct i2c_client *client, u8 mode) -{ - int ret; - - switch (mode) { - case AK09911_MODE_SNG_MEASURE: - case AK09911_MODE_SELF_TEST: - case AK09911_MODE_FUSE_ACCESS: - case AK09911_MODE_POWERDOWN: - ret = i2c_smbus_write_byte_data(client, - AK09911_REG_CNTL2, mode); - if (ret < 0) { - dev_err(&client->dev, "set_mode error\n"); - return ret; - } - /* After mode change wait atleast 100us */ - usleep_range(100, 500); - break; - default: - dev_err(&client->dev, - "%s: Unknown mode(%d).", __func__, mode); - return -EINVAL; - } - - return ret; -} - -/* Get Sensitivity Adjustment value */ -static int ak09911_get_asa(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct ak09911_data *data = iio_priv(indio_dev); - int ret; - - ret = ak09911_set_mode(client, AK09911_MODE_FUSE_ACCESS); - if (ret < 0) - return ret; - - /* Get asa data and store in the device data. */ - ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_ASAX, - 3, data->asa); - if (ret < 0) { - dev_err(&client->dev, "Not able to read asa data\n"); - return ret; - } - - ret = ak09911_set_mode(client, AK09911_MODE_POWERDOWN); - if (ret < 0) - return ret; - - data->raw_to_gauss[0] = AK09911_RAW_TO_GAUSS(data->asa[0]); - data->raw_to_gauss[1] = AK09911_RAW_TO_GAUSS(data->asa[1]); - data->raw_to_gauss[2] = AK09911_RAW_TO_GAUSS(data->asa[2]); - - return 0; -} - -static int ak09911_verify_chip_id(struct i2c_client *client) -{ - u8 wia_val[2]; - int ret; - - ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_WIA1, - 2, wia_val); - if (ret < 0) { - dev_err(&client->dev, "Error reading WIA\n"); - return ret; - } - - dev_dbg(&client->dev, "WIA %02x %02x\n", wia_val[0], wia_val[1]); - - if (wia_val[0] != AK09911_WIA1_VALUE || - wia_val[1] != AK09911_WIA2_VALUE) { - dev_err(&client->dev, "Device ak09911 not found\n"); - return -ENODEV; - } - - return 0; -} - -static int wait_conversion_complete_polled(struct ak09911_data *data) -{ - struct i2c_client *client = data->client; - u8 read_status; - u32 timeout_ms = AK09911_MAX_CONVERSION_TIMEOUT_MS; - int ret; - - /* Wait for the conversion to complete. */ - while (timeout_ms) { - msleep_interruptible(AK09911_CONVERSION_DONE_POLL_TIME_MS); - ret = i2c_smbus_read_byte_data(client, AK09911_REG_ST1); - if (ret < 0) { - dev_err(&client->dev, "Error in reading ST1\n"); - return ret; - } - read_status = ret & 0x01; - if (read_status) - break; - timeout_ms -= AK09911_CONVERSION_DONE_POLL_TIME_MS; - } - if (!timeout_ms) { - dev_err(&client->dev, "Conversion timeout happened\n"); - return -EIO; - } - - return read_status; -} - -static int ak09911_read_axis(struct iio_dev *indio_dev, int index, int *val) -{ - struct ak09911_data *data = iio_priv(indio_dev); - struct i2c_client *client = data->client; - int ret; - - mutex_lock(&data->lock); - - ret = ak09911_set_mode(client, AK09911_MODE_SNG_MEASURE); - if (ret < 0) - goto fn_exit; - - ret = wait_conversion_complete_polled(data); - if (ret < 0) - goto fn_exit; - - /* Read data */ - ret = i2c_smbus_read_word_data(client, ak09911_index_to_reg[index]); - if (ret < 0) { - dev_err(&client->dev, "Read axis data fails\n"); - goto fn_exit; - } - - mutex_unlock(&data->lock); - - /* Clamp to valid range. */ - *val = sign_extend32(clamp_t(s16, ret, -8192, 8191), 13); - - return IIO_VAL_INT; - -fn_exit: - mutex_unlock(&data->lock); - - return ret; -} - -static int ak09911_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct ak09911_data *data = iio_priv(indio_dev); - - switch (mask) { - case IIO_CHAN_INFO_RAW: - return ak09911_read_axis(indio_dev, chan->address, val); - case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = data->raw_to_gauss[chan->address]; - return IIO_VAL_INT_PLUS_MICRO; - } - - return -EINVAL; -} - -#define AK09911_CHANNEL(axis, index) \ - { \ - .type = IIO_MAGN, \ - .modified = 1, \ - .channel2 = IIO_MOD_##axis, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ - BIT(IIO_CHAN_INFO_SCALE), \ - .address = index, \ - } - -static const struct iio_chan_spec ak09911_channels[] = { - AK09911_CHANNEL(X, 0), AK09911_CHANNEL(Y, 1), AK09911_CHANNEL(Z, 2), -}; - -static const struct iio_info ak09911_info = { - .read_raw = &ak09911_read_raw, - .driver_module = THIS_MODULE, -}; - -static const struct acpi_device_id ak_acpi_match[] = { - {"AK009911", 0}, - { }, -}; -MODULE_DEVICE_TABLE(acpi, ak_acpi_match); - -static int ak09911_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct iio_dev *indio_dev; - struct ak09911_data *data; - const char *name; - int ret; - - ret = ak09911_verify_chip_id(client); - if (ret) { - dev_err(&client->dev, "AK00911 not detected\n"); - return -ENODEV; - } - - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); - if (indio_dev == NULL) - return -ENOMEM; - - data = iio_priv(indio_dev); - i2c_set_clientdata(client, indio_dev); - - data->client = client; - mutex_init(&data->lock); - - ret = ak09911_get_asa(client); - if (ret) - return ret; - - if (id) - name = id->name; - else if (ACPI_HANDLE(&client->dev)) - name = dev_name(&client->dev); - else - return -ENODEV; - - dev_dbg(&client->dev, "Asahi compass chip %s\n", name); - - indio_dev->dev.parent = &client->dev; - indio_dev->channels = ak09911_channels; - indio_dev->num_channels = ARRAY_SIZE(ak09911_channels); - indio_dev->info = &ak09911_info; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->name = name; - - return devm_iio_device_register(&client->dev, indio_dev); -} - -static const struct i2c_device_id ak09911_id[] = { - {"ak09911", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, ak09911_id); - -static struct i2c_driver ak09911_driver = { - .driver = { - .name = "ak09911", - .acpi_match_table = ACPI_PTR(ak_acpi_match), - }, - .probe = ak09911_probe, - .id_table = ak09911_id, -}; -module_i2c_driver(ak09911_driver); - -MODULE_AUTHOR("Srinivas Pandruvada "); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("AK09911 Compass driver"); diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 0f86a8e..0d10a4b 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -81,6 +81,58 @@ #define AK8975_MAX_REGS AK8975_REG_ASAZ /* + * AK09912 Register definitions + */ +#define AK09912_REG_WIA1 0x00 +#define AK09912_REG_WIA2 0x01 +#define AK09912_DEVICE_ID 0x04 +#define AK09911_DEVICE_ID 0x05 + +#define AK09911_REG_INFO1 0x02 +#define AK09911_REG_INFO2 0x03 + +#define AK09912_REG_ST1 0x10 + +#define AK09912_REG_ST1_DRDY_SHIFT 0 +#define AK09912_REG_ST1_DRDY_MASK (1 << AK09912_REG_ST1_DRDY_SHIFT) + +#define AK09912_REG_HXL 0x11 +#define AK09912_REG_HXH 0x12 +#define AK09912_REG_HYL 0x13 +#define AK09912_REG_HYH 0x14 +#define AK09912_REG_HZL 0x15 +#define AK09912_REG_HZH 0x16 +#define AK09912_REG_TMPS 0x17 + +#define AK09912_REG_ST2 0x18 +#define AK09912_REG_ST2_HOFL_SHIFT 3 +#define AK09912_REG_ST2_HOFL_MASK (1 << AK09912_REG_ST2_HOFL_SHIFT) + +#define AK09912_REG_CNTL1 0x30 + +#define AK09912_REG_CNTL2 0x31 +#define AK09912_REG_CNTL_MODE_POWER_DOWN 0x00 +#define AK09912_REG_CNTL_MODE_ONCE 0x01 +#define AK09912_REG_CNTL_MODE_SELF_TEST 0x10 +#define AK09912_REG_CNTL_MODE_FUSE_ROM 0x1F +#define AK09912_REG_CNTL2_MODE_SHIFT 0 +#define AK09912_REG_CNTL2_MODE_MASK (0x1F << AK09912_REG_CNTL2_MODE_SHIFT) + +#define AK09912_REG_CNTL3 0x32 + +#define AK09912_REG_TS1 0x33 +#define AK09912_REG_TS2 0x34 +#define AK09912_REG_TS3 0x35 +#define AK09912_REG_I2CDIS 0x36 +#define AK09912_REG_TS4 0x37 + +#define AK09912_REG_ASAX 0x60 +#define AK09912_REG_ASAY 0x61 +#define AK09912_REG_ASAZ 0x62 + +#define AK09912_MAX_REGS AK09912_REG_ASAZ + +/* * Miscellaneous values. */ #define AK8975_MAX_CONVERSION_TIMEOUT 500 @@ -130,22 +182,38 @@ static long ak8975_raw_to_gauss(u16 data) } /* - * For AK8963, same calculation, but the device is less sensitive: + * For AK8963 and AK09911, same calculation, but the device is less sensitive: * * H is in the range of +-8190. The magnetometer has a range of * +-4912uT. To go from the raw value to uT is: * * HuT = H * 4912/8190, or roughly, 6/10, instead of 3/10. */ -static long ak8963_raw_to_gauss(u16 data) + +static long ak8963_09911_raw_to_gauss(u16 data) { return (((long)data + 128) * 6000) / 256; } +/* + * For AK09912, same calculation, except the device is more sensitive: + * + * H is in the range of -32752 to 32752. The magnetometer has a range of + * +-4912uT. To go from the raw value to uT is: + * + * HuT = H * 4912/32752, or roughly, 3/20, instead of 3/10. + */ +static long ak09912_raw_to_gauss(u16 data) +{ + return (((long)data + 128) * 1500) / 256; +} + /* Compatible Asahi Kasei Compass parts */ enum asahi_compass_chipset { AK8975, AK8963, + AK09911, + AK09912, AK_MAX_TYPE }; @@ -212,7 +280,7 @@ static struct ak_def ak_def_array[AK_MAX_TYPE] = { }, { .type = AK8963, - .raw_to_gauss = ak8963_raw_to_gauss, + .raw_to_gauss = ak8963_09911_raw_to_gauss, .range = 8190, .ctrl_regs = { AK8975_REG_ST1, @@ -235,6 +303,56 @@ static struct ak_def ak_def_array[AK_MAX_TYPE] = { AK8975_REG_HYL, AK8975_REG_HZL}, }, + { + .type = AK09911, + .raw_to_gauss = ak8963_09911_raw_to_gauss, + .range = 8192, + .ctrl_regs = { + AK09912_REG_ST1, + AK09912_REG_ST2, + AK09912_REG_CNTL2, + AK09912_REG_ASAX, + AK09912_MAX_REGS}, + .ctrl_masks = { + AK09912_REG_ST1_DRDY_MASK, + AK09912_REG_ST2_HOFL_MASK, + 0, + AK09912_REG_CNTL2_MODE_MASK}, + .ctrl_modes = { + AK09912_REG_CNTL_MODE_POWER_DOWN, + AK09912_REG_CNTL_MODE_ONCE, + AK09912_REG_CNTL_MODE_SELF_TEST, + AK09912_REG_CNTL_MODE_FUSE_ROM}, + .data_regs = { + AK09912_REG_HXL, + AK09912_REG_HYL, + AK09912_REG_HZL}, + }, + { + .type = AK09912, + .raw_to_gauss = ak09912_raw_to_gauss, + .range = 32752, + .ctrl_regs = { + AK09912_REG_ST1, + AK09912_REG_ST2, + AK09912_REG_CNTL2, + AK09912_REG_ASAX, + AK09912_MAX_REGS}, + .ctrl_masks = { + AK09912_REG_ST1_DRDY_MASK, + AK09912_REG_ST2_HOFL_MASK, + 0, + AK09912_REG_CNTL2_MODE_MASK}, + .ctrl_modes = { + AK09912_REG_CNTL_MODE_POWER_DOWN, + AK09912_REG_CNTL_MODE_ONCE, + AK09912_REG_CNTL_MODE_SELF_TEST, + AK09912_REG_CNTL_MODE_FUSE_ROM}, + .data_regs = { + AK09912_REG_HXL, + AK09912_REG_HYL, + AK09912_REG_HZL}, + } }; /* @@ -255,6 +373,52 @@ struct ak8975_data { }; /* + * Return 0 if the i2c device is the one we expect. + * return a negative error number otherwise + */ +static int ak8975_who_i_am(struct i2c_client *client, + enum asahi_compass_chipset type) +{ + u8 wia_val[2]; + int ret; + + /* + * Signature for each device: + * Device | WIA1 | WIA2 + * AK09912 | DEVICE_ID | AK09912_DEVICE_ID + * AK09911 | DEVICE_ID | AK09911_DEVICE_ID + * AK8975 | DEVICE_ID | NA + * AK8963 | DEVICE_ID | NA + */ + ret = i2c_smbus_read_i2c_block_data(client, AK09912_REG_WIA1, + 2, wia_val); + if (ret < 0) { + dev_err(&client->dev, "Error reading WIA\n"); + return ret; + } + + if (wia_val[0] != AK8975_DEVICE_ID) + return -ENODEV; + + switch (type) { + case AK8975: + case AK8963: + return 0; + case AK09911: + if (wia_val[1] == AK09911_DEVICE_ID) + return 0; + break; + case AK09912: + if (wia_val[1] == AK09912_DEVICE_ID) + return 0; + break; + default: + dev_err(&client->dev, "Type %d unknown\n", type); + } + return -ENODEV; +} + +/* * Helper function to write to CNTL register. */ static int ak8975_set_mode(struct ak8975_data *data, enum ak_ctrl_mode mode) @@ -329,21 +493,8 @@ static int ak8975_setup(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct ak8975_data *data = iio_priv(indio_dev); - u8 device_id; int ret; - /* Confirm that the device we're talking to is really an AK8975. */ - ret = i2c_smbus_read_byte_data(client, AK8975_REG_WIA); - if (ret < 0) { - dev_err(&client->dev, "Error reading WIA\n"); - return ret; - } - device_id = ret; - if (device_id != AK8975_DEVICE_ID) { - dev_err(&client->dev, "Device ak8975 not found\n"); - return -ENODEV; - } - /* Write the fused rom access mode. */ ret = ak8975_set_mode(data, FUSE_ROM); if (ret < 0) { @@ -554,6 +705,8 @@ static const struct acpi_device_id ak_acpi_match[] = { {"AK8975", AK8975}, {"AK8963", AK8963}, {"INVN6500", AK8963}, + {"AK09911", AK09911}, + {"AK09912", AK09912}, { }, }; MODULE_DEVICE_TABLE(acpi, ak_acpi_match); @@ -633,6 +786,11 @@ static int ak8975_probe(struct i2c_client *client, } data->def = &ak_def_array[chipset]; + err = ak8975_who_i_am(client, data->def->type); + if (err < 0) { + dev_err(&client->dev, "Unexpected device\n"); + return err; + } dev_dbg(&client->dev, "Asahi compass chip %s\n", name); /* Perform some basic start-of-day setup of the device. */ @@ -655,6 +813,8 @@ static int ak8975_probe(struct i2c_client *client, static const struct i2c_device_id ak8975_id[] = { {"ak8975", AK8975}, {"ak8963", AK8963}, + {"ak09911", AK09911}, + {"ak09912", AK09912}, {} }; @@ -665,6 +825,10 @@ static const struct of_device_id ak8975_of_match[] = { { .compatible = "ak8975", }, { .compatible = "asahi-kasei,ak8963", }, { .compatible = "ak8963", }, + { .compatible = "asahi-kasei,ak09911", }, + { .compatible = "ak09911", }, + { .compatible = "asahi-kasei,ak09912", }, + { .compatible = "ak09912", }, {} }; MODULE_DEVICE_TABLE(of, ak8975_of_match); -- cgit v0.10.2 From 8f6eb02596cc297c12ee16c86b9bbe1c186dda15 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Sun, 16 Nov 2014 13:33:24 +0100 Subject: iio: common: remove unnecessary sizeof(u8) sizeof(u8) is always 1. Signed-off-by: Fabian Frederick Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c index 78a6a1a..5b37737 100644 --- a/drivers/iio/common/st_sensors/st_sensors_spi.c +++ b/drivers/iio/common/st_sensors/st_sensors_spi.c @@ -54,7 +54,7 @@ static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb, if (err) goto acc_spi_read_error; - memcpy(data, tb->rx_buf, len*sizeof(u8)); + memcpy(data, tb->rx_buf, len); mutex_unlock(&tb->buf_lock); return len; -- cgit v0.10.2 From 0f8994b18afc47fd0cda20ba6162c21a093173da Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Thu, 20 Nov 2014 14:00:48 +0200 Subject: iio: bmp280: refactor compensation code This version of the code avoids extra memory copy operations and is somewhat smaller in code size. Signed-off-by: Vlad Dogaru Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c index 75038da..47dfd34 100644 --- a/drivers/iio/pressure/bmp280.c +++ b/drivers/iio/pressure/bmp280.c @@ -80,16 +80,12 @@ struct bmp280_data { s32 t_fine; }; -/* Compensation parameters. */ -struct bmp280_comp_temp { - u16 dig_t1; - s16 dig_t2, dig_t3; -}; - -struct bmp280_comp_press { - u16 dig_p1; - s16 dig_p2, dig_p3, dig_p4, dig_p5, dig_p6, dig_p7, dig_p8, dig_p9; -}; +/* + * These enums are used for indexing into the array of compensation + * parameters. + */ +enum { T1, T2, T3 }; +enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 }; static const struct iio_chan_spec bmp280_channels[] = { { @@ -141,54 +137,6 @@ static const struct regmap_config bmp280_regmap_config = { .volatile_reg = bmp280_is_volatile_reg, }; -static int bmp280_read_compensation_temp(struct bmp280_data *data, - struct bmp280_comp_temp *comp) -{ - int ret; - __le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2]; - - ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START, - buf, BMP280_COMP_TEMP_REG_COUNT); - if (ret < 0) { - dev_err(&data->client->dev, - "failed to read temperature calibration parameters\n"); - return ret; - } - - comp->dig_t1 = (u16) le16_to_cpu(buf[0]); - comp->dig_t2 = (s16) le16_to_cpu(buf[1]); - comp->dig_t3 = (s16) le16_to_cpu(buf[2]); - - return 0; -} - -static int bmp280_read_compensation_press(struct bmp280_data *data, - struct bmp280_comp_press *comp) -{ - int ret; - __le16 buf[BMP280_COMP_PRESS_REG_COUNT / 2]; - - ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START, - buf, BMP280_COMP_PRESS_REG_COUNT); - if (ret < 0) { - dev_err(&data->client->dev, - "failed to read pressure calibration parameters\n"); - return ret; - } - - comp->dig_p1 = (u16) le16_to_cpu(buf[0]); - comp->dig_p2 = (s16) le16_to_cpu(buf[1]); - comp->dig_p3 = (s16) le16_to_cpu(buf[2]); - comp->dig_p4 = (s16) le16_to_cpu(buf[3]); - comp->dig_p5 = (s16) le16_to_cpu(buf[4]); - comp->dig_p6 = (s16) le16_to_cpu(buf[5]); - comp->dig_p7 = (s16) le16_to_cpu(buf[6]); - comp->dig_p8 = (s16) le16_to_cpu(buf[7]); - comp->dig_p9 = (s16) le16_to_cpu(buf[8]); - - return 0; -} - /* * Returns temperature in DegC, resolution is 0.01 DegC. Output value of * "5123" equals 51.23 DegC. t_fine carries fine temperature as global @@ -197,16 +145,33 @@ static int bmp280_read_compensation_press(struct bmp280_data *data, * Taken from datasheet, Section 3.11.3, "Compensation formula". */ static s32 bmp280_compensate_temp(struct bmp280_data *data, - struct bmp280_comp_temp *comp, s32 adc_temp) { + int ret; s32 var1, var2, t; + __le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2]; + + ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START, + buf, BMP280_COMP_TEMP_REG_COUNT); + if (ret < 0) { + dev_err(&data->client->dev, + "failed to read temperature calibration parameters\n"); + return ret; + } - var1 = (((adc_temp >> 3) - ((s32) comp->dig_t1 << 1)) * - ((s32) comp->dig_t2)) >> 11; - var2 = (((((adc_temp >> 4) - ((s32) comp->dig_t1)) * - ((adc_temp >> 4) - ((s32) comp->dig_t1))) >> 12) * - ((s32) comp->dig_t3)) >> 14; + /* + * The double casts are necessary because le16_to_cpu returns an + * unsigned 16-bit value. Casting that value directly to a + * signed 32-bit will not do proper sign extension. + * + * Conversely, T1 and P1 are unsigned values, so they can be + * cast straight to the larger type. + */ + var1 = (((adc_temp >> 3) - ((s32)le16_to_cpu(buf[T1]) << 1)) * + ((s32)(s16)le16_to_cpu(buf[T2]))) >> 11; + var2 = (((((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1]))) * + ((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1])))) >> 12) * + ((s32)(s16)le16_to_cpu(buf[T3]))) >> 14; data->t_fine = var1 + var2; t = (data->t_fine * 5 + 128) >> 8; @@ -222,27 +187,36 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data, * Taken from datasheet, Section 3.11.3, "Compensation formula". */ static u32 bmp280_compensate_press(struct bmp280_data *data, - struct bmp280_comp_press *comp, s32 adc_press) { + int ret; s64 var1, var2, p; + __le16 buf[BMP280_COMP_PRESS_REG_COUNT / 2]; + + ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_PRESS_START, + buf, BMP280_COMP_PRESS_REG_COUNT); + if (ret < 0) { + dev_err(&data->client->dev, + "failed to read pressure calibration parameters\n"); + return ret; + } - var1 = ((s64) data->t_fine) - 128000; - var2 = var1 * var1 * (s64) comp->dig_p6; - var2 = var2 + ((var1 * (s64) comp->dig_p5) << 17); - var2 = var2 + (((s64) comp->dig_p4) << 35); - var1 = ((var1 * var1 * (s64) comp->dig_p3) >> 8) + - ((var1 * (s64) comp->dig_p2) << 12); - var1 = (((((s64) 1) << 47) + var1)) * ((s64) comp->dig_p1) >> 33; + var1 = ((s64)data->t_fine) - 128000; + var2 = var1 * var1 * (s64)(s16)le16_to_cpu(buf[P6]); + var2 = var2 + ((var1 * (s64)(s16)le16_to_cpu(buf[P5])) << 17); + var2 = var2 + (((s64)(s16)le16_to_cpu(buf[P4])) << 35); + var1 = ((var1 * var1 * (s64)(s16)le16_to_cpu(buf[P3])) >> 8) + + ((var1 * (s64)(s16)le16_to_cpu(buf[P2])) << 12); + var1 = ((((s64)1) << 47) + var1) * ((s64)le16_to_cpu(buf[P1])) >> 33; if (var1 == 0) return 0; - p = ((((s64) 1048576 - adc_press) << 31) - var2) * 3125; + p = ((((s64)1048576 - adc_press) << 31) - var2) * 3125; p = div64_s64(p, var1); - var1 = (((s64) comp->dig_p9) * (p >> 13) * (p >> 13)) >> 25; - var2 = (((s64) comp->dig_p8) * p) >> 19; - p = ((p + var1 + var2) >> 8) + (((s64) comp->dig_p7) << 4); + var1 = (((s64)(s16)le16_to_cpu(buf[P9])) * (p >> 13) * (p >> 13)) >> 25; + var2 = (((s64)(s16)le16_to_cpu(buf[P8])) * p) >> 19; + p = ((p + var1 + var2) >> 8) + (((s64)(s16)le16_to_cpu(buf[P7])) << 4); return (u32) p; } @@ -253,11 +227,6 @@ static int bmp280_read_temp(struct bmp280_data *data, int ret; __be32 tmp = 0; s32 adc_temp, comp_temp; - struct bmp280_comp_temp comp; - - ret = bmp280_read_compensation_temp(data, &comp); - if (ret < 0) - return ret; ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB, (u8 *) &tmp, 3); @@ -267,7 +236,7 @@ static int bmp280_read_temp(struct bmp280_data *data, } adc_temp = be32_to_cpu(tmp) >> 12; - comp_temp = bmp280_compensate_temp(data, &comp, adc_temp); + comp_temp = bmp280_compensate_temp(data, adc_temp); /* * val might be NULL if we're called by the read_press routine, @@ -288,11 +257,6 @@ static int bmp280_read_press(struct bmp280_data *data, __be32 tmp = 0; s32 adc_press; u32 comp_press; - struct bmp280_comp_press comp; - - ret = bmp280_read_compensation_press(data, &comp); - if (ret < 0) - return ret; /* Read and compensate temperature so we get a reading of t_fine. */ ret = bmp280_read_temp(data, NULL); @@ -307,7 +271,7 @@ static int bmp280_read_press(struct bmp280_data *data, } adc_press = be32_to_cpu(tmp) >> 12; - comp_press = bmp280_compensate_press(data, &comp, adc_press); + comp_press = bmp280_compensate_press(data, adc_press); *val = comp_press; *val2 = 256000; -- cgit v0.10.2 From 3a2ecc3d2dce6e051b6afc319bb380c829e4e4fd Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 5 Dec 2014 14:52:09 -0800 Subject: iio: imu: inv_mpu6050: Add i2c mux for by pass This chip allows some limited number of sensors connected to it as slaves, which can be directly accessed by register interface of this driver.But the current upstream driver doesn't support such mode. To attach such slaves to main processor i2c bus, chip has to be set up in bypass mode. This change adds i2c mux, which will enable/disable this mode for transaction to/from such slave devices. This was discussed for a while in mailing list, this was the outcome: Reference: http://www.spinics.net/lists/linux-iio/msg12126.html http://comments.gmane.org/gmane.linux.kernel.iio/11470 Signed-off-by: Srinivas Pandruvada Reviewed-by: Wolfram Sang Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index 2d0608b..48fbc0b 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -7,6 +7,7 @@ config INV_MPU6050_IIO depends on I2C && SYSFS select IIO_BUFFER select IIO_TRIGGERED_BUFFER + select I2C_MUX help This driver supports the Invensense MPU6050 devices. This driver can also support MPU6500 in MPU6050 compatibility mode diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index b75519d..6d2c115 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "inv_mpu_iio.h" /* @@ -52,6 +53,7 @@ static const struct inv_mpu6050_reg_map reg_set_6050 = { .int_enable = INV_MPU6050_REG_INT_ENABLE, .pwr_mgmt_1 = INV_MPU6050_REG_PWR_MGMT_1, .pwr_mgmt_2 = INV_MPU6050_REG_PWR_MGMT_2, + .int_pin_cfg = INV_MPU6050_REG_INT_PIN_CFG, }; static const struct inv_mpu6050_chip_config chip_config_6050 = { @@ -77,6 +79,83 @@ int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 d) return i2c_smbus_write_i2c_block_data(st->client, reg, 1, &d); } +/* + * The i2c read/write needs to happen in unlocked mode. As the parent + * adapter is common. If we use locked versions, it will fail as + * the mux adapter will lock the parent i2c adapter, while calling + * select/deselect functions. + */ +static int inv_mpu6050_write_reg_unlocked(struct inv_mpu6050_state *st, + u8 reg, u8 d) +{ + int ret; + u8 buf[2]; + struct i2c_msg msg[1] = { + { + .addr = st->client->addr, + .flags = 0, + .len = sizeof(buf), + .buf = buf, + } + }; + + buf[0] = reg; + buf[1] = d; + ret = __i2c_transfer(st->client->adapter, msg, 1); + if (ret != 1) + return ret; + + return 0; +} + +static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv, + u32 chan_id) +{ + struct iio_dev *indio_dev = mux_priv; + struct inv_mpu6050_state *st = iio_priv(indio_dev); + int ret = 0; + + /* Use the same mutex which was used everywhere to protect power-op */ + mutex_lock(&indio_dev->mlock); + if (!st->powerup_count) { + ret = inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1, + 0); + if (ret) + goto write_error; + + msleep(INV_MPU6050_REG_UP_TIME); + } + if (!ret) { + st->powerup_count++; + ret = inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg, + st->client->irq | + INV_MPU6050_BIT_BYPASS_EN); + } +write_error: + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap, + void *mux_priv, u32 chan_id) +{ + struct iio_dev *indio_dev = mux_priv; + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + mutex_lock(&indio_dev->mlock); + /* It doesn't really mattter, if any of the calls fails */ + inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg, + st->client->irq); + st->powerup_count--; + if (!st->powerup_count) + inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1, + INV_MPU6050_BIT_SLEEP); + mutex_unlock(&indio_dev->mlock); + + return 0; +} + int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask) { u8 d, mgmt_1; @@ -133,13 +212,22 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask) int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on) { - int result; + int result = 0; + + if (power_on) { + /* Already under indio-dev->mlock mutex */ + if (!st->powerup_count) + result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, + 0); + if (!result) + st->powerup_count++; + } else { + st->powerup_count--; + if (!st->powerup_count) + result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, + INV_MPU6050_BIT_SLEEP); + } - if (power_on) - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, 0); - else - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, - INV_MPU6050_BIT_SLEEP); if (result) return result; @@ -673,6 +761,7 @@ static int inv_mpu_probe(struct i2c_client *client, st = iio_priv(indio_dev); st->client = client; + st->powerup_count = 0; pdata = dev_get_platdata(&client->dev); if (pdata) st->plat_data = *pdata; @@ -720,8 +809,21 @@ static int inv_mpu_probe(struct i2c_client *client, goto out_remove_trigger; } + st->mux_adapter = i2c_add_mux_adapter(client->adapter, + &client->dev, + indio_dev, + 0, 0, 0, + inv_mpu6050_select_bypass, + inv_mpu6050_deselect_bypass); + if (!st->mux_adapter) { + result = -ENODEV; + goto out_unreg_device; + } + return 0; +out_unreg_device: + iio_device_unregister(indio_dev); out_remove_trigger: inv_mpu6050_remove_trigger(st); out_unreg_ring: @@ -734,6 +836,7 @@ static int inv_mpu_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); struct inv_mpu6050_state *st = iio_priv(indio_dev); + i2c_del_mux_adapter(st->mux_adapter); iio_device_unregister(indio_dev); inv_mpu6050_remove_trigger(st); iio_triggered_buffer_cleanup(indio_dev); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index e779931..aa837de 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -54,6 +54,7 @@ struct inv_mpu6050_reg_map { u8 int_enable; u8 pwr_mgmt_1; u8 pwr_mgmt_2; + u8 int_pin_cfg; }; /*device enum */ @@ -119,6 +120,8 @@ struct inv_mpu6050_state { enum inv_devices chip_type; spinlock_t time_stamp_lock; struct i2c_client *client; + struct i2c_adapter *mux_adapter; + unsigned int powerup_count; struct inv_mpu6050_platform_data plat_data; DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE); }; @@ -179,6 +182,9 @@ struct inv_mpu6050_state { /* 6 + 6 round up and plus 8 */ #define INV_MPU6050_OUTPUT_DATA_SIZE 24 +#define INV_MPU6050_REG_INT_PIN_CFG 0x37 +#define INV_MPU6050_BIT_BYPASS_EN 0x2 + /* init parameters */ #define INV_MPU6050_INIT_FIFO_RATE 50 #define INV_MPU6050_TIME_STAMP_TOR 5 -- cgit v0.10.2 From d3653d09891b57f2e8089b8908f24a2e97576a49 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sat, 6 Dec 2014 00:18:07 +0200 Subject: iio: accel: kxcjk-1013: always power on device in resume When the system resumes, it will first call system resume and then runtime suspend (if CONFIG_RUNTIME_PM is enabled). There is no need to conditionally power on the device in system resume, so always power it on and leave runtime suspend to power it off if needed. Suggested-by: Srinivas Pandruvada Signed-off-by: Irina Tirdea Reviewed-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 1720e9a..aed3777 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1354,10 +1354,7 @@ static int kxcjk1013_resume(struct device *dev) int ret = 0; mutex_lock(&data->mutex); - /* Check, if the suspend occured while active */ - if (data->dready_trigger_on || data->motion_trigger_on || - data->ev_enable_state) - ret = kxcjk1013_set_mode(data, OPERATION); + ret = kxcjk1013_set_mode(data, OPERATION); mutex_unlock(&data->mutex); return ret; -- cgit v0.10.2 From c75b8dc84fd28511224a4cd2bfa791bb56a06172 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sat, 6 Dec 2014 00:18:08 +0200 Subject: iio: accel: kxcjk-1013: only set power state if CONFIG_PM is defined When CONFIG_PM is not defined and the driver tries to power off the device, kxcjk1013_set_power_state will call pm_runtime_put_autosuspend, which is not implemented (wil return -ENOSYS). Only call pm_runtime calls to change power state when CONFIG_PM is defined. Signed-off-by: Irina Tirdea Reviewed-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index aed3777..7b0a9da 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -376,6 +376,7 @@ static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data) static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) { +#ifdef CONFIG_PM int ret; if (on) @@ -389,6 +390,7 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) "Failed: kxcjk1013_set_power_state for %d\n", on); return ret; } +#endif return 0; } -- cgit v0.10.2 From f9380e7123863a4cb0627d940533be954a0a15df Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 27 Nov 2014 01:42:45 +0300 Subject: iio: inkern: add iio_write_channel_raw Introduce API for easy in-kernel setting of DAC values. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 866fe90..21655fd 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -631,3 +631,28 @@ err_unlock: return ret; } EXPORT_SYMBOL_GPL(iio_get_channel_type); + +static int iio_channel_write(struct iio_channel *chan, int val, int val2, + enum iio_chan_info_enum info) +{ + return chan->indio_dev->info->write_raw(chan->indio_dev, + chan->channel, val, val2, info); +} + +int iio_write_channel_raw(struct iio_channel *chan, int val) +{ + int ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + ret = iio_channel_write(chan, val, 0, IIO_CHAN_INFO_RAW); +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_write_channel_raw); diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 651f9a0..6f64624 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -151,6 +151,16 @@ int iio_read_channel_average_raw(struct iio_channel *chan, int *val); int iio_read_channel_processed(struct iio_channel *chan, int *val); /** + * iio_write_channel_raw() - write to a given channel + * @chan: The channel being queried. + * @val: Value being written. + * + * Note raw writes to iio channels are in dac counts and hence + * scale will need to be applied if standard units required. + */ +int iio_write_channel_raw(struct iio_channel *chan, int val); + +/** * iio_get_channel_type() - get the type of a channel * @channel: The channel being queried. * @type: The type of the channel. -- cgit v0.10.2 From db38b9f9dddb10772329de6a26b416f6e3f7be41 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:07 +0100 Subject: staging:iio:ad5933: Don't enable channels by default The convention for IIO devices is that all channels are disabled by default. Signed-off-by: Lars-Peter Clausen Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index b6bd609..aa6a368 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -757,10 +757,6 @@ static int ad5933_probe(struct i2c_client *client, if (ret) goto error_unreg_ring; - /* enable both REAL and IMAG channels by default */ - iio_scan_mask_set(indio_dev, indio_dev->buffer, 0); - iio_scan_mask_set(indio_dev, indio_dev->buffer, 1); - ret = ad5933_setup(st); if (ret) goto error_uninitialize_ring; -- cgit v0.10.2 From 00d52334857c36fe52f8fc15a6fe3f0644fb73bc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:08 +0100 Subject: staging:iio:sca3000: Don't enable channels by default The convention for IIO devices is that all channels are disabled by default. Signed-off-by: Lars-Peter Clausen Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index e4e5639..cd46a61 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -1159,11 +1159,6 @@ static int sca3000_probe(struct spi_device *spi) ARRAY_SIZE(sca3000_channels)); if (ret < 0) goto error_unregister_dev; - if (indio_dev->buffer) { - iio_scan_mask_set(indio_dev, indio_dev->buffer, 0); - iio_scan_mask_set(indio_dev, indio_dev->buffer, 1); - iio_scan_mask_set(indio_dev, indio_dev->buffer, 2); - } if (spi->irq) { ret = request_threaded_irq(spi->irq, -- cgit v0.10.2 From 217a5cf0a1100264ced523e437e2e22c442dca7c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:09 +0100 Subject: iio: Unexport iio_scan_mask_set() Individual drivers should not be messing with the scan mask that contains the list of enabled channels. This is something that is supposed to be managed by the core. Now that the last few drivers that used it to configure a default scan mask have been updated to not do this anymore we can unexport the function. Note, this patch also requires moving a few functions around so they are all declared before the first internal user. Signed-off-by: Lars-Peter Clausen Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index f971f79..f667e4e 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -178,6 +178,80 @@ static ssize_t iio_scan_el_show(struct device *dev, return sprintf(buf, "%d\n", ret); } +/* Note NULL used as error indicator as it doesn't make sense. */ +static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, + unsigned int masklength, + const unsigned long *mask) +{ + if (bitmap_empty(mask, masklength)) + return NULL; + while (*av_masks) { + if (bitmap_subset(mask, av_masks, masklength)) + return av_masks; + av_masks += BITS_TO_LONGS(masklength); + } + return NULL; +} + +static bool iio_validate_scan_mask(struct iio_dev *indio_dev, + const unsigned long *mask) +{ + if (!indio_dev->setup_ops->validate_scan_mask) + return true; + + return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask); +} + +/** + * iio_scan_mask_set() - set particular bit in the scan mask + * @indio_dev: the iio device + * @buffer: the buffer whose scan mask we are interested in + * @bit: the bit to be set. + * + * Note that at this point we have no way of knowing what other + * buffers might request, hence this code only verifies that the + * individual buffers request is plausible. + */ +static int iio_scan_mask_set(struct iio_dev *indio_dev, + struct iio_buffer *buffer, int bit) +{ + const unsigned long *mask; + unsigned long *trialmask; + + trialmask = kmalloc(sizeof(*trialmask)* + BITS_TO_LONGS(indio_dev->masklength), + GFP_KERNEL); + + if (trialmask == NULL) + return -ENOMEM; + if (!indio_dev->masklength) { + WARN_ON("Trying to set scanmask prior to registering buffer\n"); + goto err_invalid_mask; + } + bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); + set_bit(bit, trialmask); + + if (!iio_validate_scan_mask(indio_dev, trialmask)) + goto err_invalid_mask; + + if (indio_dev->available_scan_masks) { + mask = iio_scan_mask_match(indio_dev->available_scan_masks, + indio_dev->masklength, + trialmask); + if (!mask) + goto err_invalid_mask; + } + bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); + + kfree(trialmask); + + return 0; + +err_invalid_mask: + kfree(trialmask); + return -EINVAL; +} + static int iio_scan_mask_clear(struct iio_buffer *buffer, int bit) { clear_bit(bit, buffer->scan_mask); @@ -455,21 +529,6 @@ ssize_t iio_buffer_show_enable(struct device *dev, } EXPORT_SYMBOL(iio_buffer_show_enable); -/* Note NULL used as error indicator as it doesn't make sense. */ -static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, - unsigned int masklength, - const unsigned long *mask) -{ - if (bitmap_empty(mask, masklength)) - return NULL; - while (*av_masks) { - if (bitmap_subset(mask, av_masks, masklength)) - return av_masks; - av_masks += BITS_TO_LONGS(masklength); - } - return NULL; -} - static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const unsigned long *mask, bool timestamp) { @@ -808,66 +867,6 @@ bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, } EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot); -static bool iio_validate_scan_mask(struct iio_dev *indio_dev, - const unsigned long *mask) -{ - if (!indio_dev->setup_ops->validate_scan_mask) - return true; - - return indio_dev->setup_ops->validate_scan_mask(indio_dev, mask); -} - -/** - * iio_scan_mask_set() - set particular bit in the scan mask - * @indio_dev: the iio device - * @buffer: the buffer whose scan mask we are interested in - * @bit: the bit to be set. - * - * Note that at this point we have no way of knowing what other - * buffers might request, hence this code only verifies that the - * individual buffers request is plausible. - */ -int iio_scan_mask_set(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit) -{ - const unsigned long *mask; - unsigned long *trialmask; - - trialmask = kmalloc(sizeof(*trialmask)* - BITS_TO_LONGS(indio_dev->masklength), - GFP_KERNEL); - - if (trialmask == NULL) - return -ENOMEM; - if (!indio_dev->masklength) { - WARN_ON("Trying to set scanmask prior to registering buffer\n"); - goto err_invalid_mask; - } - bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength); - set_bit(bit, trialmask); - - if (!iio_validate_scan_mask(indio_dev, trialmask)) - goto err_invalid_mask; - - if (indio_dev->available_scan_masks) { - mask = iio_scan_mask_match(indio_dev->available_scan_masks, - indio_dev->masklength, - trialmask); - if (!mask) - goto err_invalid_mask; - } - bitmap_copy(buffer->scan_mask, trialmask, indio_dev->masklength); - - kfree(trialmask); - - return 0; - -err_invalid_mask: - kfree(trialmask); - return -EINVAL; -} -EXPORT_SYMBOL_GPL(iio_scan_mask_set); - int iio_scan_mask_query(struct iio_dev *indio_dev, struct iio_buffer *buffer, int bit) { diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 5193927..8c8ce61 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -117,15 +117,6 @@ int iio_scan_mask_query(struct iio_dev *indio_dev, struct iio_buffer *buffer, int bit); /** - * iio_scan_mask_set() - set particular bit in the scan mask - * @indio_dev IIO device structure - * @buffer: the buffer whose scan mask we are interested in - * @bit: the bit to be set. - **/ -int iio_scan_mask_set(struct iio_dev *indio_dev, - struct iio_buffer *buffer, int bit); - -/** * iio_push_to_buffers() - push to a registered buffer. * @indio_dev: iio_dev structure for device. * @data: Full scan. -- cgit v0.10.2 From 131e97d3faf2df29a6a488b94890481351f18aea Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:10 +0100 Subject: staging:iio:sca3000: Register same channels for device and buffer In preparation for moving the buffer registration to the core make sure to register the same channel array for the device and the buffer. Currently the temperature channel is not registered for the buffer, setting its scan index to -1 will make sure that it is skipped for the buffer. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index cd46a61..aef8c91 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -459,6 +459,8 @@ static const struct iio_chan_spec sca3000_channels_with_temp[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), + /* No buffer support */ + .scan_index = -1, }, }; @@ -1154,9 +1156,8 @@ static int sca3000_probe(struct spi_device *spi) if (ret < 0) return ret; - ret = iio_buffer_register(indio_dev, - sca3000_channels, - ARRAY_SIZE(sca3000_channels)); + ret = iio_buffer_register(indio_dev, indio_dev->channels, + indio_dev->num_channels); if (ret < 0) goto error_unregister_dev; -- cgit v0.10.2 From 4ae03019923f7dd5785b69a513b74ccc1c3f7766 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:11 +0100 Subject: staging:iio:dummy: Register same channels for device and buffer In preparation for moving the buffer registration to the core make sure to register the same channel array for the device and the buffer. Currently the output voltage and the activity channels are not registered for the buffer, setting its scan index to -1 will make sure that it is skipped for the buffer. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index 10a9e08..0b8611a 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -239,6 +239,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = { { .type = IIO_VOLTAGE, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_index = -1, /* No buffer support */ .output = 1, .indexed = 1, .channel = 0, @@ -248,7 +249,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = { .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_ENABLE) | BIT(IIO_CHAN_INFO_CALIBHEIGHT), .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), - .scan_index = -1, + .scan_index = -1, /* No buffer support */ #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS .event_spec = &step_detect_event, .num_event_specs = 1, @@ -259,6 +260,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = { .modified = 1, .channel2 = IIO_MOD_RUNNING, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = -1, /* No buffer support */ #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS .event_spec = &iio_running_event, .num_event_specs = 1, @@ -269,6 +271,7 @@ static const struct iio_chan_spec iio_dummy_channels[] = { .modified = 1, .channel2 = IIO_MOD_WALKING, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .scan_index = -1, /* No buffer support */ #ifdef CONFIG_IIO_SIMPLE_DUMMY_EVENTS .event_spec = &iio_walking_event, .num_event_specs = 1, @@ -638,13 +641,7 @@ static int iio_dummy_probe(int index) if (ret < 0) goto error_free_device; - /* - * Configure buffered capture support and register the channels with the - * buffer, but avoid the output channel being registered by reducing the - * number of channels by 1. - */ - ret = iio_simple_dummy_configure_buffer(indio_dev, - iio_dummy_channels, 5); + ret = iio_simple_dummy_configure_buffer(indio_dev); if (ret < 0) goto error_unregister_events; diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h index 3b714b4..af70126 100644 --- a/drivers/staging/iio/iio_simple_dummy.h +++ b/drivers/staging/iio/iio_simple_dummy.h @@ -114,8 +114,7 @@ enum iio_simple_dummy_scan_elements { }; #ifdef CONFIG_IIO_SIMPLE_DUMMY_BUFFER -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels); +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev); void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev); #else static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index fd74f91..35d60d5 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -115,8 +115,7 @@ static const struct iio_buffer_setup_ops iio_simple_dummy_buffer_setup_ops = { .predisable = &iio_triggered_buffer_predisable, }; -int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels) +int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) { int ret; struct iio_buffer *buffer; @@ -173,7 +172,8 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - ret = iio_buffer_register(indio_dev, channels, num_channels); + ret = iio_buffer_register(indio_dev, indio_dev->channels, + indio_dev->num_channels); if (ret) goto error_dealloc_pollfunc; -- cgit v0.10.2 From 3e1b6c95b990c93f4aa3b17e9f66221e2fa44bee Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:12 +0100 Subject: iio: Move buffer registration to the core Originally device and buffer registration were kept as separate operations in IIO to allow to register two distinct sets of channels for buffered and non-buffered operations. This has since already been further restricted and the channel set registered for the buffer needs to be a subset of the channel set registered for the device. Additionally the possibility to not have a raw (or processed) attribute for a channel which was registered for the device was added a while ago. This means it is possible to not register any device level attributes for a channel even if it is registered for the device. Also if a channel's scan_index is set to -1 and the channel is registered for the buffer it is ignored. So in summary it means it is possible to register the same channel array for both the device and the buffer yet still end up with distinctive sets of channels for both of them. This makes the argument for having to have to manually register the channels for both the device and the buffer invalid. Considering that the vast majority of all drivers want to register the same set of channels for both the buffer and the device it makes sense to move the buffer registration into the core to avoid some boiler-plate code in the device driver setup path. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index b730864..d550ac7 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -264,16 +264,8 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, indio_dev->setup_ops = setup_ops; indio_dev->modes |= INDIO_BUFFER_HARDWARE; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_free_irq; - return 0; -error_free_irq: - free_irq(irq, indio_dev); error_kfifo_free: iio_kfifo_free(indio_dev->buffer); return ret; @@ -285,7 +277,6 @@ static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev) free_irq(adc_dev->mfd_tscadc->irq, indio_dev); iio_kfifo_free(indio_dev->buffer); - iio_buffer_unregister(indio_dev); } diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h index 5f0ea77..3598835 100644 --- a/drivers/iio/iio_core.h +++ b/drivers/iio/iio_core.h @@ -48,6 +48,8 @@ unsigned int iio_buffer_poll(struct file *filp, ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf, size_t n, loff_t *f_ps); +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev); +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev); #define iio_buffer_poll_addr (&iio_buffer_poll) #define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer) @@ -60,6 +62,13 @@ void iio_buffer_wakeup_poll(struct iio_dev *indio_dev); #define iio_buffer_poll_addr NULL #define iio_buffer_read_first_n_outer_addr NULL +static inline int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) +{ + return 0; +} + +static inline void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) {} + static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {} static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {} diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index f667e4e..8bb3e64 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -385,14 +385,16 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, static const char * const iio_scan_elements_group_name = "scan_elements"; -int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels) +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) { struct iio_dev_attr *p; struct attribute **attr; struct iio_buffer *buffer = indio_dev->buffer; int ret, i, attrn, attrcount, attrcount_orig = 0; + const struct iio_chan_spec *channels; + + if (!buffer) + return 0; if (buffer->attrs) indio_dev->groups[indio_dev->groupcounter++] = buffer->attrs; @@ -404,9 +406,10 @@ int iio_buffer_register(struct iio_dev *indio_dev, } attrcount = attrcount_orig; INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list); + channels = indio_dev->channels; if (channels) { /* new magic */ - for (i = 0; i < num_channels; i++) { + for (i = 0; i < indio_dev->num_channels; i++) { if (channels[i].scan_index < 0) continue; @@ -463,15 +466,16 @@ error_cleanup_dynamic: return ret; } -EXPORT_SYMBOL(iio_buffer_register); -void iio_buffer_unregister(struct iio_dev *indio_dev) +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) { + if (!indio_dev->buffer) + return; + kfree(indio_dev->buffer->scan_mask); kfree(indio_dev->buffer->scan_el_group.attrs); iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list); } -EXPORT_SYMBOL(iio_buffer_unregister); ssize_t iio_buffer_read_length(struct device *dev, struct device_attribute *attr, diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 45bb3a4..ee442ee 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1158,11 +1158,19 @@ int iio_device_register(struct iio_dev *indio_dev) "Failed to register debugfs interfaces\n"); return ret; } + + ret = iio_buffer_alloc_sysfs_and_mask(indio_dev); + if (ret) { + dev_err(indio_dev->dev.parent, + "Failed to create buffer sysfs interfaces\n"); + goto error_unreg_debugfs; + } + ret = iio_device_register_sysfs(indio_dev); if (ret) { dev_err(indio_dev->dev.parent, "Failed to register sysfs interfaces\n"); - goto error_unreg_debugfs; + goto error_buffer_free_sysfs; } ret = iio_device_register_eventset(indio_dev); if (ret) { @@ -1195,6 +1203,8 @@ error_unreg_eventset: iio_device_unregister_eventset(indio_dev); error_free_sysfs: iio_device_unregister_sysfs(indio_dev); +error_buffer_free_sysfs: + iio_buffer_free_sysfs_and_mask(indio_dev); error_unreg_debugfs: iio_device_unregister_debugfs(indio_dev); return ret; @@ -1223,6 +1233,8 @@ void iio_device_unregister(struct iio_dev *indio_dev) iio_buffer_wakeup_poll(indio_dev); mutex_unlock(&indio_dev->info_exist_lock); + + iio_buffer_free_sysfs_and_mask(indio_dev); } EXPORT_SYMBOL(iio_device_unregister); diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/industrialio-triggered-buffer.c index d6f54930..61a5d04 100644 --- a/drivers/iio/industrialio-triggered-buffer.c +++ b/drivers/iio/industrialio-triggered-buffer.c @@ -32,7 +32,7 @@ static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { * * This function combines some common tasks which will normally be performed * when setting up a triggered buffer. It will allocate the buffer and the - * pollfunc, as well as register the buffer with the IIO core. + * pollfunc. * * Before calling this function the indio_dev structure should already be * completely initialized, but not yet registered. In practice this means that @@ -78,16 +78,8 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev, /* Flag that polled ring buffering is possible */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - ret = iio_buffer_register(indio_dev, - indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_dealloc_pollfunc; - return 0; -error_dealloc_pollfunc: - iio_dealloc_pollfunc(indio_dev->pollfunc); error_kfifo_free: iio_kfifo_free(indio_dev->buffer); error_ret: @@ -101,7 +93,6 @@ EXPORT_SYMBOL(iio_triggered_buffer_setup); */ void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev) { - iio_buffer_unregister(indio_dev); iio_dealloc_pollfunc(indio_dev->pollfunc); iio_kfifo_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index f5e145c..b78c9c5 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -716,14 +716,6 @@ static int lis3l02dq_probe(struct spi_device *spi) if (ret) return ret; - ret = iio_buffer_register(indio_dev, - lis3l02dq_channels, - ARRAY_SIZE(lis3l02dq_channels)); - if (ret) { - dev_err(&spi->dev, "failed to initialize the buffer\n"); - goto error_unreg_buffer_funcs; - } - if (spi->irq) { ret = request_threaded_irq(st->us->irq, &lis3l02dq_th, @@ -732,7 +724,7 @@ static int lis3l02dq_probe(struct spi_device *spi) "lis3l02dq", indio_dev); if (ret) - goto error_uninitialize_buffer; + goto error_unreg_buffer_funcs; ret = lis3l02dq_probe_trigger(indio_dev); if (ret) @@ -756,8 +748,6 @@ error_remove_trigger: error_free_interrupt: if (spi->irq) free_irq(st->us->irq, indio_dev); -error_uninitialize_buffer: - iio_buffer_unregister(indio_dev); error_unreg_buffer_funcs: lis3l02dq_unconfigure_buffer(indio_dev); return ret; @@ -804,7 +794,6 @@ static int lis3l02dq_remove(struct spi_device *spi) free_irq(st->us->irq, indio_dev); lis3l02dq_remove_trigger(indio_dev); - iio_buffer_unregister(indio_dev); lis3l02dq_unconfigure_buffer(indio_dev); return 0; diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index aef8c91..9cd04c7 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -1156,11 +1156,6 @@ static int sca3000_probe(struct spi_device *spi) if (ret < 0) return ret; - ret = iio_buffer_register(indio_dev, indio_dev->channels, - indio_dev->num_channels); - if (ret < 0) - goto error_unregister_dev; - if (spi->irq) { ret = request_threaded_irq(spi->irq, NULL, @@ -1169,7 +1164,7 @@ static int sca3000_probe(struct spi_device *spi) "sca3000", indio_dev); if (ret) - goto error_unregister_ring; + goto error_unregister_dev; } sca3000_register_ring_funcs(indio_dev); ret = sca3000_clean_setup(st); @@ -1180,8 +1175,6 @@ static int sca3000_probe(struct spi_device *spi) error_free_irq: if (spi->irq) free_irq(spi->irq, indio_dev); -error_unregister_ring: - iio_buffer_unregister(indio_dev); error_unregister_dev: iio_device_unregister(indio_dev); return ret; @@ -1215,7 +1208,6 @@ static int sca3000_remove(struct spi_device *spi) if (spi->irq) free_irq(spi->irq, indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); sca3000_unconfigure_ring(indio_dev); return 0; diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index 35d60d5..a2d72c1 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -172,15 +172,8 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - ret = iio_buffer_register(indio_dev, indio_dev->channels, - indio_dev->num_channels); - if (ret) - goto error_dealloc_pollfunc; - return 0; -error_dealloc_pollfunc: - iio_dealloc_pollfunc(indio_dev->pollfunc); error_free_buffer: iio_kfifo_free(indio_dev->buffer); error_ret: @@ -194,7 +187,6 @@ error_ret: */ void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev) { - iio_buffer_unregister(indio_dev); iio_dealloc_pollfunc(indio_dev->pollfunc); iio_kfifo_free(indio_dev->buffer); } diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index aa6a368..c50b138 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -752,23 +752,16 @@ static int ad5933_probe(struct i2c_client *client, if (ret) goto error_disable_reg; - ret = iio_buffer_register(indio_dev, ad5933_channels, - ARRAY_SIZE(ad5933_channels)); - if (ret) - goto error_unreg_ring; - ret = ad5933_setup(st); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring; ret = iio_device_register(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring; return 0; -error_uninitialize_ring: - iio_buffer_unregister(indio_dev); error_unreg_ring: iio_kfifo_free(indio_dev->buffer); error_disable_reg: @@ -784,7 +777,6 @@ static int ad5933_remove(struct i2c_client *client) struct ad5933_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - iio_buffer_unregister(indio_dev); iio_kfifo_free(indio_dev->buffer); if (!IS_ERR(st->reg)) regulator_disable(st->reg); diff --git a/drivers/staging/iio/meter/ade7758.h b/drivers/staging/iio/meter/ade7758.h index 0731820..762d7dc 100644 --- a/drivers/staging/iio/meter/ade7758.h +++ b/drivers/staging/iio/meter/ade7758.h @@ -146,7 +146,6 @@ ssize_t ade7758_read_data_from_ring(struct device *dev, int ade7758_configure_ring(struct iio_dev *indio_dev); void ade7758_unconfigure_ring(struct iio_dev *indio_dev); -void ade7758_uninitialize_ring(struct iio_dev *indio_dev); int ade7758_set_irq(struct device *dev, bool enable); int ade7758_spi_write_reg_8(struct device *dev, diff --git a/drivers/staging/iio/meter/ade7758_core.c b/drivers/staging/iio/meter/ade7758_core.c index abc6006..6e8b011 100644 --- a/drivers/staging/iio/meter/ade7758_core.c +++ b/drivers/staging/iio/meter/ade7758_core.c @@ -885,23 +885,15 @@ static int ade7758_probe(struct spi_device *spi) if (ret) goto error_free_tx; - ret = iio_buffer_register(indio_dev, - &ade7758_channels[0], - ARRAY_SIZE(ade7758_channels)); - if (ret) { - dev_err(&spi->dev, "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } - /* Get the device into a sane initial state */ ret = ade7758_initial_setup(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring_funcs; if (spi->irq) { ret = ade7758_probe_trigger(indio_dev); if (ret) - goto error_uninitialize_ring; + goto error_unreg_ring_funcs; } ret = iio_device_register(indio_dev); @@ -913,8 +905,6 @@ static int ade7758_probe(struct spi_device *spi) error_remove_trigger: if (spi->irq) ade7758_remove_trigger(indio_dev); -error_uninitialize_ring: - ade7758_uninitialize_ring(indio_dev); error_unreg_ring_funcs: ade7758_unconfigure_ring(indio_dev); error_free_tx: @@ -932,7 +922,6 @@ static int ade7758_remove(struct spi_device *spi) iio_device_unregister(indio_dev); ade7758_stop_device(&indio_dev->dev); ade7758_remove_trigger(indio_dev); - ade7758_uninitialize_ring(indio_dev); ade7758_unconfigure_ring(indio_dev); kfree(st->tx); kfree(st->rx); diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index c0accf8..27c3ed6 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -181,8 +181,3 @@ error_iio_kfifo_free: iio_kfifo_free(indio_dev->buffer); return ret; } - -void ade7758_uninitialize_ring(struct iio_dev *indio_dev) -{ - iio_buffer_unregister(indio_dev); -} diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 8c8ce61..b0e006c 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -151,22 +151,6 @@ static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev, int iio_update_demux(struct iio_dev *indio_dev); /** - * iio_buffer_register() - register the buffer with IIO core - * @indio_dev: device with the buffer to be registered - * @channels: the channel descriptions used to construct buffer - * @num_channels: the number of channels - **/ -int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels); - -/** - * iio_buffer_unregister() - unregister the buffer from IIO core - * @indio_dev: the device with the buffer to be unregistered - **/ -void iio_buffer_unregister(struct iio_dev *indio_dev); - -/** * iio_buffer_read_length() - attr func to get number of datums in the buffer **/ ssize_t iio_buffer_read_length(struct device *dev, @@ -223,16 +207,6 @@ static inline void iio_device_attach_buffer(struct iio_dev *indio_dev, #else /* CONFIG_IIO_BUFFER */ -static inline int iio_buffer_register(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, - int num_channels) -{ - return 0; -} - -static inline void iio_buffer_unregister(struct iio_dev *indio_dev) -{} - static inline void iio_buffer_get(struct iio_buffer *buffer) {} static inline void iio_buffer_put(struct iio_buffer *buffer) {} -- cgit v0.10.2 From 616dde2a1ea3df9398b1fcc7d6d6516c5fab6183 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:13 +0100 Subject: iio: Remove get_bytes_per_datum() from iio_buffer_access_funcs There haven't been any users of the get_bytes_per_datum() callback for a while. The core assumes that the number of bytes per datum can be calculated based on the enabled channels and the storage size of the channel and iio_compute_scan_bytes() is used to compute this number. So remove the callback. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 7134e8a..1258b4e 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -66,11 +66,6 @@ static struct attribute_group iio_kfifo_attribute_group = { .name = "buffer", }; -static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r) -{ - return r->bytes_per_datum; -} - static int iio_mark_update_needed_kfifo(struct iio_buffer *r) { struct iio_kfifo *kf = iio_to_kfifo(r); @@ -159,7 +154,6 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = { .read_first_n = &iio_read_first_n_kfifo, .data_available = iio_kfifo_buf_data_available, .request_update = &iio_request_update_kfifo, - .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo, .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, .get_length = &iio_get_length_kfifo, .set_length = &iio_set_length_kfifo, diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt index e1da433..434d63a 100644 --- a/drivers/staging/iio/Documentation/ring.txt +++ b/drivers/staging/iio/Documentation/ring.txt @@ -39,8 +39,8 @@ request_update If parameters have changed that require reinitialization or configuration of the buffer this will trigger it. -get_bytes_per_datum, set_bytes_per_datum - Get/set the number of bytes for a complete scan. (All samples + timestamp) +set_bytes_per_datum + Set the number of bytes for a complete scan. (All samples + timestamp) get_length / set_length Get/set the number of complete scans that may be held by the buffer. diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index 1578276..aa0e5d8 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -135,12 +135,6 @@ static int sca3000_ring_get_length(struct iio_buffer *r) return 64; } -/* only valid if resolution is kept at 11bits */ -static int sca3000_ring_get_bytes_per_datum(struct iio_buffer *r) -{ - return 6; -} - static bool sca3000_ring_buf_data_available(struct iio_buffer *r) { return r->stufftoread; @@ -278,7 +272,6 @@ static void sca3000_ring_release(struct iio_buffer *r) static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { .read_first_n = &sca3000_read_first_n_hw_rb, .get_length = &sca3000_ring_get_length, - .get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum, .data_available = sca3000_ring_buf_data_available, .release = sca3000_ring_release, }; diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index b0e006c..79cdb3d 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -25,7 +25,6 @@ struct iio_buffer; * available. * @request_update: if a parameter change has been marked, update underlying * storage. - * @get_bytes_per_datum:get current bytes per datum * @set_bytes_per_datum:set number of bytes per datum * @get_length: get number of datums in buffer * @set_length: set number of datums in buffer @@ -49,7 +48,6 @@ struct iio_buffer_access_funcs { int (*request_update)(struct iio_buffer *buffer); - int (*get_bytes_per_datum)(struct iio_buffer *buffer); int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); int (*get_length)(struct iio_buffer *buffer); int (*set_length)(struct iio_buffer *buffer, int length); -- cgit v0.10.2 From d967cb6bd4e79c0cd7b150f1382d3d04e00408a0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:14 +0100 Subject: iio: buffer: Move iio_buffer_alloc_sysfs and iio_buffer_free_sysfs The next patch will introduce new dependencies in iio_buffer_alloc_sysfs() to functions which are currently defined after iio_buffer_alloc_sysfs(). To avoid forward declarations move both iio_buffer_alloc_sysfs() and iio_buffer_free_sysfs() after those function. This is split into two patches one moving the functions and one adding the dependencies to make review of the actual changes easier. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 8bb3e64..8cd89eb 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -383,100 +383,6 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, return ret; } -static const char * const iio_scan_elements_group_name = "scan_elements"; - -int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) -{ - struct iio_dev_attr *p; - struct attribute **attr; - struct iio_buffer *buffer = indio_dev->buffer; - int ret, i, attrn, attrcount, attrcount_orig = 0; - const struct iio_chan_spec *channels; - - if (!buffer) - return 0; - - if (buffer->attrs) - indio_dev->groups[indio_dev->groupcounter++] = buffer->attrs; - - if (buffer->scan_el_attrs != NULL) { - attr = buffer->scan_el_attrs->attrs; - while (*attr++ != NULL) - attrcount_orig++; - } - attrcount = attrcount_orig; - INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list); - channels = indio_dev->channels; - if (channels) { - /* new magic */ - for (i = 0; i < indio_dev->num_channels; i++) { - if (channels[i].scan_index < 0) - continue; - - /* Establish necessary mask length */ - if (channels[i].scan_index > - (int)indio_dev->masklength - 1) - indio_dev->masklength - = channels[i].scan_index + 1; - - ret = iio_buffer_add_channel_sysfs(indio_dev, - &channels[i]); - if (ret < 0) - goto error_cleanup_dynamic; - attrcount += ret; - if (channels[i].type == IIO_TIMESTAMP) - indio_dev->scan_index_timestamp = - channels[i].scan_index; - } - if (indio_dev->masklength && buffer->scan_mask == NULL) { - buffer->scan_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), - sizeof(*buffer->scan_mask), - GFP_KERNEL); - if (buffer->scan_mask == NULL) { - ret = -ENOMEM; - goto error_cleanup_dynamic; - } - } - } - - buffer->scan_el_group.name = iio_scan_elements_group_name; - - buffer->scan_el_group.attrs = kcalloc(attrcount + 1, - sizeof(buffer->scan_el_group.attrs[0]), - GFP_KERNEL); - if (buffer->scan_el_group.attrs == NULL) { - ret = -ENOMEM; - goto error_free_scan_mask; - } - if (buffer->scan_el_attrs) - memcpy(buffer->scan_el_group.attrs, buffer->scan_el_attrs, - sizeof(buffer->scan_el_group.attrs[0])*attrcount_orig); - attrn = attrcount_orig; - - list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l) - buffer->scan_el_group.attrs[attrn++] = &p->dev_attr.attr; - indio_dev->groups[indio_dev->groupcounter++] = &buffer->scan_el_group; - - return 0; - -error_free_scan_mask: - kfree(buffer->scan_mask); -error_cleanup_dynamic: - iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list); - - return ret; -} - -void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) -{ - if (!indio_dev->buffer) - return; - - kfree(indio_dev->buffer->scan_mask); - kfree(indio_dev->buffer->scan_el_group.attrs); - iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list); -} - ssize_t iio_buffer_read_length(struct device *dev, struct device_attribute *attr, char *buf) @@ -855,6 +761,97 @@ done: } EXPORT_SYMBOL(iio_buffer_store_enable); +static const char * const iio_scan_elements_group_name = "scan_elements"; + +int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) +{ + struct iio_dev_attr *p; + struct attribute **attr; + struct iio_buffer *buffer = indio_dev->buffer; + int ret, i, attrn, attrcount, attrcount_orig = 0; + const struct iio_chan_spec *channels; + + if (!buffer) + return 0; + + if (buffer->scan_el_attrs != NULL) { + attr = buffer->scan_el_attrs->attrs; + while (*attr++ != NULL) + attrcount_orig++; + } + attrcount = attrcount_orig; + INIT_LIST_HEAD(&buffer->scan_el_dev_attr_list); + channels = indio_dev->channels; + if (channels) { + /* new magic */ + for (i = 0; i < indio_dev->num_channels; i++) { + if (channels[i].scan_index < 0) + continue; + + /* Establish necessary mask length */ + if (channels[i].scan_index > + (int)indio_dev->masklength - 1) + indio_dev->masklength + = channels[i].scan_index + 1; + + ret = iio_buffer_add_channel_sysfs(indio_dev, + &channels[i]); + if (ret < 0) + goto error_cleanup_dynamic; + attrcount += ret; + if (channels[i].type == IIO_TIMESTAMP) + indio_dev->scan_index_timestamp = + channels[i].scan_index; + } + if (indio_dev->masklength && buffer->scan_mask == NULL) { + buffer->scan_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), + sizeof(*buffer->scan_mask), + GFP_KERNEL); + if (buffer->scan_mask == NULL) { + ret = -ENOMEM; + goto error_cleanup_dynamic; + } + } + } + + buffer->scan_el_group.name = iio_scan_elements_group_name; + + buffer->scan_el_group.attrs = kcalloc(attrcount + 1, + sizeof(buffer->scan_el_group.attrs[0]), + GFP_KERNEL); + if (buffer->scan_el_group.attrs == NULL) { + ret = -ENOMEM; + goto error_free_scan_mask; + } + if (buffer->scan_el_attrs) + memcpy(buffer->scan_el_group.attrs, buffer->scan_el_attrs, + sizeof(buffer->scan_el_group.attrs[0])*attrcount_orig); + attrn = attrcount_orig; + + list_for_each_entry(p, &buffer->scan_el_dev_attr_list, l) + buffer->scan_el_group.attrs[attrn++] = &p->dev_attr.attr; + indio_dev->groups[indio_dev->groupcounter++] = &buffer->scan_el_group; + + return 0; + +error_free_scan_mask: + kfree(buffer->scan_mask); +error_cleanup_dynamic: + iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list); + + return ret; +} + +void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) +{ + if (!indio_dev->buffer) + return; + + kfree(indio_dev->buffer->scan_mask); + kfree(indio_dev->buffer->scan_el_group.attrs); + iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list); +} + /** * iio_validate_scan_mask_onehot() - Validates that exactly one channel is selected * @indio_dev: the iio device -- cgit v0.10.2 From 08e7e0adaa17205f86894157d86c4bee3c714330 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:15 +0100 Subject: iio: buffer: Allocate standard attributes in the core All buffers want at least the length and the enable attribute. Move the creation of those attributes to the core instead of having to do this in each individual buffer implementation. This allows us to get rid of some boiler-plate code. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 8cd89eb..ba89357 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -383,9 +383,9 @@ static int iio_buffer_add_channel_sysfs(struct iio_dev *indio_dev, return ret; } -ssize_t iio_buffer_read_length(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t iio_buffer_read_length(struct device *dev, + struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_buffer *buffer = indio_dev->buffer; @@ -396,12 +396,10 @@ ssize_t iio_buffer_read_length(struct device *dev, return 0; } -EXPORT_SYMBOL(iio_buffer_read_length); -ssize_t iio_buffer_write_length(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) +static ssize_t iio_buffer_write_length(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_buffer *buffer = indio_dev->buffer; @@ -428,16 +426,14 @@ ssize_t iio_buffer_write_length(struct device *dev, return ret ? ret : len; } -EXPORT_SYMBOL(iio_buffer_write_length); -ssize_t iio_buffer_show_enable(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t iio_buffer_show_enable(struct device *dev, + struct device_attribute *attr, + char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); return sprintf(buf, "%d\n", iio_buffer_is_active(indio_dev->buffer)); } -EXPORT_SYMBOL(iio_buffer_show_enable); static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const unsigned long *mask, bool timestamp) @@ -724,10 +720,10 @@ out_unlock: } EXPORT_SYMBOL_GPL(iio_update_buffers); -ssize_t iio_buffer_store_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) +static ssize_t iio_buffer_store_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) { int ret; bool requested_state; @@ -759,10 +755,14 @@ done: mutex_unlock(&indio_dev->mlock); return (ret < 0) ? ret : len; } -EXPORT_SYMBOL(iio_buffer_store_enable); static const char * const iio_scan_elements_group_name = "scan_elements"; +static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length, + iio_buffer_write_length); +static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, + iio_buffer_show_enable, iio_buffer_store_enable); + int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) { struct iio_dev_attr *p; @@ -774,6 +774,27 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) if (!buffer) return 0; + attrcount = 0; + if (buffer->attrs) { + while (buffer->attrs[attrcount] != NULL) + attrcount++; + } + + buffer->buffer_group.name = "buffer"; + buffer->buffer_group.attrs = kcalloc(attrcount + 3, + sizeof(*buffer->buffer_group.attrs), GFP_KERNEL); + if (!buffer->buffer_group.attrs) + return -ENOMEM; + + buffer->buffer_group.attrs[0] = &dev_attr_length.attr; + buffer->buffer_group.attrs[1] = &dev_attr_enable.attr; + if (buffer->attrs) + memcpy(&buffer->buffer_group.attrs[2], buffer->attrs, + sizeof(*&buffer->buffer_group.attrs) * (attrcount - 2)); + buffer->buffer_group.attrs[attrcount+2] = NULL; + + indio_dev->groups[indio_dev->groupcounter++] = &buffer->buffer_group; + if (buffer->scan_el_attrs != NULL) { attr = buffer->scan_el_attrs->attrs; while (*attr++ != NULL) @@ -838,6 +859,7 @@ error_free_scan_mask: kfree(buffer->scan_mask); error_cleanup_dynamic: iio_free_chan_devattr_list(&buffer->scan_el_dev_attr_list); + kfree(indio_dev->buffer->buffer_group.attrs); return ret; } @@ -848,6 +870,7 @@ void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) return; kfree(indio_dev->buffer->scan_mask); + kfree(indio_dev->buffer->buffer_group.attrs); kfree(indio_dev->buffer->scan_el_group.attrs); iio_free_chan_devattr_list(&indio_dev->buffer->scan_el_dev_attr_list); } diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 1258b4e..3b0a3bc 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -52,20 +52,6 @@ static int iio_get_length_kfifo(struct iio_buffer *r) return r->length; } -static IIO_BUFFER_ENABLE_ATTR; -static IIO_BUFFER_LENGTH_ATTR; - -static struct attribute *iio_kfifo_attributes[] = { - &dev_attr_length.attr, - &dev_attr_enable.attr, - NULL, -}; - -static struct attribute_group iio_kfifo_attribute_group = { - .attrs = iio_kfifo_attributes, - .name = "buffer", -}; - static int iio_mark_update_needed_kfifo(struct iio_buffer *r) { struct iio_kfifo *kf = iio_to_kfifo(r); @@ -169,7 +155,6 @@ struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) return NULL; kf->update_needed = true; iio_buffer_init(&kf->buffer); - kf->buffer.attrs = &iio_kfifo_attribute_group; kf->buffer.access = &kfifo_access_funcs; kf->buffer.length = 2; mutex_init(&kf->user_lock); diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index aa0e5d8..f2f260e 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -140,9 +140,6 @@ static bool sca3000_ring_buf_data_available(struct iio_buffer *r) return r->stufftoread; } -static IIO_BUFFER_ENABLE_ATTR; -static IIO_BUFFER_LENGTH_ATTR; - /** * sca3000_query_ring_int() is the hardware ring status interrupt enabled **/ @@ -232,20 +229,13 @@ static IIO_DEVICE_ATTR(in_accel_scale, * only apply to the ring buffer. At all times full rate and accuracy * is available via direct reading from registers. */ -static struct attribute *sca3000_ring_attributes[] = { - &dev_attr_length.attr, - &dev_attr_enable.attr, +static const struct attribute *sca3000_ring_attributes[] = { &iio_dev_attr_50_percent.dev_attr.attr, &iio_dev_attr_75_percent.dev_attr.attr, &iio_dev_attr_in_accel_scale.dev_attr.attr, NULL, }; -static struct attribute_group sca3000_ring_attr = { - .attrs = sca3000_ring_attributes, - .name = "buffer", -}; - static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) { struct iio_buffer *buf; @@ -258,7 +248,7 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) ring->private = indio_dev; buf = &ring->buf; buf->stufftoread = 0; - buf->attrs = &sca3000_ring_attr; + buf->attrs = sca3000_ring_attributes; iio_buffer_init(buf); return buf; diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 79cdb3d..16b7663 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -83,10 +83,11 @@ struct iio_buffer { bool scan_timestamp; const struct iio_buffer_access_funcs *access; struct list_head scan_el_dev_attr_list; + struct attribute_group buffer_group; struct attribute_group scan_el_group; wait_queue_head_t pollq; bool stufftoread; - const struct attribute_group *attrs; + const struct attribute **attrs; struct list_head demux_list; void *demux_bounce; struct list_head buffer_list; @@ -148,40 +149,6 @@ static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev, int iio_update_demux(struct iio_dev *indio_dev); -/** - * iio_buffer_read_length() - attr func to get number of datums in the buffer - **/ -ssize_t iio_buffer_read_length(struct device *dev, - struct device_attribute *attr, - char *buf); -/** - * iio_buffer_write_length() - attr func to set number of datums in the buffer - **/ -ssize_t iio_buffer_write_length(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_buffer_store_enable() - attr to turn the buffer on - **/ -ssize_t iio_buffer_store_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len); -/** - * iio_buffer_show_enable() - attr to see if the buffer is on - **/ -ssize_t iio_buffer_show_enable(struct device *dev, - struct device_attribute *attr, - char *buf); -#define IIO_BUFFER_LENGTH_ATTR DEVICE_ATTR(length, S_IRUGO | S_IWUSR, \ - iio_buffer_read_length, \ - iio_buffer_write_length) - -#define IIO_BUFFER_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \ - iio_buffer_show_enable, \ - iio_buffer_store_enable) - bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev, const unsigned long *mask); -- cgit v0.10.2 From 8d92db2827b68206f6930e79132243416183e083 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:16 +0100 Subject: iio: buffer: Make length attribute read only for buffers without set_length If a buffer implementation does not implement the set_length() callback the length will be static and can not be changed by userspace. Mark the length attribute as a read only property in this case so userspace is aware of this rather than just silently accepting any length value. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index ba89357..4ca4c0a 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -418,8 +418,7 @@ static ssize_t iio_buffer_write_length(struct device *dev, if (iio_buffer_is_active(indio_dev->buffer)) { ret = -EBUSY; } else { - if (buffer->access->set_length) - buffer->access->set_length(buffer, val); + buffer->access->set_length(buffer, val); ret = 0; } mutex_unlock(&indio_dev->mlock); @@ -760,6 +759,8 @@ static const char * const iio_scan_elements_group_name = "scan_elements"; static DEVICE_ATTR(length, S_IRUGO | S_IWUSR, iio_buffer_read_length, iio_buffer_write_length); +static struct device_attribute dev_attr_length_ro = __ATTR(length, + S_IRUGO, iio_buffer_read_length, NULL); static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, iio_buffer_show_enable, iio_buffer_store_enable); @@ -786,7 +787,10 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) if (!buffer->buffer_group.attrs) return -ENOMEM; - buffer->buffer_group.attrs[0] = &dev_attr_length.attr; + if (buffer->access->set_length) + buffer->buffer_group.attrs[0] = &dev_attr_length.attr; + else + buffer->buffer_group.attrs[0] = &dev_attr_length_ro.attr; buffer->buffer_group.attrs[1] = &dev_attr_enable.attr; if (buffer->attrs) memcpy(&buffer->buffer_group.attrs[2], buffer->attrs, -- cgit v0.10.2 From 374956600ecbedf5ca29c76bde114160eb805091 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 26 Nov 2014 18:55:17 +0100 Subject: iio: buffer: Drop get_length callback We already do have the length field in the struct iio_buffer which is expected to be in sync with the current size of the buffer. And currently all implementations of the get_length callback either return this field or a constant number. This patch removes the get_length callback and replaces all occurrences in the IIO core with directly accessing the length field of the buffer. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 4ca4c0a..2bd8d39 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -390,11 +390,7 @@ static ssize_t iio_buffer_read_length(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_buffer *buffer = indio_dev->buffer; - if (buffer->access->get_length) - return sprintf(buf, "%d\n", - buffer->access->get_length(buffer)); - - return 0; + return sprintf(buf, "%d\n", buffer->length); } static ssize_t iio_buffer_write_length(struct device *dev, @@ -410,9 +406,8 @@ static ssize_t iio_buffer_write_length(struct device *dev, if (ret) return ret; - if (buffer->access->get_length) - if (val == buffer->access->get_length(buffer)) - return len; + if (val == buffer->length) + return len; mutex_lock(&indio_dev->mlock); if (iio_buffer_is_active(indio_dev->buffer)) { diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 3b0a3bc..b20a9cf 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -47,11 +47,6 @@ static int iio_request_update_kfifo(struct iio_buffer *r) return ret; } -static int iio_get_length_kfifo(struct iio_buffer *r) -{ - return r->length; -} - static int iio_mark_update_needed_kfifo(struct iio_buffer *r) { struct iio_kfifo *kf = iio_to_kfifo(r); @@ -141,7 +136,6 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = { .data_available = iio_kfifo_buf_data_available, .request_update = &iio_request_update_kfifo, .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, - .get_length = &iio_get_length_kfifo, .set_length = &iio_set_length_kfifo, .release = &iio_kfifo_buffer_release, }; diff --git a/drivers/staging/iio/Documentation/ring.txt b/drivers/staging/iio/Documentation/ring.txt index 434d63a..18718fc 100644 --- a/drivers/staging/iio/Documentation/ring.txt +++ b/drivers/staging/iio/Documentation/ring.txt @@ -42,6 +42,6 @@ request_update set_bytes_per_datum Set the number of bytes for a complete scan. (All samples + timestamp) -get_length / set_length - Get/set the number of complete scans that may be held by the buffer. +set_length + Set the number of complete scans that may be held by the buffer. diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index f2f260e..f76a268 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -129,12 +129,6 @@ error_ret: return ret ? ret : num_read; } -/* This is only valid with all 3 elements enabled */ -static int sca3000_ring_get_length(struct iio_buffer *r) -{ - return 64; -} - static bool sca3000_ring_buf_data_available(struct iio_buffer *r) { return r->stufftoread; @@ -248,6 +242,7 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) ring->private = indio_dev; buf = &ring->buf; buf->stufftoread = 0; + buf->length = 64; buf->attrs = sca3000_ring_attributes; iio_buffer_init(buf); @@ -261,7 +256,6 @@ static void sca3000_ring_release(struct iio_buffer *r) static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = { .read_first_n = &sca3000_read_first_n_hw_rb, - .get_length = &sca3000_ring_get_length, .data_available = sca3000_ring_buf_data_available, .release = sca3000_ring_release, }; diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index 16b7663..b65850a 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -26,7 +26,6 @@ struct iio_buffer; * @request_update: if a parameter change has been marked, update underlying * storage. * @set_bytes_per_datum:set number of bytes per datum - * @get_length: get number of datums in buffer * @set_length: set number of datums in buffer * @release: called when the last reference to the buffer is dropped, * should free all resources allocated by the buffer. @@ -49,7 +48,6 @@ struct iio_buffer_access_funcs { int (*request_update)(struct iio_buffer *buffer); int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); - int (*get_length)(struct iio_buffer *buffer); int (*set_length)(struct iio_buffer *buffer, int length); void (*release)(struct iio_buffer *buffer); -- cgit v0.10.2 From fbd123e913ed25ec861ce3be10725b5beb27ab48 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Wed, 10 Dec 2014 18:23:53 +0200 Subject: iio: accel: kxcjk-1013: error handling when set mode fails If there is an error in set mode at runtime resume, reset the state of the runtime usage count. If there is an error in set mode at runtime suspend, make sure the framework retries to suspend the device. Signed-off-by: Irina Tirdea Reviewed-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 7b0a9da..0dc6ccf 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -388,6 +388,8 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) if (ret < 0) { dev_err(&data->client->dev, "Failed: kxcjk1013_set_power_state for %d\n", on); + if (on) + pm_runtime_put_noidle(&data->client->dev); return ret; } #endif @@ -859,6 +861,8 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev, ret = kxcjk1013_setup_any_motion_interrupt(data, state); if (ret < 0) { + kxcjk1013_set_power_state(data, false); + data->ev_enable_state = 0; mutex_unlock(&data->mutex); return ret; } @@ -1009,6 +1013,7 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig, else ret = kxcjk1013_setup_new_data_interrupt(data, state); if (ret < 0) { + kxcjk1013_set_power_state(data, false); mutex_unlock(&data->mutex); return ret; } @@ -1368,8 +1373,14 @@ static int kxcjk1013_runtime_suspend(struct device *dev) { struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct kxcjk1013_data *data = iio_priv(indio_dev); + int ret; - return kxcjk1013_set_mode(data, STANDBY); + ret = kxcjk1013_set_mode(data, STANDBY); + if (ret < 0) { + dev_err(&data->client->dev, "powering off device failed\n"); + return -EAGAIN; + } + return 0; } static int kxcjk1013_runtime_resume(struct device *dev) -- cgit v0.10.2 From 9d02daf738bf01b9d89d4de2b74ed3bc9bebbb40 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Wed, 10 Dec 2014 18:23:54 +0200 Subject: iio: accel: kxcjk-1013: power off device if probe fails When the device is initialized in probe, it is also powered on. If there is an error after the initialization, the device will remain powered on. Power off the device in case probe fails after device initialization. Signed-off-by: Irina Tirdea Suggested-by: Daniel Baluta Reviewed-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 0dc6ccf..a5e7d30 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1240,21 +1240,25 @@ static int kxcjk1013_probe(struct i2c_client *client, KXCJK1013_IRQ_NAME, indio_dev); if (ret) - return ret; + goto err_poweroff; data->dready_trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", indio_dev->name, indio_dev->id); - if (!data->dready_trig) - return -ENOMEM; + if (!data->dready_trig) { + ret = -ENOMEM; + goto err_poweroff; + } data->motion_trig = devm_iio_trigger_alloc(&client->dev, "%s-any-motion-dev%d", indio_dev->name, indio_dev->id); - if (!data->motion_trig) - return -ENOMEM; + if (!data->motion_trig) { + ret = -ENOMEM; + goto err_poweroff; + } data->dready_trig->dev.parent = &client->dev; data->dready_trig->ops = &kxcjk1013_trigger_ops; @@ -1263,7 +1267,7 @@ static int kxcjk1013_probe(struct i2c_client *client, iio_trigger_get(indio_dev->trig); ret = iio_trigger_register(data->dready_trig); if (ret) - return ret; + goto err_poweroff; data->motion_trig->dev.parent = &client->dev; data->motion_trig->ops = &kxcjk1013_trigger_ops; @@ -1312,6 +1316,8 @@ err_trigger_unregister: iio_trigger_unregister(data->dready_trig); if (data->motion_trig) iio_trigger_unregister(data->motion_trig); +err_poweroff: + kxcjk1013_set_mode(data, STANDBY); return ret; } -- cgit v0.10.2 From 09546a30632fd35996373146657d5a0296fd37ca Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Tue, 23 Sep 2014 15:51:42 +0300 Subject: iio: consumer.h: Fix scale factor in function comment 1 milivolt is equal to 1000000 nanovolts. Signed-off-by: Ivan T. Ivanov Signed-off-by: Jonathan Cameron diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 6f64624..26fb8f6 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -201,7 +201,7 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val, * The scale factor allows to increase the precession of the returned value. For * a scale factor of 1 the function will return the result in the normal IIO * unit for the channel type. E.g. millivolt for voltage channels, if you want - * nanovolts instead pass 1000 as the scale factor. + * nanovolts instead pass 1000000 as the scale factor. */ int iio_convert_raw_to_processed(struct iio_channel *chan, int raw, int *processed, unsigned int scale); -- cgit v0.10.2 From 7f1c2cbbdaf7da1036bfbf13615081bae72ed33a Mon Sep 17 00:00:00 2001 From: Adam Thomson Date: Tue, 25 Nov 2014 18:25:39 +0000 Subject: iio: Add ABI documentation for input current readings Add information on in_current related readings. Signed-off-by: Adam Thomson Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 4a9e29a..df5e69e 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -92,6 +92,18 @@ Description: is required is a consistent labeling. Units after application of scale and offset are millivolts. +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_raw +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_raw +KernelVersion: 3.17 +Contact: linux-iio@vger.kernel.org +Description: + Raw (unscaled no bias removal etc.) current measurement from + channel Y. In special cases where the channel does not + correspond to externally available input one of the named + versions may be used. The number must always be specified and + unique to allow association with event codes. Units after + application of scale and offset are milliamps. + What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw KernelVersion: 3.2 Contact: linux-iio@vger.kernel.org @@ -234,6 +246,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_offset What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_offset What: /sys/bus/iio/devices/iio:deviceX/in_voltage_offset +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_offset +What: /sys/bus/iio/devices/iio:deviceX/in_current_offset What: /sys/bus/iio/devices/iio:deviceX/in_tempY_offset What: /sys/bus/iio/devices/iio:deviceX/in_temp_offset What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset @@ -262,6 +276,9 @@ What: /sys/bus/iio/devices/iio:deviceX/in_voltage_scale What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_scale What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_scale What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_scale +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_scale +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_scale +What: /sys/bus/iio/devices/iio:deviceX/in_current_scale What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale What: /sys/bus/iio/devices/iio:deviceX/in_accel_peak_scale What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_scale -- cgit v0.10.2 From c78b91716340da82f57b974ee5f52d33103f9231 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 24 Nov 2014 11:43:15 +0200 Subject: iio: add driver for Freescale MMA9551L Add support for Freescale MMA9551L Intelligent Motion-Sensing Platform. The driver supports raw reads for acceleration and inclination, as well as configuring inclination rate-of-change events. The events can be used similarly to an Android sensor Tilt event. The specifications can be downloaded from: http://www.freescale.com/files/sensors/doc/ref_manual/MMA955xLSWRM.pdf Signed-off-by: Irina Tirdea Signed-off-by: Vlad Dogaru Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 9b9be87..d80616d 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -105,4 +105,14 @@ config KXCJK1013 To compile this driver as a module, choose M here: the module will be called kxcjk-1013. +config MMA9551 + tristate "Freescale MMA9551L Intelligent Motion-Sensing Platform Driver" + depends on I2C + help + Say yes here to build support for the Freescale MMA9551L + Intelligent Motion-Sensing Platform Driver. + + To compile this driver as a module, choose M here: the module + will be called mma9551. + endmenu diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index a593996..de5b9cb 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o obj-$(CONFIG_MMA8452) += mma8452.o +obj-$(CONFIG_MMA9551) += mma9551.o obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o st_accel-y := st_accel_core.o diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c new file mode 100644 index 0000000..1be125b --- /dev/null +++ b/drivers/iio/accel/mma9551.c @@ -0,0 +1,954 @@ +/* + * Freescale MMA9551L Intelligent Motion-Sensing Platform driver + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MMA9551_DRV_NAME "mma9551" +#define MMA9551_IRQ_NAME "mma9551_event" +#define MMA9551_GPIO_NAME "mma9551_int" +#define MMA9551_GPIO_COUNT 4 + +/* Applications IDs */ +#define MMA9551_APPID_VERSION 0x00 +#define MMA9551_APPID_GPIO 0x03 +#define MMA9551_APPID_AFE 0x06 +#define MMA9551_APPID_TILT 0x0B +#define MMA9551_APPID_SLEEP_WAKE 0x12 +#define MMA9551_APPID_RESET 0x17 +#define MMA9551_APPID_NONE 0xff + +/* Command masks for mailbox write command */ +#define MMA9551_CMD_READ_VERSION_INFO 0x00 +#define MMA9551_CMD_READ_CONFIG 0x10 +#define MMA9551_CMD_WRITE_CONFIG 0x20 +#define MMA9551_CMD_READ_STATUS 0x30 + +enum mma9551_gpio_pin { + mma9551_gpio6 = 0, + mma9551_gpio7, + mma9551_gpio8, + mma9551_gpio9, + mma9551_gpio_max = mma9551_gpio9, +}; + +/* Mailbox read command */ +#define MMA9551_RESPONSE_COCO BIT(7) + +/* Error-Status codes returned in mailbox read command */ +#define MMA9551_MCI_ERROR_NONE 0x00 +#define MMA9551_MCI_ERROR_PARAM 0x04 +#define MMA9551_MCI_INVALID_COUNT 0x19 +#define MMA9551_MCI_ERROR_COMMAND 0x1C +#define MMA9551_MCI_ERROR_INVALID_LENGTH 0x21 +#define MMA9551_MCI_ERROR_FIFO_BUSY 0x22 +#define MMA9551_MCI_ERROR_FIFO_ALLOCATED 0x23 +#define MMA9551_MCI_ERROR_FIFO_OVERSIZE 0x24 + +/* GPIO Application */ +#define MMA9551_GPIO_POL_MSB 0x08 +#define MMA9551_GPIO_POL_LSB 0x09 + +/* Sleep/Wake application */ +#define MMA9551_SLEEP_CFG 0x06 +#define MMA9551_SLEEP_CFG_SNCEN BIT(0) +#define MMA9551_SLEEP_CFG_SCHEN BIT(2) + +/* AFE application */ +#define MMA9551_AFE_X_ACCEL_REG 0x00 +#define MMA9551_AFE_Y_ACCEL_REG 0x02 +#define MMA9551_AFE_Z_ACCEL_REG 0x04 + +/* Tilt application (inclination in IIO terms). */ +#define MMA9551_TILT_XZ_ANG_REG 0x00 +#define MMA9551_TILT_YZ_ANG_REG 0x01 +#define MMA9551_TILT_XY_ANG_REG 0x02 +#define MMA9551_TILT_ANGFLG BIT(7) +#define MMA9551_TILT_QUAD_REG 0x03 +#define MMA9551_TILT_XY_QUAD_SHIFT 0 +#define MMA9551_TILT_YZ_QUAD_SHIFT 2 +#define MMA9551_TILT_XZ_QUAD_SHIFT 4 +#define MMA9551_TILT_CFG_REG 0x01 +#define MMA9551_TILT_ANG_THRESH_MASK GENMASK(3, 0) + +/* Tilt events are mapped to the first three GPIO pins. */ +enum mma9551_tilt_axis { + mma9551_x = 0, + mma9551_y, + mma9551_z, +}; + +/* + * A response is composed of: + * - control registers: MB0-3 + * - data registers: MB4-31 + * + * A request is composed of: + * - mbox to write to (always 0) + * - control registers: MB1-4 + * - data registers: MB5-31 + */ +#define MMA9551_MAILBOX_CTRL_REGS 4 +#define MMA9551_MAX_MAILBOX_DATA_REGS 28 +#define MMA9551_MAILBOX_REGS 32 + +#define MMA9551_I2C_READ_RETRIES 5 +#define MMA9551_I2C_READ_DELAY 50 /* us */ + +struct mma9551_mbox_request { + u8 start_mbox; /* Always 0. */ + u8 app_id; + /* + * See Section 5.3.1 of the MMA955xL Software Reference Manual. + * + * Bit 7: reserved, always 0 + * Bits 6-4: command + * Bits 3-0: upper bits of register offset + */ + u8 cmd_off; + u8 lower_off; + u8 nbytes; + u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS - 1]; +} __packed; + +struct mma9551_mbox_response { + u8 app_id; + /* + * See Section 5.3.3 of the MMA955xL Software Reference Manual. + * + * Bit 7: COCO + * Bits 6-0: Error code. + */ + u8 coco_err; + u8 nbytes; + u8 req_bytes; + u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS]; +} __packed; + +struct mma9551_version_info { + __be32 device_id; + u8 rom_version[2]; + u8 fw_version[2]; + u8 hw_version[2]; + u8 fw_build[2]; +}; + +struct mma9551_data { + struct i2c_client *client; + struct mutex mutex; + int event_enabled[3]; + int irqs[MMA9551_GPIO_COUNT]; +}; + +static int mma9551_transfer(struct i2c_client *client, + u8 app_id, u8 command, u16 offset, + u8 *inbytes, int num_inbytes, + u8 *outbytes, int num_outbytes) +{ + struct mma9551_mbox_request req; + struct mma9551_mbox_response rsp; + struct i2c_msg in, out; + u8 req_len, err_code; + int ret, retries; + + if (offset >= 1 << 12) { + dev_err(&client->dev, "register offset too large\n"); + return -EINVAL; + } + + req_len = 1 + MMA9551_MAILBOX_CTRL_REGS + num_inbytes; + req.start_mbox = 0; + req.app_id = app_id; + req.cmd_off = command | (offset >> 8); + req.lower_off = offset; + + if (command == MMA9551_CMD_WRITE_CONFIG) + req.nbytes = num_inbytes; + else + req.nbytes = num_outbytes; + if (num_inbytes) + memcpy(req.buf, inbytes, num_inbytes); + + out.addr = client->addr; + out.flags = 0; + out.len = req_len; + out.buf = (u8 *)&req; + + ret = i2c_transfer(client->adapter, &out, 1); + if (ret < 0) { + dev_err(&client->dev, "i2c write failed\n"); + return ret; + } + + retries = MMA9551_I2C_READ_RETRIES; + do { + udelay(MMA9551_I2C_READ_DELAY); + + in.addr = client->addr; + in.flags = I2C_M_RD; + in.len = sizeof(rsp); + in.buf = (u8 *)&rsp; + + ret = i2c_transfer(client->adapter, &in, 1); + if (ret < 0) { + dev_err(&client->dev, "i2c read failed\n"); + return ret; + } + + if (rsp.coco_err & MMA9551_RESPONSE_COCO) + break; + } while (--retries > 0); + + if (retries == 0) { + dev_err(&client->dev, + "timed out while waiting for command response\n"); + return -ETIMEDOUT; + } + + if (rsp.app_id != app_id) { + dev_err(&client->dev, + "app_id mismatch in response got %02x expected %02x\n", + rsp.app_id, app_id); + return -EINVAL; + } + + err_code = rsp.coco_err & ~MMA9551_RESPONSE_COCO; + if (err_code != MMA9551_MCI_ERROR_NONE) { + dev_err(&client->dev, "read returned error %x\n", err_code); + return -EINVAL; + } + + if (rsp.nbytes != rsp.req_bytes) { + dev_err(&client->dev, + "output length mismatch got %d expected %d\n", + rsp.nbytes, rsp.req_bytes); + return -EINVAL; + } + + if (num_outbytes) + memcpy(outbytes, rsp.buf, num_outbytes); + + return 0; +} + +static int mma9551_read_config_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 *val) +{ + return mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, + reg, NULL, 0, val, 1); +} + +static int mma9551_write_config_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 val) +{ + return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg, + &val, 1, NULL, 0); +} + +static int mma9551_read_status_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 *val) +{ + return mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, + reg, NULL, 0, val, 1); +} + +static int mma9551_read_status_word(struct i2c_client *client, u8 app_id, + u16 reg, u16 *val) +{ + int ret; + __be16 v; + + ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, + reg, NULL, 0, (u8 *)&v, 2); + *val = be16_to_cpu(v); + + return ret; +} + +static int mma9551_update_config_bits(struct i2c_client *client, u8 app_id, + u16 reg, u8 mask, u8 val) +{ + int ret; + u8 tmp, orig; + + ret = mma9551_read_config_byte(client, app_id, reg, &orig); + if (ret < 0) + return ret; + + tmp = orig & ~mask; + tmp |= val & mask; + + if (tmp == orig) + return 0; + + return mma9551_write_config_byte(client, app_id, reg, tmp); +} + +/* + * The polarity parameter is described in section 6.2.2, page 66, of the + * Software Reference Manual. Basically, polarity=0 means the interrupt + * line has the same value as the selected bit, while polarity=1 means + * the line is inverted. + */ +static int mma9551_gpio_config(struct i2c_client *client, + enum mma9551_gpio_pin pin, + u8 app_id, u8 bitnum, int polarity) +{ + u8 reg, pol_mask, pol_val; + int ret; + + if (pin > mma9551_gpio_max) { + dev_err(&client->dev, "bad GPIO pin\n"); + return -EINVAL; + } + + /* + * Pin 6 is configured by regs 0x00 and 0x01, pin 7 by 0x02 and + * 0x03, and so on. + */ + reg = pin * 2; + + ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, + reg, app_id); + if (ret < 0) { + dev_err(&client->dev, "error setting GPIO app_id\n"); + return ret; + } + + ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, + reg + 1, bitnum); + if (ret < 0) { + dev_err(&client->dev, "error setting GPIO bit number\n"); + return ret; + } + + switch (pin) { + case mma9551_gpio6: + reg = MMA9551_GPIO_POL_LSB; + pol_mask = 1 << 6; + break; + case mma9551_gpio7: + reg = MMA9551_GPIO_POL_LSB; + pol_mask = 1 << 7; + break; + case mma9551_gpio8: + reg = MMA9551_GPIO_POL_MSB; + pol_mask = 1 << 0; + break; + case mma9551_gpio9: + reg = MMA9551_GPIO_POL_MSB; + pol_mask = 1 << 1; + break; + } + pol_val = polarity ? pol_mask : 0; + + ret = mma9551_update_config_bits(client, MMA9551_APPID_GPIO, reg, + pol_mask, pol_val); + if (ret < 0) + dev_err(&client->dev, "error setting GPIO polarity\n"); + + return ret; +} + +static int mma9551_read_version(struct i2c_client *client) +{ + struct mma9551_version_info info; + int ret; + + ret = mma9551_transfer(client, MMA9551_APPID_VERSION, 0x00, 0x00, + NULL, 0, (u8 *)&info, sizeof(info)); + if (ret < 0) + return ret; + + dev_info(&client->dev, "Device ID 0x%x, firmware version %02x.%02x\n", + be32_to_cpu(info.device_id), info.fw_version[0], + info.fw_version[1]); + + return 0; +} + +/* + * Use 'false' as the second parameter to cause the device to enter + * sleep. + */ +static int mma9551_set_device_state(struct i2c_client *client, + bool enable) +{ + return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE, + MMA9551_SLEEP_CFG, + MMA9551_SLEEP_CFG_SNCEN, + enable ? 0 : MMA9551_SLEEP_CFG_SNCEN); +} + +static int mma9551_read_incli_chan(struct i2c_client *client, + const struct iio_chan_spec *chan, + int *val) +{ + u8 quad_shift, angle, quadrant; + u16 reg_addr; + int ret; + + switch (chan->channel2) { + case IIO_MOD_X: + reg_addr = MMA9551_TILT_YZ_ANG_REG; + quad_shift = MMA9551_TILT_YZ_QUAD_SHIFT; + break; + case IIO_MOD_Y: + reg_addr = MMA9551_TILT_XZ_ANG_REG; + quad_shift = MMA9551_TILT_XZ_QUAD_SHIFT; + break; + case IIO_MOD_Z: + reg_addr = MMA9551_TILT_XY_ANG_REG; + quad_shift = MMA9551_TILT_XY_QUAD_SHIFT; + break; + default: + return -EINVAL; + } + + ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, + reg_addr, &angle); + if (ret < 0) + return ret; + + ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, + MMA9551_TILT_QUAD_REG, &quadrant); + if (ret < 0) + return ret; + + angle &= ~MMA9551_TILT_ANGFLG; + quadrant = (quadrant >> quad_shift) & 0x03; + + if (quadrant == 1 || quadrant == 3) + *val = 90 * (quadrant + 1) - angle; + else + *val = angle + 90 * quadrant; + + return IIO_VAL_INT; +} + +static int mma9551_read_accel_chan(struct i2c_client *client, + const struct iio_chan_spec *chan, + int *val, int *val2) +{ + u16 reg_addr; + s16 raw_accel; + int ret; + + switch (chan->channel2) { + case IIO_MOD_X: + reg_addr = MMA9551_AFE_X_ACCEL_REG; + break; + case IIO_MOD_Y: + reg_addr = MMA9551_AFE_Y_ACCEL_REG; + break; + case IIO_MOD_Z: + reg_addr = MMA9551_AFE_Z_ACCEL_REG; + break; + default: + return -EINVAL; + } + + ret = mma9551_read_status_word(client, MMA9551_APPID_AFE, + reg_addr, &raw_accel); + if (ret < 0) + return ret; + + *val = raw_accel; + + return IIO_VAL_INT; +} + +static int mma9551_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct mma9551_data *data = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_INCLI: + mutex_lock(&data->mutex); + ret = mma9551_read_incli_chan(data->client, chan, val); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_ACCEL: + mutex_lock(&data->mutex); + ret = mma9551_read_accel_chan(data->client, + chan, val, val2); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + *val = 0; + *val2 = 2440; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int mma9551_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct mma9551_data *data = iio_priv(indio_dev); + + switch (chan->type) { + case IIO_INCLI: + /* IIO counts axes from 1, because IIO_NO_MOD is 0. */ + return data->event_enabled[chan->channel2 - 1]; + default: + return -EINVAL; + } +} + +static int mma9551_config_incli_event(struct iio_dev *indio_dev, + enum iio_modifier axis, + int state) +{ + struct mma9551_data *data = iio_priv(indio_dev); + enum mma9551_tilt_axis mma_axis; + int ret; + + /* IIO counts axes from 1, because IIO_NO_MOD is 0. */ + mma_axis = axis - 1; + + if (data->event_enabled[mma_axis] == state) + return 0; + + if (state == 0) { + ret = mma9551_gpio_config(data->client, mma_axis, + MMA9551_APPID_NONE, 0, 0); + if (ret < 0) + return ret; + } else { + int bitnum; + + /* Bit 7 of each angle register holds the angle flag. */ + switch (axis) { + case IIO_MOD_X: + bitnum = 7 + 8 * MMA9551_TILT_YZ_ANG_REG; + break; + case IIO_MOD_Y: + bitnum = 7 + 8 * MMA9551_TILT_XZ_ANG_REG; + break; + case IIO_MOD_Z: + bitnum = 7 + 8 * MMA9551_TILT_XY_ANG_REG; + break; + default: + return -EINVAL; + } + + ret = mma9551_gpio_config(data->client, mma_axis, + MMA9551_APPID_TILT, bitnum, 0); + if (ret < 0) + return ret; + } + + data->event_enabled[mma_axis] = state; + + return ret; +} + +static int mma9551_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct mma9551_data *data = iio_priv(indio_dev); + int ret; + + switch (chan->type) { + case IIO_INCLI: + mutex_lock(&data->mutex); + ret = mma9551_config_incli_event(indio_dev, + chan->channel2, state); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } +} + +static int mma9551_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct mma9551_data *data = iio_priv(indio_dev); + int ret; + + switch (chan->type) { + case IIO_INCLI: + if (val2 != 0 || val < 1 || val > 10) + return -EINVAL; + mutex_lock(&data->mutex); + ret = mma9551_update_config_bits(data->client, + MMA9551_APPID_TILT, + MMA9551_TILT_CFG_REG, + MMA9551_TILT_ANG_THRESH_MASK, + val); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } +} + +static int mma9551_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct mma9551_data *data = iio_priv(indio_dev); + int ret; + u8 tmp; + + switch (chan->type) { + case IIO_INCLI: + mutex_lock(&data->mutex); + ret = mma9551_read_config_byte(data->client, + MMA9551_APPID_TILT, + MMA9551_TILT_CFG_REG, &tmp); + mutex_unlock(&data->mutex); + if (ret < 0) + return ret; + *val = tmp & MMA9551_TILT_ANG_THRESH_MASK; + *val2 = 0; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static const struct iio_event_spec mma9551_incli_event = { + .type = IIO_EV_TYPE_ROC, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), +}; + +#define MMA9551_ACCEL_CHANNEL(axis) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +#define MMA9551_INCLI_CHANNEL(axis) { \ + .type = IIO_INCLI, \ + .modified = 1, \ + .channel2 = axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ + .event_spec = &mma9551_incli_event, \ + .num_event_specs = 1, \ +} + +static const struct iio_chan_spec mma9551_channels[] = { + MMA9551_ACCEL_CHANNEL(IIO_MOD_X), + MMA9551_ACCEL_CHANNEL(IIO_MOD_Y), + MMA9551_ACCEL_CHANNEL(IIO_MOD_Z), + + MMA9551_INCLI_CHANNEL(IIO_MOD_X), + MMA9551_INCLI_CHANNEL(IIO_MOD_Y), + MMA9551_INCLI_CHANNEL(IIO_MOD_Z), +}; + +static const struct iio_info mma9551_info = { + .driver_module = THIS_MODULE, + .read_raw = mma9551_read_raw, + .read_event_config = mma9551_read_event_config, + .write_event_config = mma9551_write_event_config, + .read_event_value = mma9551_read_event_value, + .write_event_value = mma9551_write_event_value, +}; + +static irqreturn_t mma9551_event_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct mma9551_data *data = iio_priv(indio_dev); + int i, ret, mma_axis = -1; + u16 reg; + u8 val; + + mutex_lock(&data->mutex); + + for (i = 0; i < 3; i++) + if (irq == data->irqs[i]) { + mma_axis = i; + break; + } + + if (mma_axis == -1) { + /* IRQ was triggered on 4th line, which we don't use. */ + dev_warn(&data->client->dev, + "irq triggered on unused line %d\n", data->irqs[3]); + goto out; + } + + switch (mma_axis) { + case mma9551_x: + reg = MMA9551_TILT_YZ_ANG_REG; + break; + case mma9551_y: + reg = MMA9551_TILT_XZ_ANG_REG; + break; + case mma9551_z: + reg = MMA9551_TILT_XY_ANG_REG; + break; + } + + /* + * Read the angle even though we don't use it, otherwise we + * won't get any further interrupts. + */ + ret = mma9551_read_status_byte(data->client, MMA9551_APPID_TILT, + reg, &val); + if (ret < 0) { + dev_err(&data->client->dev, + "error %d reading tilt register in IRQ\n", ret); + goto out; + } + + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_INCLI, 0, (mma_axis + 1), + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING), + iio_get_time_ns()); + +out: + mutex_unlock(&data->mutex); + + return IRQ_HANDLED; +} + +static int mma9551_init(struct mma9551_data *data) +{ + int ret; + + ret = mma9551_read_version(data->client); + if (ret) + return ret; + + /* Power on chip and enable doze mode. */ + return mma9551_update_config_bits(data->client, + MMA9551_APPID_SLEEP_WAKE, + MMA9551_SLEEP_CFG, + MMA9551_SLEEP_CFG_SCHEN | MMA9551_SLEEP_CFG_SNCEN, + MMA9551_SLEEP_CFG_SCHEN); +} + +static int mma9551_gpio_probe(struct iio_dev *indio_dev) +{ + struct gpio_desc *gpio; + int i, ret; + struct mma9551_data *data = iio_priv(indio_dev); + struct device *dev = &data->client->dev; + + for (i = 0; i < MMA9551_GPIO_COUNT; i++) { + gpio = devm_gpiod_get_index(dev, MMA9551_GPIO_NAME, i); + if (IS_ERR(gpio)) { + dev_err(dev, "acpi gpio get index failed\n"); + return PTR_ERR(gpio); + } + + ret = gpiod_direction_input(gpio); + if (ret) + return ret; + + data->irqs[i] = gpiod_to_irq(gpio); + ret = devm_request_threaded_irq(dev, data->irqs[i], + NULL, mma9551_event_handler, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + MMA9551_IRQ_NAME, indio_dev); + if (ret < 0) { + dev_err(dev, "request irq %d failed\n", data->irqs[i]); + return ret; + } + + dev_dbg(dev, "gpio resource, no:%d irq:%d\n", + desc_to_gpio(gpio), data->irqs[i]); + } + + return 0; +} + +static const char *mma9551_match_acpi_device(struct device *dev) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return NULL; + + return dev_name(dev); +} + +static int mma9551_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct mma9551_data *data; + struct iio_dev *indio_dev; + const char *name = NULL; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + if (id) + name = id->name; + else if (ACPI_HANDLE(&client->dev)) + name = mma9551_match_acpi_device(&client->dev); + + ret = mma9551_init(data); + if (ret < 0) + return ret; + + mutex_init(&data->mutex); + + indio_dev->dev.parent = &client->dev; + indio_dev->channels = mma9551_channels; + indio_dev->num_channels = ARRAY_SIZE(mma9551_channels); + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &mma9551_info; + + ret = mma9551_gpio_probe(indio_dev); + if (ret < 0) + goto out_poweroff; + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "unable to register iio device\n"); + goto out_poweroff; + } + + return 0; + +out_poweroff: + mma9551_set_device_state(client, false); + + return ret; +} + +static int mma9551_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct mma9551_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + mutex_lock(&data->mutex); + mma9551_set_device_state(data->client, false); + mutex_unlock(&data->mutex); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int mma9551_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma9551_data *data = iio_priv(indio_dev); + + mutex_lock(&data->mutex); + mma9551_set_device_state(data->client, false); + mutex_unlock(&data->mutex); + + return 0; +} + +static int mma9551_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma9551_data *data = iio_priv(indio_dev); + + mutex_lock(&data->mutex); + mma9551_set_device_state(data->client, true); + mutex_unlock(&data->mutex); + + return 0; +} +#else +#define mma9551_suspend NULL +#define mma9551_resume NULL +#endif + +static const struct dev_pm_ops mma9551_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(mma9551_suspend, mma9551_resume) +}; + +static const struct acpi_device_id mma9551_acpi_match[] = { + {"MMA9551", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(acpi, mma9551_acpi_match); + +static const struct i2c_device_id mma9551_id[] = { + {"mma9551", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, mma9551_id); + +static struct i2c_driver mma9551_driver = { + .driver = { + .name = MMA9551_DRV_NAME, + .acpi_match_table = ACPI_PTR(mma9551_acpi_match), + .pm = &mma9551_pm_ops, + }, + .probe = mma9551_probe, + .remove = mma9551_remove, + .id_table = mma9551_id, +}; + +module_i2c_driver(mma9551_driver); + +MODULE_AUTHOR("Irina Tirdea "); +MODULE_AUTHOR("Vlad Dogaru "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MMA9551L motion-sensing platform driver"); -- cgit v0.10.2 From 3909a0713e19e75410c3ae2ea7dd1242af78b026 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Fri, 12 Dec 2014 13:30:04 +0000 Subject: Revert "iio: imu: Add support for Kionix KMX61 sensor" The two halves of this part can run largely independently. Hence a version 4 of this patch followed that reorganized things completely. This reverts commit d7d787d29148cde12958c2e3765ad3a55dc55eaf. diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index d675f43..2b0e451 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -25,15 +25,6 @@ config ADIS16480 Say yes here to build support for Analog Devices ADIS16375, ADIS16480, ADIS16485, ADIS16488 inertial sensors. -config KMX61 - tristate "Kionix KMX61 6-axis accelerometer and magnetometer" - depends on I2C - help - Say Y here if you want to build a driver for Kionix KMX61 6-axis accelerometer - and magnetometer. - To compile this driver as module, choose M here: the module will be called - kmx61. - source "drivers/iio/imu/inv_mpu6050/Kconfig" endmenu diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index e1e6e3d..114d2c1 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -14,5 +14,3 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o obj-y += inv_mpu6050/ - -obj-$(CONFIG_KMX61) += kmx61.o diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c deleted file mode 100644 index f68b3ef..0000000 --- a/drivers/iio/imu/kmx61.c +++ /dev/null @@ -1,766 +0,0 @@ -/* - * KMX61 - Kionix 6-axis Accelerometer/Magnetometer - * - * Copyright (c) 2014, Intel Corporation. - * - * This file is subject to the terms and conditions of version 2 of - * the GNU General Public License. See the file COPYING in the main - * directory of this archive for more details. - * - * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F). - * - * TODO: buffer, interrupt, thresholds, acpi, temperature sensor - * - */ - -#include -#include -#include -#include -#include -#include - -#define KMX61_DRV_NAME "kmx61" - -#define KMX61_REG_WHO_AM_I 0x00 - -/* - * three 16-bit accelerometer output registers for X/Y/Z axis - * we use only XOUT_L as a base register, all other addresses - * can be obtained by applying an offset and are provided here - * only for clarity. - */ -#define KMX61_ACC_XOUT_L 0x0A -#define KMX61_ACC_XOUT_H 0x0B -#define KMX61_ACC_YOUT_L 0x0C -#define KMX61_ACC_YOUT_H 0x0D -#define KMX61_ACC_ZOUT_L 0x0E -#define KMX61_ACC_ZOUT_H 0x0F - -/* - * one 16-bit temperature output register - */ -#define KMX61_TEMP_L 0x10 -#define KMX61_TEMP_H 0x11 - -/* - * three 16-bit magnetometer output registers for X/Y/Z axis - */ -#define KMX61_MAG_XOUT_L 0x12 -#define KMX61_MAG_XOUT_H 0x13 -#define KMX61_MAG_YOUT_L 0x14 -#define KMX61_MAG_YOUT_H 0x15 -#define KMX61_MAG_ZOUT_L 0x16 -#define KMX61_MAG_ZOUT_H 0x17 - -#define KMX61_REG_ODCNTL 0x2C -#define KMX61_REG_STBY 0x29 -#define KMX61_REG_CTRL1 0x2A - -#define KMX61_ACC_STBY_BIT BIT(0) -#define KMX61_MAG_STBY_BIT BIT(1) -#define KMX61_ACT_STBY_BIT BIT(7) - -#define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT) - -#define KMX61_REG_CTRL1_GSEL0_SHIFT 0 -#define KMX61_REG_CTRL1_GSEL1_SHIFT 1 -#define KMX61_REG_CTRL1_GSEL0_MASK 0x01 -#define KMX61_REG_CTRL1_GSEL1_MASK 0x02 - -#define KMX61_REG_CTRL1_BIT_RES BIT(4) - -#define KMX61_ACC_ODR_SHIFT 0 -#define KMX61_MAG_ODR_SHIFT 4 -#define KMX61_ACC_ODR_MASK 0x0F -#define KMX61_MAG_ODR_MASK 0xF0 - -#define KMX61_SLEEP_DELAY_MS 2000 - -#define KMX61_CHIP_ID 0x12 - -struct kmx61_data { - struct i2c_client *client; - - /* serialize access to non-atomic ops, e.g set_mode */ - struct mutex lock; - u8 range; - u8 odr_bits; - - /* standby state */ - u8 acc_stby; - u8 mag_stby; - - /* power state */ - bool acc_ps; - bool mag_ps; -}; - -enum kmx61_range { - KMX61_RANGE_2G, - KMX61_RANGE_4G, - KMX61_RANGE_8G, -}; - -enum kmx61_scan { - KMX61_SCAN_ACC_X, - KMX61_SCAN_ACC_Y, - KMX61_SCAN_ACC_Z, - KMX61_SCAN_TEMP, - KMX61_SCAN_MAG_X, - KMX61_SCAN_MAG_Y, - KMX61_SCAN_MAG_Z, -}; - -static const struct { - u16 uscale; - u8 gsel0; - u8 gsel1; -} kmx61_scale_table[] = { - {9582, 0, 0}, - {19163, 1, 0}, - {38326, 0, 1}, -}; - -/* KMX61 devices */ -#define KMX61_ACC 0x01 -#define KMX61_MAG 0x02 - -static const struct { - int val; - int val2; - u8 odr_bits; -} kmx61_samp_freq_table[] = { {12, 500000, 0x00}, - {25, 0, 0x01}, - {50, 0, 0x02}, - {100, 0, 0x03}, - {200, 0, 0x04}, - {400, 0, 0x05}, - {800, 0, 0x06}, - {1600, 0, 0x07}, - {0, 781000, 0x08}, - {1, 563000, 0x09}, - {3, 125000, 0x0A}, - {6, 250000, 0x0B} }; - -static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326"); -static IIO_CONST_ATTR(magn_scale_available, "0.001465"); -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( - "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800"); - -static struct attribute *kmx61_attributes[] = { - &iio_const_attr_accel_scale_available.dev_attr.attr, - &iio_const_attr_magn_scale_available.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group kmx61_attribute_group = { - .attrs = kmx61_attributes, -}; - -#define KMX61_ACC_CHAN(_axis, _index) { \ - .type = IIO_ACCEL, \ - .modified = 1, \ - .channel2 = IIO_MOD_ ## _axis, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_SAMP_FREQ), \ - .address = KMX61_ACC, \ - .scan_index = _index, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 12, \ - .storagebits = 16, \ - .shift = 4, \ - .endianness = IIO_LE, \ - }, \ -} - -#define KMX61_MAG_CHAN(_axis, _index) { \ - .type = IIO_MAGN, \ - .modified = 1, \ - .channel2 = IIO_MOD_ ## _axis, \ - .address = KMX61_MAG, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ - BIT(IIO_CHAN_INFO_SAMP_FREQ), \ - .scan_index = _index, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 14, \ - .storagebits = 16, \ - .shift = 2, \ - .endianness = IIO_LE, \ - }, \ -} - -static const struct iio_chan_spec kmx61_channels[] = { - KMX61_ACC_CHAN(X, KMX61_SCAN_ACC_X), - KMX61_ACC_CHAN(Y, KMX61_SCAN_ACC_Y), - KMX61_ACC_CHAN(Z, KMX61_SCAN_ACC_Z), - KMX61_MAG_CHAN(X, KMX61_SCAN_MAG_X), - KMX61_MAG_CHAN(Y, KMX61_SCAN_MAG_Y), - KMX61_MAG_CHAN(Z, KMX61_SCAN_MAG_Z), -}; - -static int kmx61_convert_freq_to_bit(int val, int val2) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) - if (val == kmx61_samp_freq_table[i].val && - val2 == kmx61_samp_freq_table[i].val2) - return kmx61_samp_freq_table[i].odr_bits; - return -EINVAL; -} -/** - * kmx61_set_mode() - set KMX61 device operating mode - * @data - kmx61 device private data pointer - * @mode - bitmask, indicating operating mode for @device - * @device - bitmask, indicating device for which @mode needs to be set - * @update - update stby bits stored in device's private @data - * - * For each sensor (accelerometer/magnetometer) there are two operating modes - * STANDBY and OPERATION. Neither accel nor magn can be disabled independently - * if they are both enabled. Internal sensors state is saved in acc_stby and - * mag_stby members of driver's private @data. - */ -static int kmx61_set_mode(struct kmx61_data *data, u8 mode, u8 device, - bool update) -{ - int ret; - int acc_stby = -1, mag_stby = -1; - - ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); - if (ret < 0) { - dev_err(&data->client->dev, "Error reading reg_stby\n"); - return ret; - } - if (device & KMX61_ACC) { - if (mode & KMX61_ACC_STBY_BIT) { - ret |= KMX61_ACC_STBY_BIT; - acc_stby = 1; - } else { - ret &= ~KMX61_ACC_STBY_BIT; - acc_stby = 0; - } - } - - if (device & KMX61_MAG) { - if (mode & KMX61_MAG_STBY_BIT) { - ret |= KMX61_MAG_STBY_BIT; - mag_stby = 1; - } else { - ret &= ~KMX61_MAG_STBY_BIT; - mag_stby = 0; - } - } - - ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_STBY, ret); - if (ret < 0) { - dev_err(&data->client->dev, "Error writing reg_stby\n"); - return ret; - } - - if (acc_stby != -1 && update) - data->acc_stby = !!acc_stby; - if (mag_stby != -1 && update) - data->mag_stby = !!mag_stby; - - return ret; -} - -static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) -{ - int ret; - - ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); - if (ret < 0) { - dev_err(&data->client->dev, "Error reading reg_stby\n"); - return ret; - } - *mode = 0; - - if (device & KMX61_ACC) { - if (ret & KMX61_ACC_STBY_BIT) - *mode |= KMX61_ACC_STBY_BIT; - else - *mode &= ~KMX61_ACC_STBY_BIT; - } - - if (device & KMX61_MAG) { - if (ret & KMX61_MAG_STBY_BIT) - *mode |= KMX61_MAG_STBY_BIT; - else - *mode &= ~KMX61_MAG_STBY_BIT; - } - - return 0; -} - -static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) -{ - int ret; - u8 mode; - int lodr_bits, odr_bits; - - ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); - if (ret < 0) - return ret; - - lodr_bits = kmx61_convert_freq_to_bit(val, val2); - if (lodr_bits < 0) - return lodr_bits; - - /* To change ODR, accel and magn must be in STDBY */ - ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, - true); - if (ret < 0) - return ret; - - odr_bits = 0; - if (device & KMX61_ACC) - odr_bits |= lodr_bits; - if (device & KMX61_MAG) - odr_bits |= (lodr_bits << KMX61_MAG_ODR_SHIFT); - - ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_ODCNTL, - odr_bits); - if (ret < 0) - return ret; - - ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); - if (ret < 0) - return ret; - - data->odr_bits = lodr_bits; - - return 0; -} - -static -int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2, u8 device) -{ int i; - u8 lodr_bits; - - if (device & KMX61_ACC) - lodr_bits = (data->odr_bits >> KMX61_ACC_ODR_SHIFT) & - KMX61_ACC_ODR_MASK; - else if (device & KMX61_MAG) - lodr_bits = (data->odr_bits >> KMX61_MAG_ODR_SHIFT) & - KMX61_MAG_ODR_MASK; - else - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) - if (lodr_bits == kmx61_samp_freq_table[i].odr_bits) { - *val = kmx61_samp_freq_table[i].val; - *val2 = kmx61_samp_freq_table[i].val2; - return 0; - } - return -EINVAL; -} - -static int kmx61_set_range(struct kmx61_data *data, int range) -{ - int ret; - - ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); - if (ret < 0) { - dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); - return ret; - } - - ret &= ~(KMX61_REG_CTRL1_GSEL0_MASK | KMX61_REG_CTRL1_GSEL1_MASK); - ret |= kmx61_scale_table[range].gsel0 << KMX61_REG_CTRL1_GSEL0_SHIFT; - ret |= kmx61_scale_table[range].gsel1 << KMX61_REG_CTRL1_GSEL1_SHIFT; - - ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); - if (ret < 0) { - dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); - return ret; - } - - data->range = range; - - return 0; -} - -static int kmx61_set_scale(struct kmx61_data *data, int uscale) -{ - int ret, i; - u8 mode; - - for (i = 0; i < ARRAY_SIZE(kmx61_scale_table); i++) { - if (kmx61_scale_table[i].uscale == uscale) { - ret = kmx61_get_mode(data, &mode, - KMX61_ACC | KMX61_MAG); - if (ret < 0) - return ret; - - ret = kmx61_set_mode(data, KMX61_ALL_STBY, - KMX61_ACC | KMX61_MAG, true); - if (ret < 0) - return ret; - - ret = kmx61_set_range(data, i); - if (ret < 0) - return ret; - - return kmx61_set_mode(data, mode, - KMX61_ACC | KMX61_MAG, true); - } - } - return -EINVAL; -} - -static int kmx61_chip_init(struct kmx61_data *data) -{ - int ret; - - ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I); - if (ret < 0) { - dev_err(&data->client->dev, "Error reading who_am_i\n"); - return ret; - } - - if (ret != KMX61_CHIP_ID) { - dev_err(&data->client->dev, - "Wrong chip id, got %x expected %x\n", - ret, KMX61_CHIP_ID); - return -EINVAL; - } - - /* set accel 12bit, 4g range */ - ret = kmx61_set_range(data, KMX61_RANGE_4G); - if (ret < 0) - return ret; - - /* set acc/magn to OPERATION mode */ - ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true); - if (ret < 0) - return ret; - - return 0; -} -/** - * kmx61_set_power_state() - set power state for kmx61 @device - * @data - kmx61 device private pointer - * @on - power state to be set for @device - * @device - bitmask indicating device for which @on state needs to be set - * - * Notice that when ACC power state needs to be set to ON and MAG is in - * OPERATION then we know that kmx61_runtime_resume was already called - * so we must set ACC OPERATION mode here. The same happens when MAG power - * state needs to be set to ON and ACC is in OPERATION. - */ -static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) -{ -#ifdef CONFIG_PM_RUNTIME - int ret; - - if (device & KMX61_ACC) { - if (on && !data->acc_ps && !data->mag_stby) - kmx61_set_mode(data, 0, KMX61_ACC, true); - data->acc_ps = on; - } - if (device & KMX61_MAG) { - if (on && !data->mag_ps && !data->acc_stby) - kmx61_set_mode(data, 0, KMX61_MAG, true); - data->mag_ps = on; - } - - if (on) { - ret = pm_runtime_get_sync(&data->client->dev); - } else { - pm_runtime_mark_last_busy(&data->client->dev); - ret = pm_runtime_put_autosuspend(&data->client->dev); - } - if (ret < 0) { - dev_err(&data->client->dev, - "Failed: kmx61_set_power_state for %d, ret %d\n", - on, ret); - return ret; - } -#endif - return 0; -} - -static int kmx61_read_measurement(struct kmx61_data *data, int base, int offset) -{ - int ret; - u8 reg = base + offset * 2; - - ret = i2c_smbus_read_word_data(data->client, reg); - if (ret < 0) { - dev_err(&data->client->dev, "failed to read reg at %x\n", reg); - return ret; - } - - return ret; -} - -static int kmx61_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int *val, - int *val2, long mask) -{ - struct kmx61_data *data = iio_priv(indio_dev); - int ret; - u8 base_reg; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - switch (chan->type) { - case IIO_ACCEL: - case IIO_MAGN: - base_reg = KMX61_ACC_XOUT_L; - break; - default: - return -EINVAL; - } - mutex_lock(&data->lock); - - kmx61_set_power_state(data, true, chan->address); - ret = kmx61_read_measurement(data, base_reg, chan->scan_index); - if (ret < 0) { - kmx61_set_power_state(data, false, chan->address); - mutex_unlock(&data->lock); - return ret; - } - *val = sign_extend32(ret >> chan->scan_type.shift, - chan->scan_type.realbits - 1); - kmx61_set_power_state(data, false, chan->address); - - mutex_unlock(&data->lock); - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_ACCEL: - *val = 0; - *val2 = kmx61_scale_table[data->range].uscale; - return IIO_VAL_INT_PLUS_MICRO; - case IIO_MAGN: - /* 14 bits res, 1465 microGauss per magn count */ - *val = 0; - *val2 = 1465; - return IIO_VAL_INT_PLUS_MICRO; - default: - return -EINVAL; - } - case IIO_CHAN_INFO_SAMP_FREQ: - if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) - return -EINVAL; - - mutex_lock(&data->lock); - ret = kmx61_get_odr(data, val, val2, chan->address); - mutex_unlock(&data->lock); - if (ret) - return -EINVAL; - return IIO_VAL_INT_PLUS_MICRO; - } - return -EINVAL; -} - -static int kmx61_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int val, - int val2, long mask) -{ - struct kmx61_data *data = iio_priv(indio_dev); - int ret; - - switch (mask) { - case IIO_CHAN_INFO_SAMP_FREQ: - if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) - return -EINVAL; - - mutex_lock(&data->lock); - ret = kmx61_set_odr(data, val, val2, chan->address); - mutex_unlock(&data->lock); - return ret; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_ACCEL: - if (val != 0) - return -EINVAL; - mutex_lock(&data->lock); - ret = kmx61_set_scale(data, val2); - mutex_unlock(&data->lock); - return ret; - default: - return -EINVAL; - } - return ret; - default: - return -EINVAL; - } - return ret; -} - -static const struct iio_info kmx61_info = { - .driver_module = THIS_MODULE, - .read_raw = kmx61_read_raw, - .write_raw = kmx61_write_raw, - .attrs = &kmx61_attribute_group, -}; - -static int kmx61_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct kmx61_data *data; - struct iio_dev *indio_dev; - int ret; - const char *name = NULL; - - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); - if (!indio_dev) - return -ENOMEM; - - data = iio_priv(indio_dev); - i2c_set_clientdata(client, indio_dev); - data->client = client; - - if (id) - name = id->name; - - indio_dev->dev.parent = &client->dev; - indio_dev->channels = kmx61_channels; - indio_dev->num_channels = ARRAY_SIZE(kmx61_channels); - indio_dev->name = name; - indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->info = &kmx61_info; - - mutex_init(&data->lock); - - ret = kmx61_chip_init(data); - if (ret < 0) - return ret; - - ret = iio_device_register(indio_dev); - if (ret < 0) { - dev_err(&client->dev, "Failed to register iio device\n"); - goto err_iio_device_register; - } - - ret = pm_runtime_set_active(&client->dev); - if (ret < 0) - goto err_pm_runtime_set_active; - - pm_runtime_enable(&client->dev); - pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS); - pm_runtime_use_autosuspend(&client->dev); - - return 0; - -err_pm_runtime_set_active: - iio_device_unregister(indio_dev); -err_iio_device_register: - kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); - return ret; -} - -static int kmx61_remove(struct i2c_client *client) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct kmx61_data *data = iio_priv(indio_dev); - int ret; - - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); - pm_runtime_put_noidle(&client->dev); - - iio_device_unregister(indio_dev); - - mutex_lock(&data->lock); - ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); - mutex_unlock(&data->lock); - - return ret; -} - -#ifdef CONFIG_PM_SLEEP -static int kmx61_suspend(struct device *dev) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); - struct kmx61_data *data = iio_priv(indio_dev); - int ret; - - mutex_lock(&data->lock); - ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, - false); - mutex_unlock(&data->lock); - - return ret; -} - -static int kmx61_resume(struct device *dev) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); - struct kmx61_data *data = iio_priv(indio_dev); - u8 stby = 0; - - if (data->acc_stby) - stby |= KMX61_ACC_STBY_BIT; - if (data->mag_stby) - stby |= KMX61_MAG_STBY_BIT; - - return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); -} -#endif - -#ifdef CONFIG_PM_RUNTIME -static int kmx61_runtime_suspend(struct device *dev) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); - struct kmx61_data *data = iio_priv(indio_dev); - int ret; - - mutex_lock(&data->lock); - ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); - mutex_unlock(&data->lock); - - return ret; -} - -static int kmx61_runtime_resume(struct device *dev) -{ - struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); - struct kmx61_data *data = iio_priv(indio_dev); - u8 stby = 0; - - if (!data->acc_ps) - stby |= KMX61_ACC_STBY_BIT; - if (!data->mag_ps) - stby |= KMX61_MAG_STBY_BIT; - - return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); -} -#endif - -static const struct dev_pm_ops kmx61_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(kmx61_suspend, kmx61_resume) - SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL) -}; - -static const struct i2c_device_id kmx61_id[] = { - {"kmx611021", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, kmx61_id); - -static struct i2c_driver kmx61_driver = { - .driver = { - .name = KMX61_DRV_NAME, - .pm = &kmx61_pm_ops, - }, - .probe = kmx61_probe, - .remove = kmx61_remove, - .id_table = kmx61_id, -}; - -module_i2c_driver(kmx61_driver); - -MODULE_AUTHOR("Daniel Baluta "); -MODULE_DESCRIPTION("KMX61 accelerometer/magnetometer driver"); -MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 20ffac278ebd64ad031149628560f47990910dd7 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:48 +0200 Subject: iio: imu: Add support for Kionix KMX61 sensor Minimal implementation for KMX61 6-axis accelerometer/magnetometer. It exports raw accel/magn readings together with scale and sampling frequency. This driver uses two IIO devices one for accelerometer and one for magnetometer. Datasheet will be available at: http://www.kionix.com/6-axis-accelerometer-magnetometer/kmx61 Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index 2b0e451..db4221d 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -25,6 +25,15 @@ config ADIS16480 Say yes here to build support for Analog Devices ADIS16375, ADIS16480, ADIS16485, ADIS16488 inertial sensors. +config KMX61 + tristate "Kionix KMX61 6-axis accelerometer and magnetometer" + depends on I2C + help + Say Y here if you want to build a driver for Kionix KMX61 6-axis + accelerometer and magnetometer. + To compile this driver as module, choose M here: the module will + be called kmx61. + source "drivers/iio/imu/inv_mpu6050/Kconfig" endmenu diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 114d2c1..e1e6e3d 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -14,3 +14,5 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o obj-y += inv_mpu6050/ + +obj-$(CONFIG_KMX61) += kmx61.o diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c new file mode 100644 index 0000000..5231d8f --- /dev/null +++ b/drivers/iio/imu/kmx61.c @@ -0,0 +1,691 @@ +/* + * KMX61 - Kionix 6-axis Accelerometer/Magnetometer + * + * Copyright (c) 2014, Intel Corporation. + * + * This file is subject to the terms and conditions of version 2 of + * the GNU General Public License. See the file COPYING in the main + * directory of this archive for more details. + * + * IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F). + * + */ + +#include +#include +#include +#include + +#define KMX61_DRV_NAME "kmx61" + +#define KMX61_REG_WHO_AM_I 0x00 + +/* + * three 16-bit accelerometer output registers for X/Y/Z axis + * we use only XOUT_L as a base register, all other addresses + * can be obtained by applying an offset and are provided here + * only for clarity. + */ +#define KMX61_ACC_XOUT_L 0x0A +#define KMX61_ACC_XOUT_H 0x0B +#define KMX61_ACC_YOUT_L 0x0C +#define KMX61_ACC_YOUT_H 0x0D +#define KMX61_ACC_ZOUT_L 0x0E +#define KMX61_ACC_ZOUT_H 0x0F + +/* + * one 16-bit temperature output register + */ +#define KMX61_TEMP_L 0x10 +#define KMX61_TEMP_H 0x11 + +/* + * three 16-bit magnetometer output registers for X/Y/Z axis + */ +#define KMX61_MAG_XOUT_L 0x12 +#define KMX61_MAG_XOUT_H 0x13 +#define KMX61_MAG_YOUT_L 0x14 +#define KMX61_MAG_YOUT_H 0x15 +#define KMX61_MAG_ZOUT_L 0x16 +#define KMX61_MAG_ZOUT_H 0x17 + +#define KMX61_REG_STBY 0x29 +#define KMX61_REG_CTRL1 0x2A +#define KMX61_REG_ODCNTL 0x2C + +#define KMX61_ACC_STBY_BIT BIT(0) +#define KMX61_MAG_STBY_BIT BIT(1) +#define KMX61_ACT_STBY_BIT BIT(7) + +#define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT) + +#define KMX61_REG_CTRL1_GSEL_MASK 0x03 + +#define KMX61_ACC_ODR_SHIFT 0 +#define KMX61_MAG_ODR_SHIFT 4 +#define KMX61_ACC_ODR_MASK 0x0F +#define KMX61_MAG_ODR_MASK 0xF0 + +#define KMX61_CHIP_ID 0x12 + +/* KMX61 devices */ +#define KMX61_ACC 0x01 +#define KMX61_MAG 0x02 + +struct kmx61_data { + struct i2c_client *client; + + /* serialize access to non-atomic ops, e.g set_mode */ + struct mutex lock; + + /* standby state */ + bool acc_stby; + bool mag_stby; + + /* config bits */ + u8 range; + u8 odr_bits; + + /* accelerometer specific data */ + struct iio_dev *acc_indio_dev; + + /* magnetometer specific data */ + struct iio_dev *mag_indio_dev; +}; + +enum kmx61_range { + KMX61_RANGE_2G, + KMX61_RANGE_4G, + KMX61_RANGE_8G, +}; + +enum kmx61_axis { + KMX61_AXIS_X, + KMX61_AXIS_Y, + KMX61_AXIS_Z, +}; + +static const u16 kmx61_uscale_table[] = {9582, 19163, 38326}; + +static const struct { + int val; + int val2; + u8 odr_bits; +} kmx61_samp_freq_table[] = { {12, 500000, 0x00}, + {25, 0, 0x01}, + {50, 0, 0x02}, + {100, 0, 0x03}, + {200, 0, 0x04}, + {400, 0, 0x05}, + {800, 0, 0x06}, + {1600, 0, 0x07}, + {0, 781000, 0x08}, + {1, 563000, 0x09}, + {3, 125000, 0x0A}, + {6, 250000, 0x0B} }; + +static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326"); +static IIO_CONST_ATTR(magn_scale_available, "0.001465"); +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( + "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800"); + +static struct attribute *kmx61_acc_attributes[] = { + &iio_const_attr_accel_scale_available.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static struct attribute *kmx61_mag_attributes[] = { + &iio_const_attr_magn_scale_available.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group kmx61_acc_attribute_group = { + .attrs = kmx61_acc_attributes, +}; + +static const struct attribute_group kmx61_mag_attribute_group = { + .attrs = kmx61_mag_attributes, +}; + +#define KMX61_ACC_CHAN(_axis) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_ ## _axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = KMX61_ACC, \ + .scan_index = KMX61_AXIS_ ## _axis, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_LE, \ + }, \ +} + +#define KMX61_MAG_CHAN(_axis) { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = IIO_MOD_ ## _axis, \ + .address = KMX61_MAG, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = KMX61_AXIS_ ## _axis, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 14, \ + .storagebits = 16, \ + .shift = 2, \ + .endianness = IIO_LE, \ + }, \ +} + +static const struct iio_chan_spec kmx61_acc_channels[] = { + KMX61_ACC_CHAN(X), + KMX61_ACC_CHAN(Y), + KMX61_ACC_CHAN(Z), +}; + +static const struct iio_chan_spec kmx61_mag_channels[] = { + KMX61_MAG_CHAN(X), + KMX61_MAG_CHAN(Y), + KMX61_MAG_CHAN(Z), +}; + +static void kmx61_set_data(struct iio_dev *indio_dev, struct kmx61_data *data) +{ + struct kmx61_data **priv = iio_priv(indio_dev); + + *priv = data; +} + +static struct kmx61_data *kmx61_get_data(struct iio_dev *indio_dev) +{ + return *(struct kmx61_data **)iio_priv(indio_dev); +} + +static int kmx61_convert_freq_to_bit(int val, int val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) + if (val == kmx61_samp_freq_table[i].val && + val2 == kmx61_samp_freq_table[i].val2) + return kmx61_samp_freq_table[i].odr_bits; + return -EINVAL; +} + +/** + * kmx61_set_mode() - set KMX61 device operating mode + * @data - kmx61 device private data pointer + * @mode - bitmask, indicating operating mode for @device + * @device - bitmask, indicating device for which @mode needs to be set + * @update - update stby bits stored in device's private @data + * + * For each sensor (accelerometer/magnetometer) there are two operating modes + * STANDBY and OPERATION. Neither accel nor magn can be disabled independently + * if they are both enabled. Internal sensors state is saved in acc_stby and + * mag_stby members of driver's private @data. + */ +static int kmx61_set_mode(struct kmx61_data *data, u8 mode, u8 device, + bool update) +{ + int ret; + int acc_stby = -1, mag_stby = -1; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_stby\n"); + return ret; + } + if (device & KMX61_ACC) { + if (mode & KMX61_ACC_STBY_BIT) { + ret |= KMX61_ACC_STBY_BIT; + acc_stby = 1; + } else { + ret &= ~KMX61_ACC_STBY_BIT; + acc_stby = 0; + } + } + + if (device & KMX61_MAG) { + if (mode & KMX61_MAG_STBY_BIT) { + ret |= KMX61_MAG_STBY_BIT; + mag_stby = 1; + } else { + ret &= ~KMX61_MAG_STBY_BIT; + mag_stby = 0; + } + } + + if (mode & KMX61_ACT_STBY_BIT) + ret |= KMX61_ACT_STBY_BIT; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_STBY, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_stby\n"); + return ret; + } + + if (acc_stby != -1 && update) + data->acc_stby = acc_stby; + if (mag_stby != -1 && update) + data->mag_stby = mag_stby; + + return 0; +} + +static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_STBY); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_stby\n"); + return ret; + } + *mode = 0; + + if (device & KMX61_ACC) { + if (ret & KMX61_ACC_STBY_BIT) + *mode |= KMX61_ACC_STBY_BIT; + else + *mode &= ~KMX61_ACC_STBY_BIT; + } + + if (device & KMX61_MAG) { + if (ret & KMX61_MAG_STBY_BIT) + *mode |= KMX61_MAG_STBY_BIT; + else + *mode &= ~KMX61_MAG_STBY_BIT; + } + + return 0; +} + +static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) +{ + int ret; + u8 mode; + int lodr_bits, odr_bits; + + ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + lodr_bits = kmx61_convert_freq_to_bit(val, val2); + if (lodr_bits < 0) + return lodr_bits; + + /* To change ODR, accel and magn must be in STDBY */ + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, + true); + if (ret < 0) + return ret; + + odr_bits = 0; + if (device & KMX61_ACC) + odr_bits |= lodr_bits << KMX61_ACC_ODR_SHIFT; + if (device & KMX61_MAG) + odr_bits |= lodr_bits << KMX61_MAG_ODR_SHIFT; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_ODCNTL, + odr_bits); + if (ret < 0) + return ret; + + return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); +} + +static int kmx61_get_odr(struct kmx61_data *data, int *val, int *val2, + u8 device) +{ int i; + u8 lodr_bits; + + if (device & KMX61_ACC) + lodr_bits = (data->odr_bits >> KMX61_ACC_ODR_SHIFT) & + KMX61_ACC_ODR_MASK; + else if (device & KMX61_MAG) + lodr_bits = (data->odr_bits >> KMX61_MAG_ODR_SHIFT) & + KMX61_MAG_ODR_MASK; + else + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) + if (lodr_bits == kmx61_samp_freq_table[i].odr_bits) { + *val = kmx61_samp_freq_table[i].val; + *val2 = kmx61_samp_freq_table[i].val2; + return 0; + } + return -EINVAL; +} + +static int kmx61_set_range(struct kmx61_data *data, u8 range) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + ret &= ~KMX61_REG_CTRL1_GSEL_MASK; + ret |= range & KMX61_REG_CTRL1_GSEL_MASK; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); + return ret; + } + + data->range = range; + + return 0; +} + +static int kmx61_set_scale(struct kmx61_data *data, u16 uscale) +{ + int ret, i; + u8 mode; + + for (i = 0; i < ARRAY_SIZE(kmx61_uscale_table); i++) { + if (kmx61_uscale_table[i] == uscale) { + ret = kmx61_get_mode(data, &mode, + KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + ret = kmx61_set_mode(data, KMX61_ALL_STBY, + KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + ret = kmx61_set_range(data, i); + if (ret < 0) + return ret; + + return kmx61_set_mode(data, mode, + KMX61_ACC | KMX61_MAG, true); + } + } + return -EINVAL; +} + +static int kmx61_chip_init(struct kmx61_data *data) +{ + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading who_am_i\n"); + return ret; + } + + if (ret != KMX61_CHIP_ID) { + dev_err(&data->client->dev, + "Wrong chip id, got %x expected %x\n", + ret, KMX61_CHIP_ID); + return -EINVAL; + } + + /* set accel 12bit, 4g range */ + ret = kmx61_set_range(data, KMX61_RANGE_4G); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_ODCNTL); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_odcntl\n"); + return ret; + } + data->odr_bits = ret; + + /* set acc/magn to OPERATION mode */ + ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + return 0; +} + +static int kmx61_read_measurement(struct kmx61_data *data, u8 base, u8 offset) +{ + int ret; + u8 reg = base + offset * 2; + + ret = i2c_smbus_read_word_data(data->client, reg); + if (ret < 0) + dev_err(&data->client->dev, "failed to read reg at %x\n", reg); + + return ret; +} + +static int kmx61_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + int ret; + u8 base_reg; + struct kmx61_data *data = kmx61_get_data(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_ACCEL: + base_reg = KMX61_ACC_XOUT_L; + break; + case IIO_MAGN: + base_reg = KMX61_MAG_XOUT_L; + break; + default: + return -EINVAL; + } + mutex_lock(&data->lock); + + ret = kmx61_read_measurement(data, base_reg, chan->scan_index); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + *val = sign_extend32(ret >> chan->scan_type.shift, + chan->scan_type.realbits - 1); + + mutex_unlock(&data->lock); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + *val = 0; + *val2 = kmx61_uscale_table[data->range]; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_MAGN: + /* 14 bits res, 1465 microGauss per magn count */ + *val = 0; + *val2 = 1465; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SAMP_FREQ: + if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) + return -EINVAL; + + mutex_lock(&data->lock); + ret = kmx61_get_odr(data, val, val2, chan->address); + mutex_unlock(&data->lock); + if (ret) + return -EINVAL; + return IIO_VAL_INT_PLUS_MICRO; + } + return -EINVAL; +} + +static int kmx61_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + int ret; + struct kmx61_data *data = kmx61_get_data(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (chan->type != IIO_ACCEL && chan->type != IIO_MAGN) + return -EINVAL; + + mutex_lock(&data->lock); + ret = kmx61_set_odr(data, val, val2, chan->address); + mutex_unlock(&data->lock); + return ret; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + if (val != 0) + return -EINVAL; + mutex_lock(&data->lock); + ret = kmx61_set_scale(data, val2); + mutex_unlock(&data->lock); + return ret; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static const struct iio_info kmx61_acc_info = { + .driver_module = THIS_MODULE, + .read_raw = kmx61_read_raw, + .write_raw = kmx61_write_raw, + .attrs = &kmx61_acc_attribute_group, +}; + +static const struct iio_info kmx61_mag_info = { + .driver_module = THIS_MODULE, + .read_raw = kmx61_read_raw, + .write_raw = kmx61_write_raw, + .attrs = &kmx61_mag_attribute_group, +}; + +static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data, + const struct iio_info *info, + const struct iio_chan_spec *chan, + int num_channels, + const char *name) +{ + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(&data->client->dev, sizeof(data)); + if (!indio_dev) + return ERR_PTR(-ENOMEM); + + kmx61_set_data(indio_dev, data); + + indio_dev->dev.parent = &data->client->dev; + indio_dev->channels = chan; + indio_dev->num_channels = num_channels; + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = info; + + return indio_dev; +} + +static int kmx61_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct kmx61_data *data; + const char *name = NULL; + + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + data->client = client; + + mutex_init(&data->lock); + + data->acc_indio_dev = + kmx61_indiodev_setup(data, &kmx61_acc_info, + kmx61_acc_channels, + ARRAY_SIZE(kmx61_acc_channels), + name); + if (IS_ERR(data->acc_indio_dev)) + return PTR_ERR(data->acc_indio_dev); + + data->mag_indio_dev = + kmx61_indiodev_setup(data, &kmx61_mag_info, + kmx61_mag_channels, + ARRAY_SIZE(kmx61_mag_channels), + name); + if (IS_ERR(data->mag_indio_dev)) + return PTR_ERR(data->mag_indio_dev); + + ret = kmx61_chip_init(data); + if (ret < 0) + return ret; + + ret = iio_device_register(data->acc_indio_dev); + if (ret < 0) { + dev_err(&client->dev, "Failed to register acc iio device\n"); + goto err_chip_uninit; + } + + ret = iio_device_register(data->mag_indio_dev); + if (ret < 0) { + dev_err(&client->dev, "Failed to register mag iio device\n"); + goto err_iio_unregister; + } + + return 0; + +err_iio_unregister: + iio_device_unregister(data->acc_indio_dev); +err_chip_uninit: + kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + return ret; +} + +static int kmx61_remove(struct i2c_client *client) +{ + struct kmx61_data *data = i2c_get_clientdata(client); + + iio_device_unregister(data->acc_indio_dev); + iio_device_unregister(data->mag_indio_dev); + + mutex_lock(&data->lock); + kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + mutex_unlock(&data->lock); + + return 0; +} + +static const struct i2c_device_id kmx61_id[] = { + {"kmx611021", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, kmx61_id); + +static struct i2c_driver kmx61_driver = { + .driver = { + .name = KMX61_DRV_NAME, + }, + .probe = kmx61_probe, + .remove = kmx61_remove, + .id_table = kmx61_id, +}; + +module_i2c_driver(kmx61_driver); + +MODULE_AUTHOR("Daniel Baluta "); +MODULE_DESCRIPTION("KMX61 accelerometer/magnetometer driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From b25862c577979659020f3575838d366f480ec3bf Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:49 +0200 Subject: iio: imu: kmx61: Add acpi support Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 5231d8f..efb2f8b 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -13,10 +13,13 @@ #include #include +#include +#include #include #include #define KMX61_DRV_NAME "kmx61" +#define KMX61_GPIO_NAME "kmx61_int" #define KMX61_REG_WHO_AM_I 0x00 @@ -573,6 +576,44 @@ static const struct iio_info kmx61_mag_info = { .attrs = &kmx61_mag_attribute_group, }; +static const char *kmx61_match_acpi_device(struct device *dev) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return NULL; + return dev_name(dev); +} + +static int kmx61_gpio_probe(struct i2c_client *client, struct kmx61_data *data) +{ + struct device *dev; + struct gpio_desc *gpio; + int ret; + + if (!client) + return -EINVAL; + + dev = &client->dev; + + /* data ready gpio interrupt pin */ + gpio = devm_gpiod_get_index(dev, KMX61_GPIO_NAME, 0); + if (IS_ERR(gpio)) { + dev_err(dev, "acpi gpio get index failed\n"); + return PTR_ERR(gpio); + } + + ret = gpiod_direction_input(gpio); + if (ret) + return ret; + + ret = gpiod_to_irq(gpio); + + dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); + return ret; +} + static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data, const struct iio_info *info, const struct iio_chan_spec *chan, @@ -613,6 +654,13 @@ static int kmx61_probe(struct i2c_client *client, mutex_init(&data->lock); + if (id) + name = id->name; + else if (ACPI_HANDLE(&client->dev)) + name = kmx61_match_acpi_device(&client->dev); + else + return -ENODEV; + data->acc_indio_dev = kmx61_indiodev_setup(data, &kmx61_acc_info, kmx61_acc_channels, @@ -633,6 +681,9 @@ static int kmx61_probe(struct i2c_client *client, if (ret < 0) return ret; + if (client->irq < 0) + client->irq = kmx61_gpio_probe(client, data); + ret = iio_device_register(data->acc_indio_dev); if (ret < 0) { dev_err(&client->dev, "Failed to register acc iio device\n"); @@ -668,6 +719,13 @@ static int kmx61_remove(struct i2c_client *client) return 0; } +static const struct acpi_device_id kmx61_acpi_match[] = { + {"KMX61021", 0}, + {} +}; + +MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match); + static const struct i2c_device_id kmx61_id[] = { {"kmx611021", 0}, {} @@ -678,6 +736,7 @@ MODULE_DEVICE_TABLE(i2c, kmx61_id); static struct i2c_driver kmx61_driver = { .driver = { .name = KMX61_DRV_NAME, + .acpi_match_table = ACPI_PTR(kmx61_acpi_match), }, .probe = kmx61_probe, .remove = kmx61_remove, -- cgit v0.10.2 From aff8609addd00efa3d907f3523823693f95686fd Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:50 +0200 Subject: iio: imu: kmx61: Add PM runtime support By default both sensors are ACTIVE, in this way the driver will work even if CONFIG_PM_RUNTIME is not selected. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index efb2f8b..f3007dd 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -69,6 +71,8 @@ #define KMX61_ACC_ODR_MASK 0x0F #define KMX61_MAG_ODR_MASK 0xF0 +#define KMX61_SLEEP_DELAY_MS 2000 + #define KMX61_CHIP_ID 0x12 /* KMX61 devices */ @@ -85,6 +89,10 @@ struct kmx61_data { bool acc_stby; bool mag_stby; + /* power state */ + bool acc_ps; + bool mag_ps; + /* config bits */ u8 range; u8 odr_bits; @@ -457,6 +465,58 @@ static int kmx61_chip_init(struct kmx61_data *data) return 0; } +/** + * kmx61_set_power_state() - set power state for kmx61 @device + * @data - kmx61 device private pointer + * @on - power state to be set for @device + * @device - bitmask indicating device for which @on state needs to be set + * + * Notice that when ACC power state needs to be set to ON and MAG is in + * OPERATION then we know that kmx61_runtime_resume was already called + * so we must set ACC OPERATION mode here. The same happens when MAG power + * state needs to be set to ON and ACC is in OPERATION. + */ +static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) +{ +#ifdef CONFIG_PM_RUNTIME + int ret; + + if (device & KMX61_ACC) { + if (on && !data->acc_ps && !data->mag_stby) { + ret = kmx61_set_mode(data, 0, KMX61_ACC, true); + if (ret < 0) + return ret; + } + data->acc_ps = on; + } + if (device & KMX61_MAG) { + if (on && !data->mag_ps && !data->acc_stby) { + ret = kmx61_set_mode(data, 0, KMX61_MAG, true); + if (ret < 0) + return ret; + } + data->mag_ps = on; + } + + if (on) { + ret = pm_runtime_get_sync(&data->client->dev); + } else { + pm_runtime_mark_last_busy(&data->client->dev); + ret = pm_runtime_put_autosuspend(&data->client->dev); + } + if (ret < 0) { + dev_err(&data->client->dev, + "Failed: kmx61_set_power_state for %d, ret %d\n", + on, ret); + if (on) + pm_runtime_put_noidle(&data->client->dev); + + return ret; + } +#endif + return 0; +} + static int kmx61_read_measurement(struct kmx61_data *data, u8 base, u8 offset) { int ret; @@ -491,13 +551,16 @@ static int kmx61_read_raw(struct iio_dev *indio_dev, } mutex_lock(&data->lock); + kmx61_set_power_state(data, true, chan->address); ret = kmx61_read_measurement(data, base_reg, chan->scan_index); if (ret < 0) { + kmx61_set_power_state(data, false, chan->address); mutex_unlock(&data->lock); return ret; } *val = sign_extend32(ret >> chan->scan_type.shift, chan->scan_type.realbits - 1); + kmx61_set_power_state(data, false, chan->address); mutex_unlock(&data->lock); return IIO_VAL_INT; @@ -693,12 +756,22 @@ static int kmx61_probe(struct i2c_client *client, ret = iio_device_register(data->mag_indio_dev); if (ret < 0) { dev_err(&client->dev, "Failed to register mag iio device\n"); - goto err_iio_unregister; + goto err_iio_unregister_acc; } + ret = pm_runtime_set_active(&client->dev); + if (ret < 0) + goto err_iio_unregister_mag; + + pm_runtime_enable(&client->dev); + pm_runtime_set_autosuspend_delay(&client->dev, KMX61_SLEEP_DELAY_MS); + pm_runtime_use_autosuspend(&client->dev); + return 0; -err_iio_unregister: +err_iio_unregister_mag: + iio_device_unregister(data->mag_indio_dev); +err_iio_unregister_acc: iio_device_unregister(data->acc_indio_dev); err_chip_uninit: kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); @@ -709,6 +782,10 @@ static int kmx61_remove(struct i2c_client *client) { struct kmx61_data *data = i2c_get_clientdata(client); + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + iio_device_unregister(data->acc_indio_dev); iio_device_unregister(data->mag_indio_dev); @@ -719,6 +796,38 @@ static int kmx61_remove(struct i2c_client *client) return 0; } + +#ifdef CONFIG_PM_RUNTIME +static int kmx61_runtime_suspend(struct device *dev) +{ + struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); + int ret; + + mutex_lock(&data->lock); + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + mutex_unlock(&data->lock); + + return ret; +} + +static int kmx61_runtime_resume(struct device *dev) +{ + struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); + u8 stby = 0; + + if (!data->acc_ps) + stby |= KMX61_ACC_STBY_BIT; + if (!data->mag_ps) + stby |= KMX61_MAG_STBY_BIT; + + return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); +} +#endif + +static const struct dev_pm_ops kmx61_pm_ops = { + SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL) +}; + static const struct acpi_device_id kmx61_acpi_match[] = { {"KMX61021", 0}, {} @@ -737,6 +846,7 @@ static struct i2c_driver kmx61_driver = { .driver = { .name = KMX61_DRV_NAME, .acpi_match_table = ACPI_PTR(kmx61_acpi_match), + .pm = &kmx61_pm_ops, }, .probe = kmx61_probe, .remove = kmx61_remove, -- cgit v0.10.2 From 3b9c40e604ee61e69a8aff6e1a426a6250ff4361 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:51 +0200 Subject: iio: imu: kmx61: Add PM sleep support Per sensor state (ACTIVE/STANDBY) is saved in driver's private data (acc_stby/mag_stby) and restored when resume is called. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index f3007dd..98d58e1 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -796,6 +797,33 @@ static int kmx61_remove(struct i2c_client *client) return 0; } +#ifdef CONFIG_PM_SLEEP +static int kmx61_suspend(struct device *dev) +{ + int ret; + struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); + + mutex_lock(&data->lock); + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, + false); + mutex_unlock(&data->lock); + + return ret; +} + +static int kmx61_resume(struct device *dev) +{ + u8 stby = 0; + struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); + + if (data->acc_stby) + stby |= KMX61_ACC_STBY_BIT; + if (data->mag_stby) + stby |= KMX61_MAG_STBY_BIT; + + return kmx61_set_mode(data, stby, KMX61_ACC | KMX61_MAG, true); +} +#endif #ifdef CONFIG_PM_RUNTIME static int kmx61_runtime_suspend(struct device *dev) @@ -825,6 +853,7 @@ static int kmx61_runtime_resume(struct device *dev) #endif static const struct dev_pm_ops kmx61_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(kmx61_suspend, kmx61_resume) SET_RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL) }; -- cgit v0.10.2 From c3a23ecc0901f624b681bbfbc4829766c5aa3070 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:52 +0200 Subject: iio: imu: kmx61: Add support for data ready triggers This creates a data ready trigger per IIO device. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index db4221d..5e610f7 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -28,6 +28,8 @@ config ADIS16480 config KMX61 tristate "Kionix KMX61 6-axis accelerometer and magnetometer" depends on I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help Say Y here if you want to build a driver for Kionix KMX61 6-axis accelerometer and magnetometer. diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 98d58e1..b8080fc 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -20,9 +20,14 @@ #include #include #include +#include +#include +#include +#include #define KMX61_DRV_NAME "kmx61" #define KMX61_GPIO_NAME "kmx61_int" +#define KMX61_IRQ_NAME "kmx61_event" #define KMX61_REG_WHO_AM_I 0x00 @@ -55,9 +60,11 @@ #define KMX61_MAG_ZOUT_L 0x16 #define KMX61_MAG_ZOUT_H 0x17 +#define KMX61_REG_INL 0x28 #define KMX61_REG_STBY 0x29 #define KMX61_REG_CTRL1 0x2A #define KMX61_REG_ODCNTL 0x2C +#define KMX61_REG_INC1 0x2D #define KMX61_ACC_STBY_BIT BIT(0) #define KMX61_MAG_STBY_BIT BIT(1) @@ -67,6 +74,13 @@ #define KMX61_REG_CTRL1_GSEL_MASK 0x03 +#define KMX61_REG_CTRL1_BIT_RES BIT(4) +#define KMX61_REG_CTRL1_BIT_DRDYE BIT(5) + +#define KMX61_REG_INC1_BIT_DRDYM BIT(1) +#define KMX61_REG_INC1_BIT_DRDYA BIT(2) +#define KMX61_REG_INC1_BIT_IEN BIT(5) + #define KMX61_ACC_ODR_SHIFT 0 #define KMX61_MAG_ODR_SHIFT 4 #define KMX61_ACC_ODR_MASK 0x0F @@ -100,9 +114,13 @@ struct kmx61_data { /* accelerometer specific data */ struct iio_dev *acc_indio_dev; + struct iio_trigger *acc_dready_trig; + bool acc_dready_trig_on; /* magnetometer specific data */ struct iio_dev *mag_indio_dev; + struct iio_trigger *mag_dready_trig; + bool mag_dready_trig_on; }; enum kmx61_range { @@ -466,6 +484,69 @@ static int kmx61_chip_init(struct kmx61_data *data) return 0; } +static int kmx61_setup_new_data_interrupt(struct kmx61_data *data, + bool status, u8 device) +{ + u8 mode; + int ret; + + ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + if (status) { + ret |= KMX61_REG_INC1_BIT_IEN; + if (device & KMX61_ACC) + ret |= KMX61_REG_INC1_BIT_DRDYA; + if (device & KMX61_MAG) + ret |= KMX61_REG_INC1_BIT_DRDYM; + } else { + ret &= ~KMX61_REG_INC1_BIT_IEN; + if (device & KMX61_ACC) + ret &= ~KMX61_REG_INC1_BIT_DRDYA; + if (device & KMX61_MAG) + ret &= ~KMX61_REG_INC1_BIT_DRDYM; + } + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); + return ret; + } + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + if (status) + ret |= KMX61_REG_CTRL1_BIT_DRDYE; + else + ret &= ~KMX61_REG_CTRL1_BIT_DRDYE; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); + return ret; + } + + ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); + if (ret) + return ret; + + return 0; +} + /** * kmx61_set_power_state() - set power state for kmx61 @device * @data - kmx61 device private pointer @@ -626,11 +707,34 @@ static int kmx61_write_raw(struct iio_dev *indio_dev, } } +static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + + if (data->acc_dready_trig != trig) + return -EINVAL; + + return 0; +} + +static int kmx61_mag_validate_trigger(struct iio_dev *indio_dev, + struct iio_trigger *trig) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + + if (data->mag_dready_trig != trig) + return -EINVAL; + + return 0; +} + static const struct iio_info kmx61_acc_info = { .driver_module = THIS_MODULE, .read_raw = kmx61_read_raw, .write_raw = kmx61_write_raw, .attrs = &kmx61_acc_attribute_group, + .validate_trigger = kmx61_acc_validate_trigger, }; static const struct iio_info kmx61_mag_info = { @@ -638,8 +742,109 @@ static const struct iio_info kmx61_mag_info = { .read_raw = kmx61_read_raw, .write_raw = kmx61_write_raw, .attrs = &kmx61_mag_attribute_group, + .validate_trigger = kmx61_mag_validate_trigger, +}; + + +static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + int ret = 0; + u8 device; + + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct kmx61_data *data = iio_priv(indio_dev); + + mutex_lock(&data->lock); + + if (data->acc_dready_trig == trig) + device = KMX61_ACC; + else + device = KMX61_MAG; + + ret = kmx61_set_power_state(data, state, device); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + + ret = kmx61_setup_new_data_interrupt(data, state, device); + if (ret < 0) { + kmx61_set_power_state(data, false, device); + mutex_unlock(&data->lock); + return ret; + } + + if (data->acc_dready_trig == trig) + data->acc_dready_trig_on = state; + else + data->mag_dready_trig_on = state; + + mutex_unlock(&data->lock); + + return 0; +} + +static int kmx61_trig_try_reenable(struct iio_trigger *trig) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct kmx61_data *data = kmx61_get_data(indio_dev); + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_inl\n"); + return ret; + } + + return 0; +} + +static const struct iio_trigger_ops kmx61_trigger_ops = { + .set_trigger_state = kmx61_data_rdy_trigger_set_state, + .try_reenable = kmx61_trig_try_reenable, + .owner = THIS_MODULE, }; +static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) +{ + struct kmx61_data *data = private; + + if (data->acc_dready_trig_on) + iio_trigger_poll(data->acc_dready_trig); + if (data->mag_dready_trig_on) + iio_trigger_poll(data->mag_dready_trig); + + return IRQ_HANDLED; +} + +static irqreturn_t kmx61_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct kmx61_data *data = kmx61_get_data(indio_dev); + int bit, ret, i = 0; + s16 buffer[8]; + + mutex_lock(&data->lock); + for_each_set_bit(bit, indio_dev->buffer->scan_mask, + indio_dev->masklength) { + ret = kmx61_read_measurement(data, KMX61_ACC_XOUT_L, bit); + if (ret < 0) { + mutex_unlock(&data->lock); + goto err; + } + buffer[i++] = ret; + } + mutex_unlock(&data->lock); + + iio_push_to_buffers(indio_dev, buffer); +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + static const char *kmx61_match_acpi_device(struct device *dev) { const struct acpi_device_id *id; @@ -702,6 +907,32 @@ static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data, return indio_dev; } +static struct iio_trigger *kmx61_trigger_setup(struct kmx61_data *data, + struct iio_dev *indio_dev, + const char *tag) +{ + struct iio_trigger *trig; + int ret; + + trig = devm_iio_trigger_alloc(&data->client->dev, + "%s-%s-dev%d", + indio_dev->name, + tag, + indio_dev->id); + if (!trig) + return ERR_PTR(-ENOMEM); + + trig->dev.parent = &data->client->dev; + trig->ops = &kmx61_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + + ret = iio_trigger_register(trig); + if (ret) + return ERR_PTR(ret); + + return trig; +} + static int kmx61_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -748,10 +979,55 @@ static int kmx61_probe(struct i2c_client *client, if (client->irq < 0) client->irq = kmx61_gpio_probe(client, data); + if (client->irq >= 0) { + ret = devm_request_threaded_irq(&client->dev, client->irq, + kmx61_data_rdy_trig_poll, + NULL, + IRQF_TRIGGER_RISING, + KMX61_IRQ_NAME, + data); + if (ret) + goto err_chip_uninit; + + data->acc_dready_trig = + kmx61_trigger_setup(data, data->acc_indio_dev, + "dready"); + if (IS_ERR(data->acc_dready_trig)) + return PTR_ERR(data->acc_dready_trig); + + data->mag_dready_trig = + kmx61_trigger_setup(data, data->mag_indio_dev, + "dready"); + if (IS_ERR(data->mag_dready_trig)) { + ret = PTR_ERR(data->mag_dready_trig); + goto err_trigger_unregister; + } + + ret = iio_triggered_buffer_setup(data->acc_indio_dev, + &iio_pollfunc_store_time, + kmx61_trigger_handler, + NULL); + if (ret < 0) { + dev_err(&data->client->dev, + "Failed to setup acc triggered buffer\n"); + goto err_trigger_unregister; + } + + ret = iio_triggered_buffer_setup(data->mag_indio_dev, + &iio_pollfunc_store_time, + kmx61_trigger_handler, + NULL); + if (ret < 0) { + dev_err(&data->client->dev, + "Failed to setup mag triggered buffer\n"); + goto err_trigger_unregister; + } + } + ret = iio_device_register(data->acc_indio_dev); if (ret < 0) { dev_err(&client->dev, "Failed to register acc iio device\n"); - goto err_chip_uninit; + goto err_buffer_cleanup; } ret = iio_device_register(data->mag_indio_dev); @@ -774,6 +1050,16 @@ err_iio_unregister_mag: iio_device_unregister(data->mag_indio_dev); err_iio_unregister_acc: iio_device_unregister(data->acc_indio_dev); +err_buffer_cleanup: + if (client->irq >= 0) { + iio_triggered_buffer_cleanup(data->acc_indio_dev); + iio_triggered_buffer_cleanup(data->mag_indio_dev); + } +err_trigger_unregister: + if (data->acc_dready_trig) + iio_trigger_unregister(data->acc_dready_trig); + if (data->mag_dready_trig) + iio_trigger_unregister(data->mag_dready_trig); err_chip_uninit: kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); return ret; @@ -790,6 +1076,13 @@ static int kmx61_remove(struct i2c_client *client) iio_device_unregister(data->acc_indio_dev); iio_device_unregister(data->mag_indio_dev); + if (client->irq >= 0) { + iio_triggered_buffer_cleanup(data->acc_indio_dev); + iio_triggered_buffer_cleanup(data->mag_indio_dev); + iio_trigger_unregister(data->acc_dready_trig); + iio_trigger_unregister(data->mag_dready_trig); + } + mutex_lock(&data->lock); kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); mutex_unlock(&data->lock); -- cgit v0.10.2 From fd3ae7a9f21c2a51a1d220bc7a7c3b45ab5e6ad1 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Dec 2014 15:31:53 +0200 Subject: iio: imu: kmx61: Add support for any motion trigger We use WUFE (Wake Up from Sleep Engine) and BTSE (Back to Sleep Engine) to detect general motion input. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index b8080fc..bda9c40 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,8 @@ #define KMX61_IRQ_NAME "kmx61_event" #define KMX61_REG_WHO_AM_I 0x00 +#define KMX61_REG_INS1 0x01 +#define KMX61_REG_INS2 0x02 /* * three 16-bit accelerometer output registers for X/Y/Z axis @@ -63,20 +66,36 @@ #define KMX61_REG_INL 0x28 #define KMX61_REG_STBY 0x29 #define KMX61_REG_CTRL1 0x2A +#define KMX61_REG_CTRL2 0x2B #define KMX61_REG_ODCNTL 0x2C #define KMX61_REG_INC1 0x2D +#define KMX61_REG_WUF_THRESH 0x3D +#define KMX61_REG_WUF_TIMER 0x3E + #define KMX61_ACC_STBY_BIT BIT(0) #define KMX61_MAG_STBY_BIT BIT(1) #define KMX61_ACT_STBY_BIT BIT(7) #define KMX61_ALL_STBY (KMX61_ACC_STBY_BIT | KMX61_MAG_STBY_BIT) +#define KMX61_REG_INS1_BIT_WUFS BIT(1) + +#define KMX61_REG_INS2_BIT_ZP BIT(0) +#define KMX61_REG_INS2_BIT_ZN BIT(1) +#define KMX61_REG_INS2_BIT_YP BIT(2) +#define KMX61_REG_INS2_BIT_YN BIT(3) +#define KMX61_REG_INS2_BIT_XP BIT(4) +#define KMX61_REG_INS2_BIT_XN BIT(5) + #define KMX61_REG_CTRL1_GSEL_MASK 0x03 #define KMX61_REG_CTRL1_BIT_RES BIT(4) #define KMX61_REG_CTRL1_BIT_DRDYE BIT(5) +#define KMX61_REG_CTRL1_BIT_WUFE BIT(6) +#define KMX61_REG_CTRL1_BIT_BTSE BIT(7) +#define KMX61_REG_INC1_BIT_WUFS BIT(0) #define KMX61_REG_INC1_BIT_DRDYM BIT(1) #define KMX61_REG_INC1_BIT_DRDYA BIT(2) #define KMX61_REG_INC1_BIT_IEN BIT(5) @@ -86,6 +105,11 @@ #define KMX61_ACC_ODR_MASK 0x0F #define KMX61_MAG_ODR_MASK 0xF0 +#define KMX61_OWUF_MASK 0x7 + +#define KMX61_DEFAULT_WAKE_THRESH 1 +#define KMX61_DEFAULT_WAKE_DURATION 1 + #define KMX61_SLEEP_DELAY_MS 2000 #define KMX61_CHIP_ID 0x12 @@ -111,11 +135,16 @@ struct kmx61_data { /* config bits */ u8 range; u8 odr_bits; + u8 wake_thresh; + u8 wake_duration; /* accelerometer specific data */ struct iio_dev *acc_indio_dev; struct iio_trigger *acc_dready_trig; + struct iio_trigger *motion_trig; bool acc_dready_trig_on; + bool motion_trig_on; + bool ev_enable_state; /* magnetometer specific data */ struct iio_dev *mag_indio_dev; @@ -154,6 +183,23 @@ static const struct { {3, 125000, 0x0A}, {6, 250000, 0x0B} }; +static const struct { + int val; + int val2; + int odr_bits; +} kmx61_wake_up_odr_table[] = { {0, 781000, 0x00}, + {1, 563000, 0x01}, + {3, 125000, 0x02}, + {6, 250000, 0x03}, + {12, 500000, 0x04}, + {25, 0, 0x05}, + {50, 0, 0x06}, + {100, 0, 0x06}, + {200, 0, 0x06}, + {400, 0, 0x06}, + {800, 0, 0x06}, + {1600, 0, 0x06} }; + static IIO_CONST_ATTR(accel_scale_available, "0.009582 0.019163 0.038326"); static IIO_CONST_ATTR(magn_scale_available, "0.001465"); static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( @@ -179,6 +225,14 @@ static const struct attribute_group kmx61_mag_attribute_group = { .attrs = kmx61_mag_attributes, }; +static const struct iio_event_spec kmx61_event = { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_PERIOD), +}; + #define KMX61_ACC_CHAN(_axis) { \ .type = IIO_ACCEL, \ .modified = 1, \ @@ -195,6 +249,8 @@ static const struct attribute_group kmx61_mag_attribute_group = { .shift = 4, \ .endianness = IIO_LE, \ }, \ + .event_spec = &kmx61_event, \ + .num_event_specs = 1 \ } #define KMX61_MAG_CHAN(_axis) { \ @@ -250,6 +306,31 @@ static int kmx61_convert_freq_to_bit(int val, int val2) return -EINVAL; } +static int kmx61_convert_bit_to_freq(u8 odr_bits, int *val, int *val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(kmx61_samp_freq_table); i++) + if (odr_bits == kmx61_samp_freq_table[i].odr_bits) { + *val = kmx61_samp_freq_table[i].val; + *val2 = kmx61_samp_freq_table[i].val2; + return 0; + } + return -EINVAL; +} + + +static int kmx61_convert_wake_up_odr_to_bit(int val, int val2) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(kmx61_wake_up_odr_table); ++i) + if (kmx61_wake_up_odr_table[i].val == val && + kmx61_wake_up_odr_table[i].val2 == val2) + return kmx61_wake_up_odr_table[i].odr_bits; + return -EINVAL; +} + /** * kmx61_set_mode() - set KMX61 device operating mode * @data - kmx61 device private data pointer @@ -338,6 +419,21 @@ static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) return 0; } +int kmx61_set_wake_up_odr(struct kmx61_data *data, int val, int val2) +{ + int ret, odr_bits; + + odr_bits = kmx61_convert_wake_up_odr_to_bit(val, val2); + if (odr_bits < 0) + return odr_bits; + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL2, + odr_bits); + if (ret < 0) + dev_err(&data->client->dev, "Error writing reg_ctrl2\n"); + return ret; +} + static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) { int ret; @@ -369,6 +465,12 @@ static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) if (ret < 0) return ret; + if (device & KMX61_ACC) { + ret = kmx61_set_wake_up_odr(data, val, val2); + if (ret) + return ret; + } + return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); } @@ -449,7 +551,7 @@ static int kmx61_set_scale(struct kmx61_data *data, u16 uscale) static int kmx61_chip_init(struct kmx61_data *data) { - int ret; + int ret, val, val2; ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_WHO_AM_I); if (ret < 0) { @@ -476,11 +578,23 @@ static int kmx61_chip_init(struct kmx61_data *data) } data->odr_bits = ret; + /* set output data rate for wake up (motion detection) function */ + ret = kmx61_convert_bit_to_freq(data->odr_bits, &val, &val2); + if (ret < 0) + return ret; + + ret = kmx61_set_wake_up_odr(data, val, val2); + if (ret < 0) + return ret; + /* set acc/magn to OPERATION mode */ ret = kmx61_set_mode(data, 0, KMX61_ACC | KMX61_MAG, true); if (ret < 0) return ret; + data->wake_thresh = KMX61_DEFAULT_WAKE_THRESH; + data->wake_duration = KMX61_DEFAULT_WAKE_DURATION; + return 0; } @@ -547,6 +661,87 @@ static int kmx61_setup_new_data_interrupt(struct kmx61_data *data, return 0; } +static int kmx61_chip_update_thresholds(struct kmx61_data *data) +{ + int ret; + + ret = i2c_smbus_write_byte_data(data->client, + KMX61_REG_WUF_TIMER, + data->wake_duration); + if (ret < 0) { + dev_err(&data->client->dev, "Errow writing reg_wuf_timer\n"); + return ret; + } + + ret = i2c_smbus_write_byte_data(data->client, + KMX61_REG_WUF_THRESH, + data->wake_thresh); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_wuf_thresh\n"); + return ret; + } + + return 0; +} + +static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, + bool status, u8 device) +{ + u8 mode; + int ret; + + ret = kmx61_get_mode(data, &mode, KMX61_ACC | KMX61_MAG); + if (ret < 0) + return ret; + + ret = kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); + if (ret < 0) + return ret; + + ret = kmx61_chip_update_thresholds(data); + if (ret < 0) + return ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INC1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_inc1\n"); + return ret; + } + if (status) + ret |= (KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS); + else + ret &= ~(KMX61_REG_INC1_BIT_IEN | KMX61_REG_INC1_BIT_WUFS); + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_INC1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_inc1\n"); + return ret; + } + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + return ret; + } + + if (status) + ret |= KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE; + else + ret &= ~(KMX61_REG_CTRL1_BIT_WUFE | KMX61_REG_CTRL1_BIT_BTSE); + + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); + if (ret < 0) { + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); + return ret; + } + mode |= KMX61_ACT_STBY_BIT; + ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); + if (ret) + return ret; + + return 0; +} + /** * kmx61_set_power_state() - set power state for kmx61 @device * @data - kmx61 device private pointer @@ -707,12 +902,111 @@ static int kmx61_write_raw(struct iio_dev *indio_dev, } } +static int kmx61_read_event(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + + *val2 = 0; + switch (info) { + case IIO_EV_INFO_VALUE: + *val = data->wake_thresh; + break; + case IIO_EV_INFO_PERIOD: + *val = data->wake_duration; + break; + default: + return -EINVAL; + } + + return IIO_VAL_INT; +} + +static int kmx61_write_event(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + + if (data->ev_enable_state) + return -EBUSY; + + switch (info) { + case IIO_EV_INFO_VALUE: + data->wake_thresh = val; + break; + case IIO_EV_INFO_PERIOD: + data->wake_duration = val; + break; + default: + return -EINVAL; + } + + return IIO_VAL_INT; +} + +static int kmx61_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + + return data->ev_enable_state; +} + +static int kmx61_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct kmx61_data *data = kmx61_get_data(indio_dev); + int ret; + + if (state && data->ev_enable_state) + return 0; + + mutex_lock(&data->lock); + + if (!state && data->motion_trig_on) { + data->ev_enable_state = 0; + mutex_unlock(&data->lock); + return 0; + } + + ret = kmx61_set_power_state(data, state, KMX61_ACC); + if (ret < 0) { + mutex_unlock(&data->lock); + return ret; + } + + ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); + if (ret < 0) { + kmx61_set_power_state(data, false, KMX61_ACC); + mutex_unlock(&data->lock); + return ret; + } + + data->ev_enable_state = state; + mutex_unlock(&data->lock); + + return 0; +} + static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig) { struct kmx61_data *data = kmx61_get_data(indio_dev); - if (data->acc_dready_trig != trig) + if (data->acc_dready_trig != trig && data->motion_trig != trig) return -EINVAL; return 0; @@ -734,6 +1028,10 @@ static const struct iio_info kmx61_acc_info = { .read_raw = kmx61_read_raw, .write_raw = kmx61_write_raw, .attrs = &kmx61_acc_attribute_group, + .read_event_value = kmx61_read_event, + .write_event_value = kmx61_write_event, + .read_event_config = kmx61_read_event_config, + .write_event_config = kmx61_write_event_config, .validate_trigger = kmx61_acc_validate_trigger, }; @@ -753,11 +1051,18 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, u8 device; struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); - struct kmx61_data *data = iio_priv(indio_dev); + struct kmx61_data *data = kmx61_get_data(indio_dev); mutex_lock(&data->lock); - if (data->acc_dready_trig == trig) + if (!state && data->ev_enable_state && data->motion_trig_on) { + data->motion_trig_on = false; + mutex_unlock(&data->lock); + return 0; + } + + + if (data->acc_dready_trig == trig || data->motion_trig) device = KMX61_ACC; else device = KMX61_MAG; @@ -768,7 +1073,10 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, return ret; } - ret = kmx61_setup_new_data_interrupt(data, state, device); + if (data->acc_dready_trig == trig || data->mag_dready_trig == trig) + ret = kmx61_setup_new_data_interrupt(data, state, device); + else + ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); if (ret < 0) { kmx61_set_power_state(data, false, device); mutex_unlock(&data->lock); @@ -777,8 +1085,10 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, if (data->acc_dready_trig == trig) data->acc_dready_trig_on = state; - else + else if (data->mag_dready_trig == trig) data->mag_dready_trig_on = state; + else + data->motion_trig_on = state; mutex_unlock(&data->lock); @@ -806,6 +1116,99 @@ static const struct iio_trigger_ops kmx61_trigger_ops = { .owner = THIS_MODULE, }; +static irqreturn_t kmx61_event_handler(int irq, void *private) +{ + struct kmx61_data *data = private; + struct iio_dev *indio_dev = data->acc_indio_dev; + int ret; + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ins1\n"); + goto ack_intr; + } + + if (ret & KMX61_REG_INS1_BIT_WUFS) { + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS2); + if (ret < 0) { + dev_err(&data->client->dev, "Error reading reg_ins2\n"); + goto ack_intr; + } + + if (ret & KMX61_REG_INS2_BIT_XN) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_X, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + 0); + + if (ret & KMX61_REG_INS2_BIT_XP) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_X, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + 0); + + if (ret & KMX61_REG_INS2_BIT_YN) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Y, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + 0); + + if (ret & KMX61_REG_INS2_BIT_YP) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Y, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + 0); + + if (ret & KMX61_REG_INS2_BIT_ZN) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + 0); + + if (ret & KMX61_REG_INS2_BIT_ZP) + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, + 0, + IIO_MOD_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + 0); + } + +ack_intr: + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_CTRL1); + if (ret < 0) + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + + ret |= KMX61_REG_CTRL1_BIT_RES; + ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); + if (ret < 0) + dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL); + if (ret < 0) + dev_err(&data->client->dev, "Error reading reg_inl\n"); + + ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1); + + return IRQ_HANDLED; +} + static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) { struct kmx61_data *data = private; @@ -815,6 +1218,11 @@ static irqreturn_t kmx61_data_rdy_trig_poll(int irq, void *private) if (data->mag_dready_trig_on) iio_trigger_poll(data->mag_dready_trig); + if (data->motion_trig_on) + iio_trigger_poll(data->motion_trig); + + if (data->ev_enable_state) + return IRQ_WAKE_THREAD; return IRQ_HANDLED; } @@ -982,7 +1390,7 @@ static int kmx61_probe(struct i2c_client *client, if (client->irq >= 0) { ret = devm_request_threaded_irq(&client->dev, client->irq, kmx61_data_rdy_trig_poll, - NULL, + kmx61_event_handler, IRQF_TRIGGER_RISING, KMX61_IRQ_NAME, data); @@ -1003,6 +1411,14 @@ static int kmx61_probe(struct i2c_client *client, goto err_trigger_unregister; } + data->motion_trig = + kmx61_trigger_setup(data, data->acc_indio_dev, + "any-motion"); + if (IS_ERR(data->motion_trig)) { + ret = PTR_ERR(data->motion_trig); + goto err_trigger_unregister; + } + ret = iio_triggered_buffer_setup(data->acc_indio_dev, &iio_pollfunc_store_time, kmx61_trigger_handler, @@ -1060,6 +1476,8 @@ err_trigger_unregister: iio_trigger_unregister(data->acc_dready_trig); if (data->mag_dready_trig) iio_trigger_unregister(data->mag_dready_trig); + if (data->motion_trig) + iio_trigger_unregister(data->motion_trig); err_chip_uninit: kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); return ret; @@ -1081,6 +1499,7 @@ static int kmx61_remove(struct i2c_client *client) iio_triggered_buffer_cleanup(data->mag_indio_dev); iio_trigger_unregister(data->acc_dready_trig); iio_trigger_unregister(data->mag_dready_trig); + iio_trigger_unregister(data->motion_trig); } mutex_lock(&data->lock); -- cgit v0.10.2 From ebd163660675534dd5f27c8d3fa426b8253a98f4 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Sat, 13 Dec 2014 00:28:52 +0800 Subject: iio: imu: kmx61: kmx61_set_wake_up_odr() can be static drivers/iio/imu/kmx61.c:422:5: sparse: symbol 'kmx61_set_wake_up_odr' was not declared. Should it be static? Signed-off-by: Fengguang Wu Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index bda9c40..9b32f01 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -419,7 +419,7 @@ static int kmx61_get_mode(struct kmx61_data *data, u8 *mode, u8 device) return 0; } -int kmx61_set_wake_up_odr(struct kmx61_data *data, int val, int val2) +static int kmx61_set_wake_up_odr(struct kmx61_data *data, int val, int val2) { int ret, odr_bits; -- cgit v0.10.2 From d9d0ac96554c21e40fd56982bc7f8f4bc557f16a Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 16 Dec 2014 11:11:45 +0200 Subject: iio: frequency: Remove 'out of memory' message This patch fixes the following checkpatch.pl warning: WARNING: Possible unnecessary 'out of memory' message Signed-off-by: Roberta Dobrescu Acked-by: Lars-Peter Clausen Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 63a25d9..2b301eb 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -387,10 +387,8 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev) int ret; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) { - dev_err(dev, "could not allocate memory for platform data\n"); + if (!pdata) return NULL; - } strncpy(&pdata->name[0], np->name, SPI_NAME_SIZE - 1); -- cgit v0.10.2 From 762c4da347109398bbcc7783b7ce2496664442ed Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 16 Dec 2014 11:11:46 +0200 Subject: iio: frequency: Remove unnecessary braces around single statement block This patch fixes the following checkpatch.pl warning: WARNING: braces {} are not necessary for single statement blocks Signed-off-by: Roberta Dobrescu Acked-by: Lars-Peter Clausen Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 2b301eb..10a0dfc 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -611,9 +611,8 @@ static int adf4350_remove(struct spi_device *spi) if (st->clk) clk_disable_unprepare(st->clk); - if (!IS_ERR(reg)) { + if (!IS_ERR(reg)) regulator_disable(reg); - } return 0; } -- cgit v0.10.2 From 44cf3798a3de3ebd8e5abe6c7fd5ee5c09b049de Mon Sep 17 00:00:00 2001 From: Hartmut Knaack Date: Fri, 19 Dec 2014 23:59:25 +0100 Subject: iio:pressure:bmp280: cleanup The calculations for temperature and pressure compensation were already slightly optimized in comparison to the datasheet. So, it makes sense to optimize even a bit more, making proper use of C operators: - variable t in bmp280_compensate_temp() can be eliminated by directly returning the result of the relevant equation. - make use of the += operator and eliminate an unnecessary parenthesis level in bmp280_compensate_press(). When the initialization of the ctrl_meas register fails, the error message will now mention the right register name. During probe, i2c_set_clientdata() is called, although it is not necessary. Drop it. Signed-off-by: Hartmut Knaack Reviewed-by: Vlad Dogaru Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/pressure/bmp280.c b/drivers/iio/pressure/bmp280.c index 47dfd34..7c623e2 100644 --- a/drivers/iio/pressure/bmp280.c +++ b/drivers/iio/pressure/bmp280.c @@ -148,7 +148,7 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data, s32 adc_temp) { int ret; - s32 var1, var2, t; + s32 var1, var2; __le16 buf[BMP280_COMP_TEMP_REG_COUNT / 2]; ret = regmap_bulk_read(data->regmap, BMP280_REG_COMP_TEMP_START, @@ -173,10 +173,7 @@ static s32 bmp280_compensate_temp(struct bmp280_data *data, ((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1])))) >> 12) * ((s32)(s16)le16_to_cpu(buf[T3]))) >> 14; - data->t_fine = var1 + var2; - t = (data->t_fine * 5 + 128) >> 8; - - return t; + return (data->t_fine * 5 + 128) >> 8; } /* @@ -203,8 +200,8 @@ static u32 bmp280_compensate_press(struct bmp280_data *data, var1 = ((s64)data->t_fine) - 128000; var2 = var1 * var1 * (s64)(s16)le16_to_cpu(buf[P6]); - var2 = var2 + ((var1 * (s64)(s16)le16_to_cpu(buf[P5])) << 17); - var2 = var2 + (((s64)(s16)le16_to_cpu(buf[P4])) << 35); + var2 += (var1 * (s64)(s16)le16_to_cpu(buf[P5])) << 17; + var2 += ((s64)(s16)le16_to_cpu(buf[P4])) << 35; var1 = ((var1 * var1 * (s64)(s16)le16_to_cpu(buf[P3])) >> 8) + ((var1 * (s64)(s16)le16_to_cpu(buf[P2])) << 12); var1 = ((((s64)1) << 47) + var1) * ((s64)le16_to_cpu(buf[P1])) >> 33; @@ -218,7 +215,7 @@ static u32 bmp280_compensate_press(struct bmp280_data *data, var2 = (((s64)(s16)le16_to_cpu(buf[P8])) * p) >> 19; p = ((p + var1 + var2) >> 8) + (((s64)(s16)le16_to_cpu(buf[P7])) << 4); - return (u32) p; + return (u32)p; } static int bmp280_read_temp(struct bmp280_data *data, @@ -330,7 +327,7 @@ static int bmp280_chip_init(struct bmp280_data *data) BMP280_MODE_NORMAL); if (ret < 0) { dev_err(&data->client->dev, - "failed to write config register\n"); + "failed to write ctrl_meas register\n"); return ret; } @@ -358,7 +355,6 @@ static int bmp280_probe(struct i2c_client *client, if (!indio_dev) return -ENOMEM; - i2c_set_clientdata(client, indio_dev); data = iio_priv(indio_dev); mutex_init(&data->lock); data->client = client; -- cgit v0.10.2 From 614e8842ddf5502f0e781f91695bfbc1e1e1d9b6 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 15 Dec 2014 17:14:49 +0200 Subject: iio: ABI: add clarification for proximity Signed-off-by: Vlad Dogaru Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index df5e69e..831db86 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1068,7 +1068,9 @@ Description: reflectivity of infrared or ultrasound emitted. Often these sensors are unit less and as such conversion to SI units is not possible. Where it is, the units should - be meters. + be meters. If such a conversion is not possible, the reported + values should behave in the same way as a distance, i.e. lower + values indicate something is closer to the sensor. What: /sys/.../iio:deviceX/in_illuminanceY_input What: /sys/.../iio:deviceX/in_illuminanceY_raw -- cgit v0.10.2 From 7ab374a053a43050117eb452306b6cd9dcb58cfd Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Fri, 19 Dec 2014 18:39:24 +0100 Subject: iio: kfifo: Remove unused argument in iio_kfifo_allocate indio_dev was unused in function body plus some small style fix - add new lines after "if(sth) return sth" and before the last return statement. The argument was removed also in its client. Signed-off-by: Karol Wrona Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index d550ac7..5eea299 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -250,7 +250,7 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev, struct iio_buffer *buffer; int ret; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/industrialio-triggered-buffer.c index 61a5d04..15a5341 100644 --- a/drivers/iio/industrialio-triggered-buffer.c +++ b/drivers/iio/industrialio-triggered-buffer.c @@ -49,7 +49,7 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev, struct iio_buffer *buffer; int ret; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) { ret = -ENOMEM; goto error_ret; diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index b20a9cf..7f6fad6 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -140,18 +140,20 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = { .release = &iio_kfifo_buffer_release, }; -struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) +struct iio_buffer *iio_kfifo_allocate(void) { struct iio_kfifo *kf; - kf = kzalloc(sizeof *kf, GFP_KERNEL); + kf = kzalloc(sizeof(*kf), GFP_KERNEL); if (!kf) return NULL; + kf->update_needed = true; iio_buffer_init(&kf->buffer); kf->buffer.access = &kfifo_access_funcs; kf->buffer.length = 2; mutex_init(&kf->user_lock); + return &kf->buffer; } EXPORT_SYMBOL(iio_kfifo_allocate); diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 9efc77b..1fd9009 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -393,7 +393,7 @@ int lis3l02dq_configure_buffer(struct iio_dev *indio_dev) int ret; struct iio_buffer *buffer; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index a2d72c1..360a4c9 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -121,7 +121,7 @@ int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) struct iio_buffer *buffer; /* Allocate a buffer to use - here a kfifo */ - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (buffer == NULL) { ret = -ENOMEM; goto error_ret; diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index c50b138..39f60aca0 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -626,7 +626,7 @@ static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) { struct iio_buffer *buffer; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index 27c3ed6..782fd9a 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -119,7 +119,7 @@ int ade7758_configure_ring(struct iio_dev *indio_dev) struct iio_buffer *buffer; int ret = 0; - buffer = iio_kfifo_allocate(indio_dev); + buffer = iio_kfifo_allocate(); if (!buffer) { ret = -ENOMEM; return ret; diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h index 25eeac7..1a8d57a 100644 --- a/include/linux/iio/kfifo_buf.h +++ b/include/linux/iio/kfifo_buf.h @@ -5,7 +5,7 @@ #include #include -struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); +struct iio_buffer *iio_kfifo_allocate(void); void iio_kfifo_free(struct iio_buffer *r); #endif -- cgit v0.10.2 From 780103fef5c88a97fb9c8d0079bf326ed6147f1f Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Fri, 19 Dec 2014 18:39:25 +0100 Subject: iio: kfifo: Add resource management devm_iio_kfifo_allocate/free iio kfifo allocate/free gained their devm_ wrappers. Signed-off-by: Karol Wrona Suggested-by: Jonathan Cameron Signed-off-by: Jonathan Cameron diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index b5ab416..6d1e8ee 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -258,6 +258,8 @@ IIO devm_iio_device_free() devm_iio_device_register() devm_iio_device_unregister() + devm_iio_kfifo_allocate() + devm_iio_kfifo_free() devm_iio_trigger_alloc() devm_iio_trigger_free() diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c index 7f6fad6..b2beea0 100644 --- a/drivers/iio/kfifo_buf.c +++ b/drivers/iio/kfifo_buf.c @@ -164,4 +164,58 @@ void iio_kfifo_free(struct iio_buffer *r) } EXPORT_SYMBOL(iio_kfifo_free); +static void devm_iio_kfifo_release(struct device *dev, void *res) +{ + iio_kfifo_free(*(struct iio_buffer **)res); +} + +static int devm_iio_kfifo_match(struct device *dev, void *res, void *data) +{ + struct iio_buffer **r = res; + + if (WARN_ON(!r || !*r)) + return 0; + + return *r == data; +} + +/** + * devm_iio_fifo_allocate - Resource-managed iio_kfifo_allocate() + * @dev: Device to allocate kfifo buffer for + * + * RETURNS: + * Pointer to allocated iio_buffer on success, NULL on failure. + */ +struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev) +{ + struct iio_buffer **ptr, *r; + + ptr = devres_alloc(devm_iio_kfifo_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + r = iio_kfifo_allocate(); + if (r) { + *ptr = r; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return r; +} +EXPORT_SYMBOL(devm_iio_kfifo_allocate); + +/** + * devm_iio_fifo_free - Resource-managed iio_kfifo_free() + * @dev: Device the buffer belongs to + * @r: The buffer associated with the device + */ +void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r) +{ + WARN_ON(devres_release(dev, devm_iio_kfifo_release, + devm_iio_kfifo_match, r)); +} +EXPORT_SYMBOL(devm_iio_kfifo_free); + MODULE_LICENSE("GPL"); diff --git a/include/linux/iio/kfifo_buf.h b/include/linux/iio/kfifo_buf.h index 1a8d57a..1683bc7 100644 --- a/include/linux/iio/kfifo_buf.h +++ b/include/linux/iio/kfifo_buf.h @@ -8,4 +8,7 @@ struct iio_buffer *iio_kfifo_allocate(void); void iio_kfifo_free(struct iio_buffer *r); +struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev); +void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r); + #endif -- cgit v0.10.2 From 20dd20f68f9b41534ba9ebddc4f179d0efbc3c8e Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Fri, 19 Dec 2014 18:39:26 +0100 Subject: iio: core: Get rid of misleading comment This comment did not fit here. It explains why devm_kmalloc uses dr_alloc. Generally is not needed at all. Signed-off-by: Karol Wrona Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index ee442ee..b7a397717 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1043,7 +1043,6 @@ struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv) if (!ptr) return NULL; - /* use raw alloc_dr for kmalloc caller tracing */ iio_dev = iio_device_alloc(sizeof_priv); if (iio_dev) { *ptr = iio_dev; -- cgit v0.10.2 From 60347e71c0d1f001aab75cb2569729980e2d737a Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 15 Dec 2014 17:16:51 +0200 Subject: iio: mma9551: fix sparse warning sparse warnings: (new ones prefixed by >>) >> drivers/iio/accel/mma9551.c:554:57: sparse: mixing different enum types drivers/iio/accel/mma9551.c:554:57: int enum mma9551_tilt_axis versus drivers/iio/accel/mma9551.c:554:57: int enum mma9551_gpio_pin >> drivers/iio/accel/mma9551.c:576:57: sparse: mixing different enum types drivers/iio/accel/mma9551.c:576:57: int enum mma9551_tilt_axis versus drivers/iio/accel/mma9551.c:576:57: int enum mma9551_gpio_pin Signed-off-by: Vlad Dogaru Reported-by: kbuild test robot Reviewed-by: Irina Tirdea Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index 1be125b..6563e26 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -551,7 +551,8 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev, return 0; if (state == 0) { - ret = mma9551_gpio_config(data->client, mma_axis, + ret = mma9551_gpio_config(data->client, + (enum mma9551_gpio_pin)mma_axis, MMA9551_APPID_NONE, 0, 0); if (ret < 0) return ret; @@ -573,7 +574,8 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev, return -EINVAL; } - ret = mma9551_gpio_config(data->client, mma_axis, + ret = mma9551_gpio_config(data->client, + (enum mma9551_gpio_pin)mma_axis, MMA9551_APPID_TILT, bitnum, 0); if (ret < 0) return ret; -- cgit v0.10.2 From 450a5ff768b008817d7914e3d2db16400e571dff Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 16 Dec 2014 11:16:06 +0200 Subject: iio: trigger: Add a blank line after declarations This patch fixes the following checkpatch.pl warning: WARNING: Missing a blank line after declarations Signed-off-by: Roberta Dobrescu Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/trigger/iio-trig-sysfs.c b/drivers/iio/trigger/iio-trig-sysfs.c index 254c7e9..3dfab2b 100644 --- a/drivers/iio/trigger/iio-trig-sysfs.c +++ b/drivers/iio/trigger/iio-trig-sysfs.c @@ -135,6 +135,7 @@ static int iio_sysfs_trigger_probe(int id) struct iio_sysfs_trig *t; int ret; bool foundit = false; + mutex_lock(&iio_sysfs_trig_list_mut); list_for_each_entry(t, &iio_sysfs_trig_list, l) if (id == t->id) { @@ -185,6 +186,7 @@ static int iio_sysfs_trigger_remove(int id) { bool foundit = false; struct iio_sysfs_trig *t; + mutex_lock(&iio_sysfs_trig_list_mut); list_for_each_entry(t, &iio_sysfs_trig_list, l) if (id == t->id) { -- cgit v0.10.2 From 6ed5ac50a3e0d21bc5423eea066913553c6c5320 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 15 Dec 2014 13:19:21 -0800 Subject: iio: imu: inv_mpu6050: ACPI enumeration Added changes so that the module can be enumerated via ACPI. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 6d2c115..f73e60b 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "inv_mpu_iio.h" /* @@ -875,6 +876,13 @@ static const struct i2c_device_id inv_mpu_id[] = { MODULE_DEVICE_TABLE(i2c, inv_mpu_id); +static const struct acpi_device_id inv_acpi_match[] = { + {"INVN6500", 0}, + { }, +}; + +MODULE_DEVICE_TABLE(acpi, inv_acpi_match); + static struct i2c_driver inv_mpu_driver = { .probe = inv_mpu_probe, .remove = inv_mpu_remove, @@ -883,6 +891,7 @@ static struct i2c_driver inv_mpu_driver = { .owner = THIS_MODULE, .name = "inv-mpu6050", .pm = INV_MPU6050_PMOPS, + .acpi_match_table = ACPI_PTR(inv_acpi_match), }, }; -- cgit v0.10.2 From e37156ec85f28b9008c7d8366ef0f936da018943 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sat, 20 Dec 2014 15:53:07 +0100 Subject: staging: iio: accel: sca3000_core.c: Remove unused function Remove the function sca3000_check_status() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c index 9cd04c7..31fb218 100644 --- a/drivers/staging/iio/accel/sca3000_core.c +++ b/drivers/staging/iio/accel/sca3000_core.c @@ -223,33 +223,6 @@ error_ret: return ret; } -#ifdef SCA3000_DEBUG -/** - * sca3000_check_status() check the status register - * - * Only used for debugging purposes - **/ -static int sca3000_check_status(struct device *dev) -{ - int ret; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct sca3000_state *st = iio_priv(indio_dev); - - mutex_lock(&st->lock); - ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_STATUS, 1); - if (ret < 0) - goto error_ret; - if (st->rx[0] & SCA3000_EEPROM_CS_ERROR) - dev_err(dev, "eeprom error\n"); - if (st->rx[0] & SCA3000_SPI_FRAME_ERROR) - dev_err(dev, "Previous SPI Frame was corrupt\n"); - -error_ret: - mutex_unlock(&st->lock); - return ret; -} -#endif /* SCA3000_DEBUG */ - /** * sca3000_show_rev() - sysfs interface to read the chip revision number **/ -- cgit v0.10.2 From b0868df4339fabf3dee680818f3193af352aa25d Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:57:53 +0200 Subject: iio: accel: kxcjk-1013: Add a blank line after declarations This patch fixes the following checkpatch.pl warning: WARNING: Missing a blank line after declarations Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index a5e7d30..09902f4e 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -1141,6 +1141,7 @@ static const char *kxcjk1013_match_acpi_device(struct device *dev, bool *is_smo8500_device) { const struct acpi_device_id *id; + id = acpi_match_device(dev->driver->acpi_match_table, dev); if (!id) return NULL; -- cgit v0.10.2 From c876109e66e11b85a057375d1fa15735813e5fd3 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:57:54 +0200 Subject: iio: accel: mma8452: Remove trailing whitespace This patch fixes the following checkpatch.pl error: ERROR: trailing whitespace Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 3c12d49..5b80657 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -111,7 +111,7 @@ static const int mma8452_samp_freq[8][2] = { {6, 250000}, {1, 560000} }; -/* +/* * Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048 * The userspace interface uses m/s^2 and we declare micro units * So scale factor is given by: -- cgit v0.10.2 From 88f4c6c468b86c58adddc56bb2ff768d6dc0c890 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:57:55 +0200 Subject: iio: accel: Annotate Kconfig entries with module name information This patch fixes the following checkpatch.pl warning: WARNING: please write a paragraph that describes the config symbol fully Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index d80616d..9f67c10 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -43,6 +43,9 @@ config HID_SENSOR_ACCEL_3D Say yes here to build support for the HID SENSOR accelerometers 3D. + To compile this driver as a module, choose M here: the + module will be called hid-sensor-accel-3d. + config IIO_ST_ACCEL_3AXIS tristate "STMicroelectronics accelerometers 3-Axis Driver" depends on (I2C || SPI_MASTER) && SYSFS @@ -80,6 +83,9 @@ config KXSD9 Say yes here to build support for the Kionix KXSD9 accelerometer. Currently this only supports the device via an SPI interface. + To compile this driver as a module, choose M here: the module + will be called kxsd9. + config MMA8452 tristate "Freescale MMA8452Q Accelerometer Driver" depends on I2C -- cgit v0.10.2 From 4f51c9ada76811d344d52deccf9014d329300858 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:48:49 +0200 Subject: iio: light: Annotate Kconfig entry with module name information This patch fixes the following checkpatch.pl warning: WARNING: please write a paragraph that describes the config symbol fully Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 2e2ba12..5a3237b 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -95,6 +95,9 @@ config HID_SENSOR_ALS Say yes here to build support for the HID SENSOR Ambient light sensor. + To compile this driver as a module, choose M here: the + module will be called hid-sensor-als. + config HID_SENSOR_PROX depends on HID_SENSOR_HUB select IIO_BUFFER -- cgit v0.10.2 From 586d48f92691976cc1932e2fdcbb3abd1bec8aa8 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:48:50 +0200 Subject: iio: light: lm3533-als: Remove space before ',' This patch fixes the following checkpatch.pl error: ERROR: space prohibited before that ',' (ctx:WxE) Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c index ae3c71b..076bc46 100644 --- a/drivers/iio/light/lm3533-als.c +++ b/drivers/iio/light/lm3533-als.c @@ -657,7 +657,7 @@ static ALS_HYSTERESIS_ATTR_RO(3); #define ILLUMINANCE_ATTR_RO(_name) \ DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO, show_##_name, NULL) #define ILLUMINANCE_ATTR_RW(_name) \ - DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO | S_IWUSR , \ + DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO | S_IWUSR, \ show_##_name, store_##_name) /* * ALS Zone threshold-event enable -- cgit v0.10.2 From c5878d9dbb959538d09faf9ad5f359e645de4d95 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:45:43 +0200 Subject: iio: amplifiers: ad8366: Remove space before ',' This patch fixes the following checkpatch.pl error: ERROR: space prohibited before that ',' (ctx:WxW) Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index ba6f6a9..fce25a0 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c @@ -166,7 +166,7 @@ static int ad8366_probe(struct spi_device *spi) if (ret) goto error_disable_reg; - ad8366_write(indio_dev, 0 , 0); + ad8366_write(indio_dev, 0, 0); return 0; -- cgit v0.10.2 From ff6f46295d81fab7ef7379761ea87ba71cc13fce Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:45:44 +0200 Subject: iio: amplifiers: ad8366: Use right order for type specification This patch fixes the following checkpatch.pl warning: WARNING: type 'char unsigned' should be specified in [[un]signed] [short|int|long|long long] order Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index fce25a0..c0d364e 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c @@ -31,7 +31,7 @@ struct ad8366_state { }; static int ad8366_write(struct iio_dev *indio_dev, - unsigned char ch_a, char unsigned ch_b) + unsigned char ch_a, unsigned char ch_b) { struct ad8366_state *st = iio_priv(indio_dev); int ret; -- cgit v0.10.2 From e904ce7e26c6ae84e8fb08b53cd466c0470445fd Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Tue, 30 Dec 2014 20:44:34 +0200 Subject: iio: frequency: ad9523: Increase sleep time in ad9523_store_eeprom This patch increases sleep time in ad9523_store_eeprom to 20ms since it isn't timing critical. It fixes the following checkpatch.pl warning: WARNING: msleep < 20ms can sleep for up to 20ms Signed-off-by: Roberta Dobrescu Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index 7c5245d..50ed8d1 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -445,7 +445,7 @@ static int ad9523_store_eeprom(struct iio_dev *indio_dev) tmp = 4; do { - msleep(16); + msleep(20); ret = ad9523_read(indio_dev, AD9523_EEPROM_DATA_XFER_STATUS); if (ret < 0) -- cgit v0.10.2 From 75d44ce08f3e5575c3060b04fa2abf99ba190284 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 29 Dec 2014 11:50:16 +0200 Subject: staging: iio: dummy: fix compile error when not using buffering Commit 4ae03019923f ("staging:iio:dummy: Register same channels for device and buffer") has changed the number of parameters for iio_simple_dummy_configure_buffer() only for the IIO_SIMPLE_DUMMY_BUFFER case. Fix this by also changing the placeholder function declared in the header when buffering is not enabled. Signed-off-by: Vlad Dogaru Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h index af70126..34989bf 100644 --- a/drivers/staging/iio/iio_simple_dummy.h +++ b/drivers/staging/iio/iio_simple_dummy.h @@ -117,8 +117,7 @@ enum iio_simple_dummy_scan_elements { int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev); void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev); #else -static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev, - const struct iio_chan_spec *channels, unsigned int num_channels) +static inline int iio_simple_dummy_configure_buffer(struct iio_dev *indio_dev) { return 0; }; -- cgit v0.10.2 From 4193c0f1d8631d439cea5f78329fe70f3a6e9128 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 29 Dec 2014 14:41:14 +0200 Subject: iio: driver for Semtech SX9500 proximity solution Supports buffering, IIO events and changing sampling frequency. Datasheet available at: http://www.semtech.com/images/datasheet/sx9500_ag.pdf Signed-off-by: Vlad Dogaru Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index 0c8cdf5..41a8d8f 100644 --- a/drivers/iio/proximity/Kconfig +++ b/drivers/iio/proximity/Kconfig @@ -17,3 +17,20 @@ config AS3935 module will be called as3935 endmenu + +menu "Proximity sensors" + +config SX9500 + tristate "SX9500 Semtech proximity sensor" + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + select REGMAP_I2C + depends on I2C + help + Say Y here to build a driver for Semtech's SX9500 capacitive + proximity/button sensor. + + To compile this driver as a module, choose M here: the + module will be called sx9500. + +endmenu diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile index 743adee..9818dc5 100644 --- a/drivers/iio/proximity/Makefile +++ b/drivers/iio/proximity/Makefile @@ -4,3 +4,4 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_AS3935) += as3935.o +obj-$(CONFIG_SX9500) += sx9500.o diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c new file mode 100644 index 0000000..74dff4e --- /dev/null +++ b/drivers/iio/proximity/sx9500.c @@ -0,0 +1,752 @@ +/* + * Copyright (c) 2014 Intel Corporation + * + * Driver for Semtech's SX9500 capacitive proximity/button solution. + * Datasheet available at + * . + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define SX9500_DRIVER_NAME "sx9500" +#define SX9500_IRQ_NAME "sx9500_event" +#define SX9500_GPIO_NAME "sx9500_gpio" + +/* Register definitions. */ +#define SX9500_REG_IRQ_SRC 0x00 +#define SX9500_REG_STAT 0x01 +#define SX9500_REG_IRQ_MSK 0x03 + +#define SX9500_REG_PROX_CTRL0 0x06 +#define SX9500_REG_PROX_CTRL1 0x07 +#define SX9500_REG_PROX_CTRL2 0x08 +#define SX9500_REG_PROX_CTRL3 0x09 +#define SX9500_REG_PROX_CTRL4 0x0a +#define SX9500_REG_PROX_CTRL5 0x0b +#define SX9500_REG_PROX_CTRL6 0x0c +#define SX9500_REG_PROX_CTRL7 0x0d +#define SX9500_REG_PROX_CTRL8 0x0e + +#define SX9500_REG_SENSOR_SEL 0x20 +#define SX9500_REG_USE_MSB 0x21 +#define SX9500_REG_USE_LSB 0x22 +#define SX9500_REG_AVG_MSB 0x23 +#define SX9500_REG_AVG_LSB 0x24 +#define SX9500_REG_DIFF_MSB 0x25 +#define SX9500_REG_DIFF_LSB 0x26 +#define SX9500_REG_OFFSET_MSB 0x27 +#define SX9500_REG_OFFSET_LSB 0x28 + +#define SX9500_REG_RESET 0x7f + +/* Write this to REG_RESET to do a soft reset. */ +#define SX9500_SOFT_RESET 0xde + +#define SX9500_SCAN_PERIOD_MASK GENMASK(6, 4) +#define SX9500_SCAN_PERIOD_SHIFT 4 + +/* + * These serve for identifying IRQ source in the IRQ_SRC register, and + * also for masking the IRQs in the IRQ_MSK register. + */ +#define SX9500_CLOSE_IRQ BIT(6) +#define SX9500_FAR_IRQ BIT(5) +#define SX9500_CONVDONE_IRQ BIT(3) + +#define SX9500_PROXSTAT_SHIFT 4 + +#define SX9500_NUM_CHANNELS 4 + +struct sx9500_data { + struct mutex mutex; + struct i2c_client *client; + struct iio_trigger *trig; + struct regmap *regmap; + /* + * Last reading of the proximity status for each channel. We + * only send an event to user space when this changes. + */ + bool prox_stat[SX9500_NUM_CHANNELS]; + bool event_enabled[SX9500_NUM_CHANNELS]; + bool trigger_enabled; + u16 *buffer; +}; + +static const struct iio_event_spec sx9500_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_EITHER, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + }, +}; + +#define SX9500_CHANNEL(idx) \ + { \ + .type = IIO_PROXIMITY, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .indexed = 1, \ + .channel = idx, \ + .event_spec = sx9500_events, \ + .num_event_specs = ARRAY_SIZE(sx9500_events), \ + .scan_index = idx, \ + .scan_type = { \ + .sign = 'u', \ + .realbits = 16, \ + .storagebits = 16, \ + .shift = 0, \ + }, \ + } + +static const struct iio_chan_spec sx9500_channels[] = { + SX9500_CHANNEL(0), + SX9500_CHANNEL(1), + SX9500_CHANNEL(2), + SX9500_CHANNEL(3), + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + +static const struct { + int val; + int val2; +} sx9500_samp_freq_table[] = { + {33, 333333}, + {16, 666666}, + {11, 111111}, + {8, 333333}, + {6, 666666}, + {5, 0}, + {3, 333333}, + {2, 500000}, +}; + +static const struct regmap_range sx9500_writable_reg_ranges[] = { + regmap_reg_range(SX9500_REG_IRQ_MSK, SX9500_REG_IRQ_MSK), + regmap_reg_range(SX9500_REG_PROX_CTRL0, SX9500_REG_PROX_CTRL8), + regmap_reg_range(SX9500_REG_SENSOR_SEL, SX9500_REG_SENSOR_SEL), + regmap_reg_range(SX9500_REG_OFFSET_MSB, SX9500_REG_OFFSET_LSB), + regmap_reg_range(SX9500_REG_RESET, SX9500_REG_RESET), +}; + +static const struct regmap_access_table sx9500_writeable_regs = { + .yes_ranges = sx9500_writable_reg_ranges, + .n_yes_ranges = ARRAY_SIZE(sx9500_writable_reg_ranges), +}; + +/* + * All allocated registers are readable, so we just list unallocated + * ones. + */ +static const struct regmap_range sx9500_non_readable_reg_ranges[] = { + regmap_reg_range(SX9500_REG_STAT + 1, SX9500_REG_STAT + 1), + regmap_reg_range(SX9500_REG_IRQ_MSK + 1, SX9500_REG_PROX_CTRL0 - 1), + regmap_reg_range(SX9500_REG_PROX_CTRL8 + 1, SX9500_REG_SENSOR_SEL - 1), + regmap_reg_range(SX9500_REG_OFFSET_LSB + 1, SX9500_REG_RESET - 1), +}; + +static const struct regmap_access_table sx9500_readable_regs = { + .no_ranges = sx9500_non_readable_reg_ranges, + .n_no_ranges = ARRAY_SIZE(sx9500_non_readable_reg_ranges), +}; + +static const struct regmap_range sx9500_volatile_reg_ranges[] = { + regmap_reg_range(SX9500_REG_IRQ_SRC, SX9500_REG_STAT), + regmap_reg_range(SX9500_REG_USE_MSB, SX9500_REG_OFFSET_LSB), + regmap_reg_range(SX9500_REG_RESET, SX9500_REG_RESET), +}; + +static const struct regmap_access_table sx9500_volatile_regs = { + .yes_ranges = sx9500_volatile_reg_ranges, + .n_yes_ranges = ARRAY_SIZE(sx9500_volatile_reg_ranges), +}; + +static const struct regmap_config sx9500_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .max_register = SX9500_REG_RESET, + .cache_type = REGCACHE_RBTREE, + + .wr_table = &sx9500_writeable_regs, + .rd_table = &sx9500_readable_regs, + .volatile_table = &sx9500_volatile_regs, +}; + +static int sx9500_read_proximity(struct sx9500_data *data, + const struct iio_chan_spec *chan, + int *val) +{ + int ret; + __be16 regval; + + ret = regmap_write(data->regmap, SX9500_REG_SENSOR_SEL, chan->channel); + if (ret < 0) + return ret; + + ret = regmap_bulk_read(data->regmap, SX9500_REG_USE_MSB, ®val, 2); + if (ret < 0) + return ret; + + *val = 32767 - (s16)be16_to_cpu(regval); + + return IIO_VAL_INT; +} + +static int sx9500_read_samp_freq(struct sx9500_data *data, + int *val, int *val2) +{ + int ret; + unsigned int regval; + + mutex_lock(&data->mutex); + ret = regmap_read(data->regmap, SX9500_REG_PROX_CTRL0, ®val); + mutex_unlock(&data->mutex); + + if (ret < 0) + return ret; + + regval = (regval & SX9500_SCAN_PERIOD_MASK) >> SX9500_SCAN_PERIOD_SHIFT; + *val = sx9500_samp_freq_table[regval].val; + *val2 = sx9500_samp_freq_table[regval].val2; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int sx9500_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long mask) +{ + struct sx9500_data *data = iio_priv(indio_dev); + int ret; + + switch (chan->type) { + case IIO_PROXIMITY: + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (iio_buffer_enabled(indio_dev)) + return -EBUSY; + mutex_lock(&data->mutex); + ret = sx9500_read_proximity(data, chan, val); + mutex_unlock(&data->mutex); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + return sx9500_read_samp_freq(data, val, val2); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int sx9500_set_samp_freq(struct sx9500_data *data, + int val, int val2) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(sx9500_samp_freq_table); i++) + if (val == sx9500_samp_freq_table[i].val && + val2 == sx9500_samp_freq_table[i].val2) + break; + + if (i == ARRAY_SIZE(sx9500_samp_freq_table)) + return -EINVAL; + + mutex_lock(&data->mutex); + + ret = regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, + SX9500_SCAN_PERIOD_MASK, + i << SX9500_SCAN_PERIOD_SHIFT); + + mutex_unlock(&data->mutex); + + return ret; +} + +static int sx9500_write_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int val, int val2, long mask) +{ + struct sx9500_data *data = iio_priv(indio_dev); + + switch (chan->type) { + case IIO_PROXIMITY: + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + return sx9500_set_samp_freq(data, val, val2); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static irqreturn_t sx9500_irq_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct sx9500_data *data = iio_priv(indio_dev); + + if (data->trigger_enabled) + iio_trigger_poll(data->trig); + + /* + * Even if no event is enabled, we need to wake the thread to + * clear the interrupt state by reading SX9500_REG_IRQ_SRC. It + * is not possible to do that here because regmap_read takes a + * mutex. + */ + return IRQ_WAKE_THREAD; +} + +static irqreturn_t sx9500_irq_thread_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct sx9500_data *data = iio_priv(indio_dev); + int ret; + unsigned int val, chan; + + mutex_lock(&data->mutex); + + ret = regmap_read(data->regmap, SX9500_REG_IRQ_SRC, &val); + if (ret < 0) { + dev_err(&data->client->dev, "i2c transfer error in irq\n"); + goto out; + } + + if (!(val & (SX9500_CLOSE_IRQ | SX9500_FAR_IRQ))) + goto out; + + ret = regmap_read(data->regmap, SX9500_REG_STAT, &val); + if (ret < 0) { + dev_err(&data->client->dev, "i2c transfer error in irq\n"); + goto out; + } + + val >>= SX9500_PROXSTAT_SHIFT; + for (chan = 0; chan < SX9500_NUM_CHANNELS; chan++) { + int dir; + u64 ev; + bool new_prox = val & BIT(chan); + + if (!data->event_enabled[chan]) + continue; + if (new_prox == data->prox_stat[chan]) + /* No change on this channel. */ + continue; + + dir = new_prox ? IIO_EV_DIR_FALLING : + IIO_EV_DIR_RISING; + ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, + chan, + IIO_EV_TYPE_THRESH, + dir); + iio_push_event(indio_dev, ev, iio_get_time_ns()); + data->prox_stat[chan] = new_prox; + } + +out: + mutex_unlock(&data->mutex); + + return IRQ_HANDLED; +} + +static int sx9500_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct sx9500_data *data = iio_priv(indio_dev); + + if (chan->type != IIO_PROXIMITY || type != IIO_EV_TYPE_THRESH || + dir != IIO_EV_DIR_EITHER) + return -EINVAL; + + return data->event_enabled[chan->channel]; +} + +static int sx9500_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct sx9500_data *data = iio_priv(indio_dev); + int ret, i; + bool any_active = false; + unsigned int irqmask; + + if (chan->type != IIO_PROXIMITY || type != IIO_EV_TYPE_THRESH || + dir != IIO_EV_DIR_EITHER) + return -EINVAL; + + mutex_lock(&data->mutex); + + data->event_enabled[chan->channel] = state; + + for (i = 0; i < SX9500_NUM_CHANNELS; i++) + if (data->event_enabled[i]) { + any_active = true; + break; + } + + irqmask = SX9500_CLOSE_IRQ | SX9500_FAR_IRQ; + if (any_active) + ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, + irqmask, irqmask); + else + ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, + irqmask, 0); + + mutex_unlock(&data->mutex); + + return ret; +} + +static int sx9500_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct sx9500_data *data = iio_priv(indio_dev); + + mutex_lock(&data->mutex); + kfree(data->buffer); + data->buffer = kzalloc(indio_dev->scan_bytes, GFP_KERNEL); + mutex_unlock(&data->mutex); + + if (data->buffer == NULL) + return -ENOMEM; + + return 0; +} + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( + "2.500000 3.333333 5 6.666666 8.333333 11.111111 16.666666 33.333333"); + +static struct attribute *sx9500_attributes[] = { + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group sx9500_attribute_group = { + .attrs = sx9500_attributes, +}; + +static const struct iio_info sx9500_info = { + .driver_module = THIS_MODULE, + .attrs = &sx9500_attribute_group, + .read_raw = &sx9500_read_raw, + .write_raw = &sx9500_write_raw, + .read_event_config = &sx9500_read_event_config, + .write_event_config = &sx9500_write_event_config, + .update_scan_mode = &sx9500_update_scan_mode, +}; + +static int sx9500_set_trigger_state(struct iio_trigger *trig, + bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct sx9500_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + + ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, + SX9500_CONVDONE_IRQ, + state ? SX9500_CONVDONE_IRQ : 0); + if (ret == 0) + data->trigger_enabled = state; + + mutex_unlock(&data->mutex); + + return ret; +} + +static const struct iio_trigger_ops sx9500_trigger_ops = { + .set_trigger_state = sx9500_set_trigger_state, + .owner = THIS_MODULE, +}; + +static irqreturn_t sx9500_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct sx9500_data *data = iio_priv(indio_dev); + int val, bit, ret, i = 0; + + mutex_lock(&data->mutex); + + for_each_set_bit(bit, indio_dev->buffer->scan_mask, + indio_dev->masklength) { + ret = sx9500_read_proximity(data, &indio_dev->channels[bit], + &val); + if (ret < 0) + goto out; + + data->buffer[i++] = val; + } + + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_get_time_ns()); + +out: + mutex_unlock(&data->mutex); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +struct sx9500_reg_default { + u8 reg; + u8 def; +}; + +static const struct sx9500_reg_default sx9500_default_regs[] = { + { + .reg = SX9500_REG_PROX_CTRL1, + /* Shield enabled, small range. */ + .def = 0x43, + }, + { + .reg = SX9500_REG_PROX_CTRL2, + /* x8 gain, 167kHz frequency, finest resolution. */ + .def = 0x77, + }, + { + .reg = SX9500_REG_PROX_CTRL3, + /* Doze enabled, 2x scan period doze, no raw filter. */ + .def = 0x40, + }, + { + .reg = SX9500_REG_PROX_CTRL4, + /* Average threshold. */ + .def = 0x30, + }, + { + .reg = SX9500_REG_PROX_CTRL5, + /* + * Debouncer off, lowest average negative filter, + * highest average postive filter. + */ + .def = 0x0f, + }, + { + .reg = SX9500_REG_PROX_CTRL6, + /* Proximity detection threshold: 280 */ + .def = 0x0e, + }, + { + .reg = SX9500_REG_PROX_CTRL7, + /* + * No automatic compensation, compensate each pin + * independently, proximity hysteresis: 32, close + * debouncer off, far debouncer off. + */ + .def = 0x00, + }, + { + .reg = SX9500_REG_PROX_CTRL8, + /* No stuck timeout, no periodic compensation. */ + .def = 0x00, + }, + { + .reg = SX9500_REG_PROX_CTRL0, + /* Scan period: 30ms, all sensors enabled. */ + .def = 0x0f, + }, +}; + +static int sx9500_init_device(struct iio_dev *indio_dev) +{ + struct sx9500_data *data = iio_priv(indio_dev); + int ret, i; + unsigned int val; + + ret = regmap_write(data->regmap, SX9500_REG_IRQ_MSK, 0); + if (ret < 0) + return ret; + + ret = regmap_write(data->regmap, SX9500_REG_RESET, + SX9500_SOFT_RESET); + if (ret < 0) + return ret; + + ret = regmap_read(data->regmap, SX9500_REG_IRQ_SRC, &val); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(sx9500_default_regs); i++) { + ret = regmap_write(data->regmap, + sx9500_default_regs[i].reg, + sx9500_default_regs[i].def); + if (ret < 0) + return ret; + } + + return 0; +} + +static int sx9500_gpio_probe(struct i2c_client *client, + struct sx9500_data *data) +{ + struct device *dev; + struct gpio_desc *gpio; + int ret; + + if (!client) + return -EINVAL; + + dev = &client->dev; + + /* data ready gpio interrupt pin */ + gpio = devm_gpiod_get_index(dev, SX9500_GPIO_NAME, 0); + if (IS_ERR(gpio)) { + dev_err(dev, "acpi gpio get index failed\n"); + return PTR_ERR(gpio); + } + + ret = gpiod_direction_input(gpio); + if (ret) + return ret; + + ret = gpiod_to_irq(gpio); + + dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); + + return ret; +} + +static int sx9500_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret; + struct iio_dev *indio_dev; + struct sx9500_data *data; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (indio_dev == NULL) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + mutex_init(&data->mutex); + data->trigger_enabled = false; + + data->regmap = devm_regmap_init_i2c(client, &sx9500_regmap_config); + if (IS_ERR(data->regmap)) + return PTR_ERR(data->regmap); + + sx9500_init_device(indio_dev); + + indio_dev->dev.parent = &client->dev; + indio_dev->name = SX9500_DRIVER_NAME; + indio_dev->channels = sx9500_channels; + indio_dev->num_channels = ARRAY_SIZE(sx9500_channels); + indio_dev->info = &sx9500_info; + indio_dev->modes = INDIO_DIRECT_MODE; + i2c_set_clientdata(client, indio_dev); + + if (client->irq <= 0) + client->irq = sx9500_gpio_probe(client, data); + + if (client->irq > 0) { + ret = devm_request_threaded_irq(&client->dev, client->irq, + sx9500_irq_handler, sx9500_irq_thread_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + SX9500_IRQ_NAME, indio_dev); + if (ret < 0) + return ret; + + data->trig = devm_iio_trigger_alloc(&client->dev, + "%s-dev%d", indio_dev->name, indio_dev->id); + if (!data->trig) + return -ENOMEM; + + data->trig->dev.parent = &client->dev; + data->trig->ops = &sx9500_trigger_ops; + iio_trigger_set_drvdata(data->trig, indio_dev); + + ret = iio_trigger_register(data->trig); + if (ret) + return ret; + } + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + sx9500_trigger_handler, NULL); + if (ret < 0) + goto out_trigger_unregister; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto out_buffer_cleanup; + + return 0; + +out_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); +out_trigger_unregister: + if (client->irq > 0) + iio_trigger_unregister(data->trig); + + return ret; +} + +static int sx9500_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct sx9500_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + if (client->irq > 0) + iio_trigger_unregister(data->trig); + kfree(data->buffer); + + return 0; +} + +static const struct acpi_device_id sx9500_acpi_match[] = { + {"SSX9500", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match); + +static const struct i2c_device_id sx9500_id[] = { + {"sx9500", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, sx9500_id); + +static struct i2c_driver sx9500_driver = { + .driver = { + .name = SX9500_DRIVER_NAME, + .acpi_match_table = ACPI_PTR(sx9500_acpi_match), + }, + .probe = sx9500_probe, + .remove = sx9500_remove, + .id_table = sx9500_id, +}; +module_i2c_driver(sx9500_driver); + +MODULE_AUTHOR("Vlad Dogaru "); +MODULE_DESCRIPTION("Driver for Semtech SX9500 proximity sensor"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 1f202725b70c3d6dc736904a0d1b77a5faed6690 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Thu, 1 Jan 2015 18:13:24 +0000 Subject: iio: inkern: add out of range error message If the DT contains an invalid channel specifier then the probe of iio_hwmon fails with the following message: iio_hwmon: probe of iio_hwmon failed with error -22 So it's better to print out the relevant channel specifier in error case to locate the problem. Signed-off-by: Stefan Wahren Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 21655fd..2800b80 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -116,8 +116,11 @@ static int __of_iio_simple_xlate(struct iio_dev *indio_dev, if (!iiospec->args_count) return 0; - if (iiospec->args[0] >= indio_dev->num_channels) + if (iiospec->args[0] >= indio_dev->num_channels) { + dev_err(&indio_dev->dev, "invalid channel index %u\n", + iiospec->args[0]); return -EINVAL; + } return iiospec->args[0]; } -- cgit v0.10.2 From 4e8439779ef613135049cea77f50cf58ccc44255 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:24 +0200 Subject: iio: imu: kmx61: Save odr_bits for later use Signed-off-by: Daniel Baluta Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 9b32f01..52c943d 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -465,6 +465,8 @@ static int kmx61_set_odr(struct kmx61_data *data, int val, int val2, u8 device) if (ret < 0) return ret; + data->odr_bits = odr_bits; + if (device & KMX61_ACC) { ret = kmx61_set_wake_up_odr(data, val, val2); if (ret) -- cgit v0.10.2 From a3da4fa301ae60aac688ca320fb8b46a053d6d25 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:25 +0200 Subject: iio: imu: kmx61: Don't ignore kmx61_set_power_state errors ..except while in an error handler, where there is nothing to be done anyway. Signed-off-by: Daniel Baluta Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 52c943d..6eaecb9 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -830,7 +830,12 @@ static int kmx61_read_raw(struct iio_dev *indio_dev, } mutex_lock(&data->lock); - kmx61_set_power_state(data, true, chan->address); + ret = kmx61_set_power_state(data, true, chan->address); + if (ret) { + mutex_unlock(&data->lock); + return ret; + } + ret = kmx61_read_measurement(data, base_reg, chan->scan_index); if (ret < 0) { kmx61_set_power_state(data, false, chan->address); @@ -839,9 +844,11 @@ static int kmx61_read_raw(struct iio_dev *indio_dev, } *val = sign_extend32(ret >> chan->scan_type.shift, chan->scan_type.realbits - 1); - kmx61_set_power_state(data, false, chan->address); + ret = kmx61_set_power_state(data, false, chan->address); mutex_unlock(&data->lock); + if (ret) + return ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: switch (chan->type) { -- cgit v0.10.2 From 28ff344e1d0a08d60149b859d47e1610fa5b622b Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:26 +0200 Subject: iio: imu: kmx61: Enhance error handling This fixes parts of kmx61 error handling to make code easier to read and to be more consistent with IIO coding conventions: * prefer as single point for error handling instead of duplicating code for each function * directly return a value from a case branch instead of breaking * fix error message for writing REG_CTRL1 Also, add separate error paths for kmx61_trigger_setup/iio_triggered_buffer_setup calls. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 6eaecb9..137c1d5 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -656,11 +656,7 @@ static int kmx61_setup_new_data_interrupt(struct kmx61_data *data, return ret; } - ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); - if (ret) - return ret; - - return 0; + return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); } static int kmx61_chip_update_thresholds(struct kmx61_data *data) @@ -678,12 +674,10 @@ static int kmx61_chip_update_thresholds(struct kmx61_data *data) ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_WUF_THRESH, data->wake_thresh); - if (ret < 0) { + if (ret < 0) dev_err(&data->client->dev, "Error writing reg_wuf_thresh\n"); - return ret; - } - return 0; + return ret; } static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, @@ -737,11 +731,7 @@ static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, return ret; } mode |= KMX61_ACT_STBY_BIT; - ret = kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); - if (ret) - return ret; - - return 0; + return kmx61_set_mode(data, mode, KMX61_ACC | KMX61_MAG, true); } /** @@ -924,15 +914,13 @@ static int kmx61_read_event(struct iio_dev *indio_dev, switch (info) { case IIO_EV_INFO_VALUE: *val = data->wake_thresh; - break; + return IIO_VAL_INT; case IIO_EV_INFO_PERIOD: *val = data->wake_duration; - break; + return IIO_VAL_INT; default: return -EINVAL; } - - return IIO_VAL_INT; } static int kmx61_write_event(struct iio_dev *indio_dev, @@ -950,15 +938,13 @@ static int kmx61_write_event(struct iio_dev *indio_dev, switch (info) { case IIO_EV_INFO_VALUE: data->wake_thresh = val; - break; + return IIO_VAL_INT; case IIO_EV_INFO_PERIOD: data->wake_duration = val; - break; + return IIO_VAL_INT; default: return -EINVAL; } - - return IIO_VAL_INT; } static int kmx61_read_event_config(struct iio_dev *indio_dev, @@ -978,7 +964,7 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev, int state) { struct kmx61_data *data = kmx61_get_data(indio_dev); - int ret; + int ret = 0; if (state && data->ev_enable_state) return 0; @@ -987,27 +973,25 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev, if (!state && data->motion_trig_on) { data->ev_enable_state = 0; - mutex_unlock(&data->lock); - return 0; + goto err_unlock; } ret = kmx61_set_power_state(data, state, KMX61_ACC); - if (ret < 0) { - mutex_unlock(&data->lock); - return ret; - } + if (ret < 0) + goto err_unlock; ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); if (ret < 0) { kmx61_set_power_state(data, false, KMX61_ACC); - mutex_unlock(&data->lock); - return ret; + goto err_unlock; } data->ev_enable_state = state; + +err_unlock: mutex_unlock(&data->lock); - return 0; + return ret; } static int kmx61_acc_validate_trigger(struct iio_dev *indio_dev, @@ -1066,8 +1050,7 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, if (!state && data->ev_enable_state && data->motion_trig_on) { data->motion_trig_on = false; - mutex_unlock(&data->lock); - return 0; + goto err_unlock; } @@ -1077,10 +1060,8 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, device = KMX61_MAG; ret = kmx61_set_power_state(data, state, device); - if (ret < 0) { - mutex_unlock(&data->lock); - return ret; - } + if (ret < 0) + goto err_unlock; if (data->acc_dready_trig == trig || data->mag_dready_trig == trig) ret = kmx61_setup_new_data_interrupt(data, state, device); @@ -1088,8 +1069,7 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); if (ret < 0) { kmx61_set_power_state(data, false, device); - mutex_unlock(&data->lock); - return ret; + goto err_unlock; } if (data->acc_dready_trig == trig) @@ -1098,10 +1078,10 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, data->mag_dready_trig_on = state; else data->motion_trig_on = state; - +err_unlock: mutex_unlock(&data->lock); - return 0; + return ret; } static int kmx61_trig_try_reenable(struct iio_trigger *trig) @@ -1207,7 +1187,7 @@ ack_intr: ret |= KMX61_REG_CTRL1_BIT_RES; ret = i2c_smbus_write_byte_data(data->client, KMX61_REG_CTRL1, ret); if (ret < 0) - dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); + dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INL); if (ret < 0) @@ -1409,15 +1389,17 @@ static int kmx61_probe(struct i2c_client *client, data->acc_dready_trig = kmx61_trigger_setup(data, data->acc_indio_dev, "dready"); - if (IS_ERR(data->acc_dready_trig)) - return PTR_ERR(data->acc_dready_trig); + if (IS_ERR(data->acc_dready_trig)) { + ret = PTR_ERR(data->acc_dready_trig); + goto err_chip_uninit; + } data->mag_dready_trig = kmx61_trigger_setup(data, data->mag_indio_dev, "dready"); if (IS_ERR(data->mag_dready_trig)) { ret = PTR_ERR(data->mag_dready_trig); - goto err_trigger_unregister; + goto err_trigger_unregister_acc_dready; } data->motion_trig = @@ -1425,7 +1407,7 @@ static int kmx61_probe(struct i2c_client *client, "any-motion"); if (IS_ERR(data->motion_trig)) { ret = PTR_ERR(data->motion_trig); - goto err_trigger_unregister; + goto err_trigger_unregister_mag_dready; } ret = iio_triggered_buffer_setup(data->acc_indio_dev, @@ -1435,7 +1417,7 @@ static int kmx61_probe(struct i2c_client *client, if (ret < 0) { dev_err(&data->client->dev, "Failed to setup acc triggered buffer\n"); - goto err_trigger_unregister; + goto err_trigger_unregister_motion; } ret = iio_triggered_buffer_setup(data->mag_indio_dev, @@ -1445,14 +1427,14 @@ static int kmx61_probe(struct i2c_client *client, if (ret < 0) { dev_err(&data->client->dev, "Failed to setup mag triggered buffer\n"); - goto err_trigger_unregister; + goto err_buffer_cleanup_acc; } } ret = iio_device_register(data->acc_indio_dev); if (ret < 0) { dev_err(&client->dev, "Failed to register acc iio device\n"); - goto err_buffer_cleanup; + goto err_buffer_cleanup_mag; } ret = iio_device_register(data->mag_indio_dev); @@ -1475,18 +1457,18 @@ err_iio_unregister_mag: iio_device_unregister(data->mag_indio_dev); err_iio_unregister_acc: iio_device_unregister(data->acc_indio_dev); -err_buffer_cleanup: - if (client->irq >= 0) { - iio_triggered_buffer_cleanup(data->acc_indio_dev); +err_buffer_cleanup_mag: + if (client->irq >= 0) iio_triggered_buffer_cleanup(data->mag_indio_dev); - } -err_trigger_unregister: - if (data->acc_dready_trig) - iio_trigger_unregister(data->acc_dready_trig); - if (data->mag_dready_trig) - iio_trigger_unregister(data->mag_dready_trig); - if (data->motion_trig) - iio_trigger_unregister(data->motion_trig); +err_buffer_cleanup_acc: + if (client->irq >= 0) + iio_triggered_buffer_cleanup(data->acc_indio_dev); +err_trigger_unregister_motion: + iio_trigger_unregister(data->motion_trig); +err_trigger_unregister_mag_dready: + iio_trigger_unregister(data->mag_dready_trig); +err_trigger_unregister_acc_dready: + iio_trigger_unregister(data->acc_dready_trig); err_chip_uninit: kmx61_set_mode(data, KMX61_ALL_STBY, KMX61_ACC | KMX61_MAG, true); return ret; -- cgit v0.10.2 From dfb12edea5577243d4ea64d93a32f575e8b1cc4c Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:27 +0200 Subject: iio: imu: kmx61: Fixup parameters alignment Signed-off-by: Daniel Baluta Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 137c1d5..bf3468b 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -924,11 +924,11 @@ static int kmx61_read_event(struct iio_dev *indio_dev, } static int kmx61_write_event(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int val, int val2) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { struct kmx61_data *data = kmx61_get_data(indio_dev); @@ -958,10 +958,10 @@ static int kmx61_read_event_config(struct iio_dev *indio_dev, } static int kmx61_write_event_config(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - int state) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) { struct kmx61_data *data = kmx61_get_data(indio_dev); int ret = 0; -- cgit v0.10.2 From 0475c68544ddcb72905e35cb8c050c523020e2c7 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:28 +0200 Subject: iio: imu: kmx61: Drop unused device parameter Signed-off-by: Daniel Baluta Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index bf3468b..777b7f6 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -681,7 +681,7 @@ static int kmx61_chip_update_thresholds(struct kmx61_data *data) } static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, - bool status, u8 device) + bool status) { u8 mode; int ret; @@ -980,7 +980,7 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev, if (ret < 0) goto err_unlock; - ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); + ret = kmx61_setup_any_motion_interrupt(data, state); if (ret < 0) { kmx61_set_power_state(data, false, KMX61_ACC); goto err_unlock; @@ -1066,7 +1066,7 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, if (data->acc_dready_trig == trig || data->mag_dready_trig == trig) ret = kmx61_setup_new_data_interrupt(data, state, device); else - ret = kmx61_setup_any_motion_interrupt(data, state, KMX61_ACC); + ret = kmx61_setup_any_motion_interrupt(data, state); if (ret < 0) { kmx61_set_power_state(data, false, device); goto err_unlock; -- cgit v0.10.2 From d4a4ae04d236a01a8648648a0e11777250ab2974 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:29 +0200 Subject: iio: imu: kmx61: Use false instead of 0 for ev_enable_state Signed-off-by: Daniel Baluta Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 777b7f6..a70a3ef 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -972,7 +972,7 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev, mutex_lock(&data->lock); if (!state && data->motion_trig_on) { - data->ev_enable_state = 0; + data->ev_enable_state = false; goto err_unlock; } -- cgit v0.10.2 From dbdd0e2dd9981eafe33687d0b2d089c5285ea22b Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:30 +0200 Subject: iio: imu: kmx61: Fix device initialization when setting trigger state Signed-off-by: Daniel Baluta Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index a70a3ef..578e3dd 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -1053,8 +1053,7 @@ static int kmx61_data_rdy_trigger_set_state(struct iio_trigger *trig, goto err_unlock; } - - if (data->acc_dready_trig == trig || data->motion_trig) + if (data->acc_dready_trig == trig || data->motion_trig == trig) device = KMX61_ACC; else device = KMX61_MAG; -- cgit v0.10.2 From ea04d2965874ca5753e756b335449c5322a85733 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:31 +0200 Subject: iio: imu: kmx61: Remove unnecessary REG_INS1 read Useful in the debugging phase, not needed now. Signed-off-by: Daniel Baluta Acked-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 578e3dd..1f7c3f1 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -1192,8 +1192,6 @@ ack_intr: if (ret < 0) dev_err(&data->client->dev, "Error reading reg_inl\n"); - ret = i2c_smbus_read_byte_data(data->client, KMX61_REG_INS1); - return IRQ_HANDLED; } -- cgit v0.10.2 From 6a191c7025f80c328156a358871f5d947f443aa9 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Tue, 23 Dec 2014 15:22:33 +0200 Subject: iio: imu: kmx61: Use correct base when reading data We have two IIO devices and we need to adjust the base when reading data. Signed-off-by: Daniel Baluta Reviewed-by: Hartmut Knaack Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index 1f7c3f1..b60b22d 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -1218,12 +1218,18 @@ static irqreturn_t kmx61_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct kmx61_data *data = kmx61_get_data(indio_dev); int bit, ret, i = 0; + u8 base; s16 buffer[8]; + if (indio_dev == data->acc_indio_dev) + base = KMX61_ACC_XOUT_L; + else + base = KMX61_MAG_XOUT_L; + mutex_lock(&data->lock); for_each_set_bit(bit, indio_dev->buffer->scan_mask, indio_dev->masklength) { - ret = kmx61_read_measurement(data, KMX61_ACC_XOUT_L, bit); + ret = kmx61_read_measurement(data, base, bit); if (ret < 0) { mutex_unlock(&data->lock); goto err; -- cgit v0.10.2 From a5b940fa4ac0c4d8d9e07bda17a68a042e4d1d94 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 29 Dec 2014 10:27:20 +0000 Subject: DT: mxs-lradc: fix ranges of ts properties This patch fixes off-by-one issues in the devicetree binding of mxs-lradc. According to the i.MX23 and i.MX28 reference manuals [1][2] the range of NUM_SAMPLES is 0..31, but property ave-ctrl is substracted by 1 before used. Considering all limitations the range of DELAY is 1..2047, but also property ave-delay is substracted by 1 before used. The patch has been suggested by Hartmut Knaack and Kristina Martsenko. [1] - http://cache.freescale.com/files/dsp/doc/ref_manual/IMX23RM.pdf [2] - http://cache.freescale.com/files/dsp/doc/ref_manual/MCIMX28RM.pdf Signed-off-by: Stefan Wahren Signed-off-by: Jonathan Cameron diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt index ee05dc3..3075377 100644 --- a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt +++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt @@ -12,9 +12,9 @@ Optional properties: property is not present, then the touchscreen is disabled. 5 wires is valid for i.MX28 SoC only. - fsl,ave-ctrl: number of samples per direction to calculate an average value. - Allowed value is 1 ... 31, default is 4 + Allowed value is 1 ... 32, default is 4 - fsl,ave-delay: delay between consecutive samples. Allowed value is - 1 ... 2047. It is used if 'fsl,ave-ctrl' > 1, counts at + 2 ... 2048. It is used if 'fsl,ave-ctrl' > 1, counts at 2 kHz and its default is 2 (= 1 ms) - fsl,settling: delay between plate switch to next sample. Allowed value is 1 ... 2047. It counts at 2 kHz and its default is -- cgit v0.10.2 From c22d2672c826a67a84fa60c17797315f4c94cedb Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 29 Dec 2014 10:27:21 +0000 Subject: iio: mxs-lradc: check ranges of ts properties The devicetree binding for mxs-lradc defines ranges for the touchscreen properties. In order to avoid unexpected behavior like division by zero, we better check these ranges during probe and abort in error case. Additionally this patch adds an important note from the reference manual about the range of sample delay. Signed-off-by: Stefan Wahren Reviewed-by: Marek Vasut Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index 6757f10..e0e9183 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -436,7 +436,14 @@ static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch) */ mxs_lradc_reg_clear(lradc, LRADC_CH_VALUE_MASK, LRADC_CH(ch)); - /* prepare the delay/loop unit according to the oversampling count */ + /* + * prepare the delay/loop unit according to the oversampling count + * + * from the datasheet: + * "The DELAY fields in HW_LRADC_DELAY0, HW_LRADC_DELAY1, + * HW_LRADC_DELAY2, and HW_LRADC_DELAY3 must be non-zero; otherwise, + * the LRADC will not trigger the delay group." + */ mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << ch) | LRADC_DELAY_TRIGGER_DELAYS(0) | LRADC_DELAY_LOOP(lradc->over_sample_cnt - 1) | @@ -1495,20 +1502,38 @@ static int mxs_lradc_probe_touchscreen(struct mxs_lradc *lradc, return -EINVAL; } - lradc->over_sample_cnt = 4; - ret = of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt); - if (ret == 0) + if (of_property_read_u32(lradc_node, "fsl,ave-ctrl", &adapt)) { + lradc->over_sample_cnt = 4; + } else { + if (adapt < 1 || adapt > 32) { + dev_err(lradc->dev, "Invalid sample count (%u)\n", + adapt); + return -EINVAL; + } lradc->over_sample_cnt = adapt; + } - lradc->over_sample_delay = 2; - ret = of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt); - if (ret == 0) + if (of_property_read_u32(lradc_node, "fsl,ave-delay", &adapt)) { + lradc->over_sample_delay = 2; + } else { + if (adapt < 2 || adapt > LRADC_DELAY_DELAY_MASK + 1) { + dev_err(lradc->dev, "Invalid sample delay (%u)\n", + adapt); + return -EINVAL; + } lradc->over_sample_delay = adapt; + } - lradc->settling_delay = 10; - ret = of_property_read_u32(lradc_node, "fsl,settling", &adapt); - if (ret == 0) + if (of_property_read_u32(lradc_node, "fsl,settling", &adapt)) { + lradc->settling_delay = 10; + } else { + if (adapt < 1 || adapt > LRADC_DELAY_DELAY_MASK) { + dev_err(lradc->dev, "Invalid settling delay (%u)\n", + adapt); + return -EINVAL; + } lradc->settling_delay = adapt; + } return 0; } -- cgit v0.10.2 From 8f5d8727a7736024f28101b922d23754c67c2cc8 Mon Sep 17 00:00:00 2001 From: Vlad Dogaru Date: Mon, 29 Dec 2014 11:37:48 +0200 Subject: iio: ensure scan index is unique at device register Having two or more channels with the same positive scan_index field makes no sense if the device supports buffering. Prevent this situation by failing to register such a device. Signed-off-by: Vlad Dogaru Reviewed-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index b7a397717..69feb91 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1134,6 +1134,29 @@ static const struct file_operations iio_buffer_fileops = { .compat_ioctl = iio_ioctl, }; +static int iio_check_unique_scan_index(struct iio_dev *indio_dev) +{ + int i, j; + const struct iio_chan_spec *channels = indio_dev->channels; + + if (!(indio_dev->modes & INDIO_ALL_BUFFER_MODES)) + return 0; + + for (i = 0; i < indio_dev->num_channels - 1; i++) { + if (channels[i].scan_index < 0) + continue; + for (j = i + 1; j < indio_dev->num_channels; j++) + if (channels[i].scan_index == channels[j].scan_index) { + dev_err(&indio_dev->dev, + "Duplicate scan index %d\n", + channels[i].scan_index); + return -EINVAL; + } + } + + return 0; +} + static const struct iio_buffer_setup_ops noop_ring_setup_ops; /** @@ -1148,6 +1171,10 @@ int iio_device_register(struct iio_dev *indio_dev) if (!indio_dev->dev.of_node && indio_dev->dev.parent) indio_dev->dev.of_node = indio_dev->dev.parent->of_node; + ret = iio_check_unique_scan_index(indio_dev); + if (ret < 0) + return ret; + /* configure elements for the chrdev */ indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); -- cgit v0.10.2 From 66ad1fd025c7cb9d0d4d01de965c80871226f422 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Sun, 21 Dec 2014 02:42:26 +0200 Subject: iio: buffer: fix custom buffer attributes copy Signed-off-by: Octavian Purdila Reviewed-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 2bd8d39..403b728 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -789,7 +789,7 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) buffer->buffer_group.attrs[1] = &dev_attr_enable.attr; if (buffer->attrs) memcpy(&buffer->buffer_group.attrs[2], buffer->attrs, - sizeof(*&buffer->buffer_group.attrs) * (attrcount - 2)); + sizeof(*&buffer->buffer_group.attrs) * attrcount); buffer->buffer_group.attrs[attrcount+2] = NULL; indio_dev->groups[indio_dev->groupcounter++] = &buffer->buffer_group; -- cgit v0.10.2 From 9251d14a275878879400eefae7601c3ee7ee9d71 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 25 Sep 2014 16:27:14 +0200 Subject: staging:iio:ad5933: Report temperature as raw value We shouldn't be doing the unit conversion in kernel space. Just report the raw value for the property and the scale. Userspace can do the conversion if necessary. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index 39f60aca0..d18a8ec 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -113,7 +113,8 @@ static const struct iio_chan_spec ad5933_channels[] = { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), .address = AD5933_REG_TEMP_DATA, .scan_index = -1, .scan_type = { @@ -520,12 +521,11 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, { struct ad5933_state *st = iio_priv(indio_dev); __be16 dat; - int ret = -EINVAL; + int ret; - mutex_lock(&indio_dev->mlock); switch (m) { case IIO_CHAN_INFO_RAW: - case IIO_CHAN_INFO_PROCESSED: + mutex_lock(&indio_dev->mlock); if (iio_buffer_enabled(indio_dev)) { ret = -EBUSY; goto out; @@ -543,16 +543,16 @@ static int ad5933_read_raw(struct iio_dev *indio_dev, if (ret < 0) goto out; mutex_unlock(&indio_dev->mlock); - ret = be16_to_cpu(dat); - /* Temp in Milli degrees Celsius */ - if (ret < 8192) - *val = ret * 1000 / 32; - else - *val = (ret - 16384) * 1000 / 32; + *val = sign_extend32(be16_to_cpu(dat), 13); return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 1000; + *val2 = 5; + return IIO_VAL_FRACTIONAL_LOG2; } + return -EINVAL; out: mutex_unlock(&indio_dev->mlock); return ret; -- cgit v0.10.2 From 0a01db9d64350754f5d714d44dab81cb97a67a81 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 25 Sep 2014 16:27:15 +0200 Subject: staging:iio:ad5933: Remove platform data from state struct The platform data is only used in the probe function. No need to keep it around. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index d18a8ec..e90653f 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -89,7 +89,6 @@ struct ad5933_state { struct i2c_client *client; struct regulator *reg; - struct ad5933_platform_data *pdata; struct delayed_work work; unsigned long mclk_hz; unsigned char ctrl_hb; @@ -712,9 +711,7 @@ static int ad5933_probe(struct i2c_client *client, st->client = client; if (!pdata) - st->pdata = &ad5933_default_pdata; - else - st->pdata = pdata; + pdata = &ad5933_default_pdata; st->reg = devm_regulator_get(&client->dev, "vcc"); if (!IS_ERR(st->reg)) { @@ -727,10 +724,10 @@ static int ad5933_probe(struct i2c_client *client, if (voltage_uv) st->vref_mv = voltage_uv / 1000; else - st->vref_mv = st->pdata->vref_mv; + st->vref_mv = pdata->vref_mv; - if (st->pdata->ext_clk_Hz) { - st->mclk_hz = st->pdata->ext_clk_Hz; + if (pdata->ext_clk_Hz) { + st->mclk_hz = pdata->ext_clk_Hz; st->ctrl_lb = AD5933_CTRL_EXT_SYSCLK; } else { st->mclk_hz = AD5933_INT_OSC_FREQ_Hz; -- cgit v0.10.2 From 54c3ef46572015e05537526304b0d22095821a7f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 3 Dec 2014 11:25:32 -0700 Subject: staging: comedi: hwdrv_apci1500: introduce z8536_read() The Z8536 CIO registers are indirectly read by writing the register offset to the control register then reading the control register to get the value. Introduce a helper function to read the Z8536 CIO registers. The registers are read from "normal" code and in the interrupt handler, spinlock the sequence to protect the indirect register access. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index bfa9228..594f132 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -129,6 +129,20 @@ static int i_InputChannel; static int i_TimerCounter1Enabled, i_TimerCounter2Enabled, i_WatchdogCounter3Enabled; +static unsigned int z8536_read(struct comedi_device *dev, unsigned int reg) +{ + struct apci1500_private *devpriv = dev->private; + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&dev->spinlock, flags); + outb(reg, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + val = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + spin_unlock_irqrestore(&dev->spinlock, flags); + + return val; +} + /* * An event can be generated for each port. The first event is related to the * first 8 channels (port 1) and the second to the following 6 channels (port 2) @@ -311,14 +325,8 @@ static int apci1500_di_config(struct comedi_device *dev, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the mode specification mask */ - /* register of port 1 */ - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, + APCI1500_RW_PORT_A_SPECIFICATION); /* Selects the mode specification mask */ /* register of port 1 */ @@ -366,14 +374,8 @@ static int apci1500_di_config(struct comedi_device *dev, outb(0x74, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the mode specification mask */ - /* register of port B */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, + APCI1500_RW_PORT_B_SPECIFICATION); /* Selects the mode specification mask */ /* register of port B */ @@ -416,14 +418,8 @@ static int apci1500_di_config(struct comedi_device *dev, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the mode specification mask */ - /* register of port 2 */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, + APCI1500_RW_PORT_B_SPECIFICATION); /* Selects the mode specification mask */ /* register of port 2 */ outb(APCI1500_RW_PORT_B_SPECIFICATION, @@ -500,12 +496,8 @@ static int apci1500_di_write(struct comedi_device *dev, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); i_Event1InterruptStatus = 1; - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, + APCI1500_RW_PORT_A_SPECIFICATION); /* Selects the master interrupt control register */ outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); @@ -1068,17 +1060,8 @@ static int apci1500_timer_config(struct comedi_device *dev, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the master configuration register */ - - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Reads the register */ - - i_MasterConfiguration = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + i_MasterConfiguration = z8536_read(dev, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); /* Enables timer/counter 1 and triggers timer/counter 1 */ @@ -1228,17 +1211,8 @@ static int apci1500_timer_config(struct comedi_device *dev, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the master configuration register */ - - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Reads the register */ - - i_MasterConfiguration = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + i_MasterConfiguration = z8536_read(dev, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); /* Enables timer/counter 2 and triggers timer/counter 2 */ @@ -1382,17 +1356,8 @@ static int apci1500_timer_config(struct comedi_device *dev, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the master configuration register */ - - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Reads the register */ - - i_MasterConfiguration = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + i_MasterConfiguration = z8536_read(dev, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); /* Enables watchdog/counter 3 and triggers watchdog/counter 3 */ @@ -1756,21 +1721,12 @@ static int apci1500_timer_bits(struct comedi_device *dev, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the counter register (high) */ - outb(APCI1500_R_CPT_TMR1_VALUE_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + data[0] = z8536_read(dev, + APCI1500_R_CPT_TMR1_VALUE_HIGH); data[0] = data[0] << 8; data[0] = data[0] & 0xff00; - outb(APCI1500_R_CPT_TMR1_VALUE_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - data[0] | inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + data[0] |= z8536_read(dev, + APCI1500_R_CPT_TMR1_VALUE_LOW); } else { dev_warn(dev->class_dev, "Timer/Counter1 not configured\n"); @@ -1798,21 +1754,12 @@ static int apci1500_timer_bits(struct comedi_device *dev, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the counter register (high) */ - outb(APCI1500_R_CPT_TMR2_VALUE_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + data[0] = z8536_read(dev, + APCI1500_R_CPT_TMR2_VALUE_HIGH); data[0] = data[0] << 8; data[0] = data[0] & 0xff00; - outb(APCI1500_R_CPT_TMR2_VALUE_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - data[0] | inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + data[0] |= z8536_read(dev, + APCI1500_R_CPT_TMR2_VALUE_LOW); } else { dev_warn(dev->class_dev, "Timer/Counter2 not configured\n"); @@ -1840,21 +1787,12 @@ static int apci1500_timer_bits(struct comedi_device *dev, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the counter register (high) */ - outb(APCI1500_R_CPT_TMR3_VALUE_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + data[0] = z8536_read(dev, + APCI1500_R_CPT_TMR3_VALUE_HIGH); data[0] = data[0] << 8; data[0] = data[0] & 0xff00; - outb(APCI1500_R_CPT_TMR3_VALUE_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - data[0] = - data[0] | inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + data[0] |= z8536_read(dev, + APCI1500_R_CPT_TMR3_VALUE_LOW); } else { dev_warn(dev->class_dev, "WatchdogCounter3 not configured\n"); @@ -1914,10 +1852,7 @@ static int apci1500_do_bits(struct comedi_device *dev, } } - /* Selects the mode specification register of port B */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, APCI1500_RW_PORT_B_SPECIFICATION); outb(APCI1500_RW_PORT_B_SPECIFICATION, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Writes the new configuration (APCI1500_OR) */ @@ -1942,20 +1877,14 @@ static int apci1500_do_bits(struct comedi_device *dev, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of port A */ i_RegValue = (i_RegValue & 0x0F) | 0x20; outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of port B */ @@ -1963,10 +1892,7 @@ static int apci1500_do_bits(struct comedi_device *dev, i_RegValue = (i_RegValue & 0x0F) | 0x20; outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS); outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of timer 1 */ @@ -1974,10 +1900,7 @@ static int apci1500_do_bits(struct comedi_device *dev, i_RegValue = (i_RegValue & 0x0F) | 0x20; outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS); outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of timer 2 */ @@ -1985,10 +1908,7 @@ static int apci1500_do_bits(struct comedi_device *dev, i_RegValue = (i_RegValue & 0x0F) | 0x20; outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS); outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of timer 3 */ @@ -2030,11 +1950,8 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) /* Disable all Interrupt */ /* Selects the master interrupt control register */ /* Disables the main interrupt on the board */ - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, + APCI1500_RW_PORT_A_COMMAND_AND_STATUS); if ((i_RegValue & 0x60) == 0x60) { /* Selects the command and status register of port A */ outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, @@ -2047,20 +1964,11 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) APCI1500_Z8536_CONTROL_REGISTER); i_InterruptMask = i_InterruptMask | 1; if (i_Logic == APCI1500_OR_PRIORITY) { - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, + APCI1500_RW_PORT_A_SPECIFICATION); - /* Selects the interrupt vector register of port A */ - outb(APCI1500_RW_PORT_A_INTERRUPT_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, + APCI1500_RW_PORT_A_INTERRUPT_CONTROL); i_InputChannel = 1 + (i_RegValue >> 1); @@ -2069,11 +1977,8 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) } } - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, + APCI1500_RW_PORT_B_COMMAND_AND_STATUS); if ((i_RegValue & 0x60) == 0x60) { /* Selects the command and status register of port B */ outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, @@ -2111,11 +2016,7 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) } } - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS); if ((i_RegValue & 0x60) == 0x60) { /* Selects the command and status register of timer 1 */ outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, @@ -2128,11 +2029,8 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) APCI1500_Z8536_CONTROL_REGISTER); i_InterruptMask = i_InterruptMask | 4; } - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + + i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS); if ((i_RegValue & 0x60) == 0x60) { /* Selects the command and status register of timer 2 */ outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, @@ -2146,11 +2044,7 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) i_InterruptMask = i_InterruptMask | 8; } - /* Selects the command and status register of timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS); if ((i_RegValue & 0x60) == 0x60) { /* Selects the command and status register of timer 3 */ outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, -- cgit v0.10.2 From 8dbaadb93117c8aec77c5e97fb06c125c1e345cc Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 3 Dec 2014 11:25:33 -0700 Subject: staging: comedi: hwdrv_apci1500: introduce z8536_write() The Z8536 CIO registers are indirectly written by writing the register offset to the control register then writing the value to the control register. Introduce a helper function to write the Z8536 CIO registers. The registers are written from "normal" code and in the interrupt handler, spinlock the sequence to protect the indirect register access. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 594f132..248fae5 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -143,6 +143,18 @@ static unsigned int z8536_read(struct comedi_device *dev, unsigned int reg) return val; } +static void z8536_write(struct comedi_device *dev, + unsigned int val, unsigned int reg) +{ + struct apci1500_private *devpriv = dev->private; + unsigned long flags; + + spin_lock_irqsave(&dev->spinlock, flags); + outb(reg, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(val, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + spin_unlock_irqrestore(&dev->spinlock, flags); +} + /* * An event can be generated for each port. The first event is related to the * first 8 channels (port 1) and the second to the following 6 channels (port 2) @@ -172,17 +184,13 @@ static int apci1500_di_config(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct apci1500_private *devpriv = dev->private; int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0; int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0; int i_PatternTransitionCount = 0, i_RegValue; int i; - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Disables the main interrupt on the board */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Disables the main interrupt on the board */ + z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); if (data[0] == 1) { i_MaxChannel = 8; @@ -292,67 +300,29 @@ static int apci1500_di_config(struct comedi_device *dev, } } - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); /* Disable Port A */ - outb(0xF0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the polarity register of port 1 */ - outb(APCI1500_RW_PORT_A_PATTERN_POLARITY, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternPolarity, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the pattern mask register of */ - /* port 1 */ - outb(APCI1500_RW_PORT_A_PATTERN_MASK, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternMask, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern transition register */ - /* of port 1 */ - outb(APCI1500_RW_PORT_A_PATTERN_TRANSITION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternTransition, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - i_RegValue = z8536_read(dev, - APCI1500_RW_PORT_A_SPECIFICATION); + z8536_write(dev, 0xf0, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - /* Selects the mode specification mask */ - /* register of port 1 */ - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_PatternPolarity, + APCI1500_RW_PORT_A_PATTERN_POLARITY); + z8536_write(dev, i_PatternMask, + APCI1500_RW_PORT_A_PATTERN_MASK); + z8536_write(dev, i_PatternTransition, + APCI1500_RW_PORT_A_PATTERN_TRANSITION); /* Port A new mode */ - + i_RegValue = z8536_read(dev, + APCI1500_RW_PORT_A_SPECIFICATION); i_RegValue = (i_RegValue & 0xF9) | data[1] | 0x9; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, + APCI1500_RW_PORT_A_SPECIFICATION); i_Event1Status = 1; - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); /* Enable Port A */ - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - + z8536_write(dev, 0xf4, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); } else { dev_warn(dev->class_dev, "The choice for interrupt logic does not exist\n"); @@ -366,81 +336,39 @@ static int apci1500_di_config(struct comedi_device *dev, /* Test the event logic */ if (data[1] == APCI1500_OR) { - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); /* Disable Port B */ - outb(0x74, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x74, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); + i_RegValue = z8536_read(dev, APCI1500_RW_PORT_B_SPECIFICATION); - - /* Selects the mode specification mask */ - /* register of port B */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); i_RegValue = i_RegValue & 0xF9; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, + APCI1500_RW_PORT_B_SPECIFICATION); /* Selects error channels 1 and 2 */ - i_PatternMask = (i_PatternMask | 0xC0); i_PatternPolarity = (i_PatternPolarity | 0xC0); i_PatternTransition = (i_PatternTransition | 0xC0); - /* Selects the polarity register of port 2 */ - outb(APCI1500_RW_PORT_B_PATTERN_POLARITY, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternPolarity, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern transition register */ - /* of port 2 */ - outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternTransition, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern Mask register */ - /* of port 2 */ - - outb(APCI1500_RW_PORT_B_PATTERN_MASK, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_PatternMask, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_PatternPolarity, + APCI1500_RW_PORT_B_PATTERN_POLARITY); + z8536_write(dev, i_PatternTransition, + APCI1500_RW_PORT_B_PATTERN_TRANSITION); + z8536_write(dev, i_PatternMask, + APCI1500_RW_PORT_B_PATTERN_MASK); i_RegValue = z8536_read(dev, APCI1500_RW_PORT_B_SPECIFICATION); - /* Selects the mode specification mask */ - /* register of port 2 */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); i_RegValue = (i_RegValue & 0xF9) | 4; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, + APCI1500_RW_PORT_B_SPECIFICATION); i_Event2Status = 1; - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); /* Enable Port B */ - - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xf4, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); } else { dev_warn(dev->class_dev, "The choice for interrupt logic does not exist\n"); @@ -462,7 +390,6 @@ static int apci1500_di_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct apci1500_private *devpriv = dev->private; int i_Event1InterruptStatus = 0, i_Event2InterruptStatus = 0, i_RegValue; @@ -476,36 +403,24 @@ static int apci1500_di_write(struct comedi_device *dev, if (data[1] == 1) { /* Test if event initialised */ if (i_Event1Status == 1) { - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Disable Port A */ - outb(0xF0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of */ - /* port 1 */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xf0, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); /* Allows the pattern interrupt */ - outb(0xC0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xc0, + APCI1500_RW_PORT_A_COMMAND_AND_STATUS); /* Enable Port A */ - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xf4, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); + i_Event1InterruptStatus = 1; + i_RegValue = z8536_read(dev, APCI1500_RW_PORT_A_SPECIFICATION); - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Authorizes the main interrupt on the board */ - outb(0xD0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - + z8536_write(dev, 0xd0, + APCI1500_RW_MASTER_INTERRUPT_CONTROL); } else { dev_warn(dev->class_dev, "Event 1 not initialised\n"); @@ -515,32 +430,20 @@ static int apci1500_di_write(struct comedi_device *dev, if (data[1] == 2) { if (i_Event2Status == 1) { - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Disable Port B */ - outb(0x74, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of */ - /* port 2 */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x74, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); /* Allows the pattern interrupt */ - outb(0xC0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xc0, + APCI1500_RW_PORT_B_COMMAND_AND_STATUS); /* Enable Port B */ - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xf4, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Authorizes the main interrupt on the board */ - outb(0xD0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xd0, + APCI1500_RW_MASTER_INTERRUPT_CONTROL); + i_Event2InterruptStatus = 1; } else { dev_warn(dev->class_dev, @@ -565,25 +468,16 @@ static int apci1500_di_write(struct comedi_device *dev, if (data[1] == 1) { /* Test if event initialised */ if (i_Event1Status == 1) { - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Disable Port A */ - outb(0xF0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of */ - /* port 1 */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Inhibits the pattern interrupt */ - outb(0xE0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xf0, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); + /* Inhibits the pattern interrupt */ + z8536_write(dev, 0xe0, + APCI1500_RW_PORT_A_COMMAND_AND_STATUS); /* Enable Port A */ - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xf4, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); + i_Event1InterruptStatus = 0; } else { dev_warn(dev->class_dev, @@ -594,25 +488,16 @@ static int apci1500_di_write(struct comedi_device *dev, if (data[1] == 2) { /* Test if event initialised */ if (i_Event2Status == 1) { - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Disable Port B */ - outb(0x74, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of */ - /* port 2 */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x74, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); /* Inhibits the pattern interrupt */ - outb(0xE0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the APCI1500_RW_MASTER_CONFIGURATION_CONTROL register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xe0, + APCI1500_RW_PORT_B_COMMAND_AND_STATUS); /* Enable Port B */ - outb(0xF4, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xf4, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); + i_Event2InterruptStatus = 0; } else { @@ -656,123 +541,55 @@ static int apci1500_di_read(struct comedi_device *dev, outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the master configuration control register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the mode specification register of port A */ - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xf4, APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - /* Selects the data path polarity register of port A */ - outb(APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x10, APCI1500_RW_PORT_A_SPECIFICATION); /* High level of port A means 1 */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the data direction register of port A */ - outb(APCI1500_RW_PORT_A_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY); /* All bits used as inputs */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_DIRECTION); /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of port A: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the handshake specification register of port A */ - outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x20, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); + /* Deactivates the interrupt management of port A */ + z8536_write(dev, 0xe0, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); /* Deletes the register */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION); - /* Selects the mode specification register of port B */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data path polarity register of port B */ - outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x10, APCI1500_RW_PORT_B_SPECIFICATION); /* A high level of port B means 1 */ - outb(0x7F, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data direction register of port B */ - outb(APCI1500_RW_PORT_B_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x7f, APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY); /* All bits used as inputs */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xff, APCI1500_RW_PORT_B_DATA_DIRECTION); /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of port B: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the handshake specification register of port B */ - outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x20, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); + /* Deactivates the interrupt management of port B */ + z8536_write(dev, 0xe0, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); /* Deletes the register */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION); - /* Selects the data path polarity register of port C */ - outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* High level of port C means 1 */ - outb(0x9, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data direction register of port C */ - outb(APCI1500_RW_PORT_C_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x09, APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY); /* All bits used as inputs except channel 1 */ - outb(0x0E, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the special IO register of port C */ - outb(APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x0e, APCI1500_RW_PORT_C_DATA_DIRECTION); /* Deletes it */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL); + /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of timer 1 */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR1_CMD_STATUS); + /* Deactivates the interrupt management of timer 1 */ + z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR1_CMD_STATUS); /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates Timer 2 interrupt management: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR2_CMD_STATUS); + /* Deactivates Timer 2 interrupt management */ + z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR2_CMD_STATUS); /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of Timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates interrupt management of timer 3: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR3_CMD_STATUS); + /* Deactivates interrupt management of timer 3 */ + z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR3_CMD_STATUS); + /* Deletes all interrupts */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); + return insn->n; } @@ -1023,82 +840,34 @@ static int apci1500_timer_config(struct comedi_device *dev, /* Test the reload value */ if ((data[3] >= 0) && (data[3] <= 65535)) { - if (data[7] == APCI1500_ENABLE - || data[7] == APCI1500_DISABLE) { - - /* Selects the mode register of timer/counter 1 */ - outb(APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + if (data[7] == APCI1500_ENABLE || + data[7] == APCI1500_DISABLE) { /* Writes the new mode */ - outb(i_TimerCounterMode, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of timer/counter 1 */ - - outb(APCI1500_RW_CPT_TMR1_TIME_CST_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the low value */ - - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of timer/counter 1 */ - - outb(APCI1500_RW_CPT_TMR1_TIME_CST_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_TimerCounterMode, + APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION); + /* Writes the low value */ + z8536_write(dev, data[3], + APCI1500_RW_CPT_TMR1_TIME_CST_LOW); /* Writes the high value */ - data[3] = data[3] >> 8; - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, data[3], + APCI1500_RW_CPT_TMR1_TIME_CST_HIGH); + /* Enables timer/counter 1 and triggers timer/counter 1 */ i_MasterConfiguration = z8536_read(dev, APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - /* Enables timer/counter 1 and triggers timer/counter 1 */ - i_MasterConfiguration = i_MasterConfiguration | 0x40; - - /* Selects the master configuration register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the new configuration */ - outb(i_MasterConfiguration, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the commands register of */ - /* timer/counter 1 */ - - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_MasterConfiguration, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); /* Disable timer/counter 1 */ - - outb(0x0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the commands register of */ - /* timer/counter 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - + z8536_write(dev, 0x00, + APCI1500_RW_CPT_TMR1_CMD_STATUS); /* Trigger timer/counter 1 */ - outb(0x2, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x02, + APCI1500_RW_CPT_TMR1_CMD_STATUS); } else { dev_warn(dev->class_dev, "Error in selection of interrupt enable or disable\n"); @@ -1174,82 +943,34 @@ static int apci1500_timer_config(struct comedi_device *dev, /* Test the reload value */ if ((data[3] >= 0) && (data[3] <= 65535)) { - if (data[7] == APCI1500_ENABLE - || data[7] == APCI1500_DISABLE) { - - /* Selects the mode register of timer/counter 2 */ - outb(APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + if (data[7] == APCI1500_ENABLE || + data[7] == APCI1500_DISABLE) { /* Writes the new mode */ - outb(i_TimerCounterMode, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of timer/counter 2 */ - - outb(APCI1500_RW_CPT_TMR2_TIME_CST_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the low value */ - - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of timer/counter 2 */ - - outb(APCI1500_RW_CPT_TMR2_TIME_CST_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the high value */ + z8536_write(dev, i_TimerCounterMode, + APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION); + /* Writes the low value */ + z8536_write(dev, data[3], + APCI1500_RW_CPT_TMR2_TIME_CST_LOW); + /* Writes the high value */ data[3] = data[3] >> 8; - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, data[3], + APCI1500_RW_CPT_TMR2_TIME_CST_HIGH); + /* Enables timer/counter 2 and triggers timer/counter 2 */ i_MasterConfiguration = z8536_read(dev, APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - /* Enables timer/counter 2 and triggers timer/counter 2 */ - i_MasterConfiguration = i_MasterConfiguration | 0x20; - - /* Selects the master configuration register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the new configuration */ - outb(i_MasterConfiguration, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the commands register of */ - /* timer/counter 2 */ - - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_MasterConfiguration, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); /* Disable timer/counter 2 */ - - outb(0x0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the commands register of */ - /* timer/counter 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - + z8536_write(dev, 0x00, + APCI1500_RW_CPT_TMR2_CMD_STATUS); /* Trigger timer/counter 1 */ - outb(0x2, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x02, + APCI1500_RW_CPT_TMR2_CMD_STATUS); } else { dev_warn(dev->class_dev, "Error in selection of interrupt enable or disable\n"); @@ -1319,85 +1040,36 @@ static int apci1500_timer_config(struct comedi_device *dev, /* Test the reload value */ if ((data[3] >= 0) && (data[3] <= 65535)) { - if (data[7] == APCI1500_ENABLE - || data[7] == APCI1500_DISABLE) { - - /* Selects the mode register of watchdog/counter 3 */ - outb(APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + if (data[7] == APCI1500_ENABLE || + data[7] == APCI1500_DISABLE) { /* Writes the new mode */ - outb(i_TimerCounterMode, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of watchdog/counter 3 */ - - outb(APCI1500_RW_CPT_TMR3_TIME_CST_LOW, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_TimerCounterMode, + APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION); /* Writes the low value */ - - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the constant register of watchdog/counter 3 */ - - outb(APCI1500_RW_CPT_TMR3_TIME_CST_HIGH, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - + z8536_write(dev, data[3], + APCI1500_RW_CPT_TMR3_TIME_CST_LOW); /* Writes the high value */ - data[3] = data[3] >> 8; - outb(data[3], - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, data[3], + APCI1500_RW_CPT_TMR3_TIME_CST_HIGH); + /* Enables watchdog/counter 3 and triggers watchdog/counter 3 */ i_MasterConfiguration = z8536_read(dev, APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - /* Enables watchdog/counter 3 and triggers watchdog/counter 3 */ - i_MasterConfiguration = i_MasterConfiguration | 0x10; - - /* Selects the master configuration register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Writes the new configuration */ - outb(i_MasterConfiguration, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_MasterConfiguration, + APCI1500_RW_MASTER_CONFIGURATION_CONTROL); /* Test if COUNTER */ if (data[2] == APCI1500_COUNTER) { - - /* Selects the command register of */ - /* watchdog/counter 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); /* Disable the watchdog/counter 3 and starts it */ - outb(0x0, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the command register of */ - /* watchdog/counter 3 */ - - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, + APCI1500_RW_CPT_TMR3_CMD_STATUS); /* Trigger the watchdog/counter 3 and starts it */ - outb(0x2, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - + z8536_write(dev, 0x02, + APCI1500_RW_CPT_TMR3_CMD_STATUS); } } else { @@ -1436,7 +1108,6 @@ static int apci1500_timer_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct apci1500_private *devpriv = dev->private; int i_CommandAndStatusValue; switch (data[0]) { @@ -1451,13 +1122,8 @@ static int apci1500_timer_write(struct comedi_device *dev, /* Starts timer/counter 1 */ i_TimerCounter1Enabled = 1; - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_CommandAndStatusValue, + APCI1500_RW_CPT_TMR1_CMD_STATUS); } else { dev_warn(dev->class_dev, "Counter/Timer1 not configured\n"); @@ -1466,16 +1132,8 @@ static int apci1500_timer_write(struct comedi_device *dev, break; case STOP: - /* Stop timer/counter 1 */ - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(0x00, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR1_CMD_STATUS); i_TimerCounter1Enabled = 0; break; @@ -1490,14 +1148,8 @@ static int apci1500_timer_write(struct comedi_device *dev, i_CommandAndStatusValue = 0x2; } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_CommandAndStatusValue, + APCI1500_RW_CPT_TMR1_CMD_STATUS); } else { dev_warn(dev->class_dev, "Counter/Timer1 not configured\n"); @@ -1523,13 +1175,8 @@ static int apci1500_timer_write(struct comedi_device *dev, /* Starts timer/counter 2 */ i_TimerCounter2Enabled = 1; - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_CommandAndStatusValue, + APCI1500_RW_CPT_TMR2_CMD_STATUS); } else { dev_warn(dev->class_dev, "Counter/Timer2 not configured\n"); @@ -1538,16 +1185,8 @@ static int apci1500_timer_write(struct comedi_device *dev, break; case STOP: - /* Stop timer/counter 2 */ - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(0x00, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR2_CMD_STATUS); i_TimerCounter2Enabled = 0; break; case TRIGGER: @@ -1561,14 +1200,8 @@ static int apci1500_timer_write(struct comedi_device *dev, i_CommandAndStatusValue = 0x2; } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_CommandAndStatusValue, + APCI1500_RW_CPT_TMR2_CMD_STATUS); } else { dev_warn(dev->class_dev, "Counter/Timer2 not configured\n"); @@ -1593,14 +1226,8 @@ static int apci1500_timer_write(struct comedi_device *dev, /* Starts Watchdog/counter 3 */ i_WatchdogCounter3Enabled = 1; - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - + z8536_write(dev, i_CommandAndStatusValue, + APCI1500_RW_CPT_TMR3_CMD_STATUS); } else { dev_warn(dev->class_dev, "Watchdog/Counter3 not configured\n"); @@ -1609,16 +1236,8 @@ static int apci1500_timer_write(struct comedi_device *dev, break; case STOP: - /* Stop Watchdog/counter 3 */ - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(0x00, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR3_CMD_STATUS); i_WatchdogCounter3Enabled = 0; break; @@ -1635,14 +1254,8 @@ static int apci1500_timer_write(struct comedi_device *dev, i_CommandAndStatusValue = 0x2; } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_CommandAndStatusValue, + APCI1500_RW_CPT_TMR3_CMD_STATUS); } else { dev_warn(dev->class_dev, "Counter3 not configured\n"); @@ -1652,14 +1265,8 @@ static int apci1500_timer_write(struct comedi_device *dev, case 1: /* triggering Watchdog 3 */ if (i_WatchdogCounter3Init == 1) { - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(0x6, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x06, + APCI1500_RW_CPT_TMR3_CMD_STATUS); } else { dev_warn(dev->class_dev, "Watchdog 3 not configured\n"); @@ -1696,7 +1303,6 @@ static int apci1500_timer_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct apci1500_private *devpriv = dev->private; int i_CommandAndStatusValue; switch (data[0]) { @@ -1712,14 +1318,8 @@ static int apci1500_timer_bits(struct comedi_device *dev, i_CommandAndStatusValue = 0x8; } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_CommandAndStatusValue, + APCI1500_RW_CPT_TMR1_CMD_STATUS); data[0] = z8536_read(dev, APCI1500_R_CPT_TMR1_VALUE_HIGH); @@ -1745,14 +1345,8 @@ static int apci1500_timer_bits(struct comedi_device *dev, i_CommandAndStatusValue = 0x8; } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_CommandAndStatusValue, + APCI1500_RW_CPT_TMR2_CMD_STATUS); data[0] = z8536_read(dev, APCI1500_R_CPT_TMR2_VALUE_HIGH); @@ -1778,14 +1372,8 @@ static int apci1500_timer_bits(struct comedi_device *dev, i_CommandAndStatusValue = 0x8; } - - /* Selects the commands and status register */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); - outb(i_CommandAndStatusValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_CommandAndStatusValue, + APCI1500_RW_CPT_TMR3_CMD_STATUS); data[0] = z8536_read(dev, APCI1500_R_CPT_TMR3_VALUE_HIGH); @@ -1852,75 +1440,45 @@ static int apci1500_do_bits(struct comedi_device *dev, } } - i_RegValue = z8536_read(dev, APCI1500_RW_PORT_B_SPECIFICATION); - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Writes the new configuration (APCI1500_OR) */ + i_RegValue = z8536_read(dev, APCI1500_RW_PORT_B_SPECIFICATION); i_RegValue = (i_RegValue & 0xF9) | APCI1500_OR; + z8536_write(dev, i_RegValue, APCI1500_RW_PORT_B_SPECIFICATION); - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Authorises the interrupt on the board */ - outb(0xC0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern polarity register of port B */ - outb(APCI1500_RW_PORT_B_PATTERN_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern transition register of port B */ - outb(APCI1500_RW_PORT_B_PATTERN_TRANSITION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the pattern mask register of port B */ - outb(APCI1500_RW_PORT_B_PATTERN_MASK, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(i_Constant, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xc0, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - i_RegValue = z8536_read(dev, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of port A */ + z8536_write(dev, i_Constant, APCI1500_RW_PORT_B_PATTERN_POLARITY); + z8536_write(dev, i_Constant, APCI1500_RW_PORT_B_PATTERN_TRANSITION); + z8536_write(dev, i_Constant, APCI1500_RW_PORT_B_PATTERN_MASK); + /* Deletes the interrupt of port A */ + i_RegValue = z8536_read(dev, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_RegValue = z8536_read(dev, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deletes the interrupt of port B */ + z8536_write(dev, i_RegValue, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); + /* Deletes the interrupt of port B */ + i_RegValue = z8536_read(dev, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS); - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of timer 1 */ - + i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS); i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, APCI1500_RW_CPT_TMR1_CMD_STATUS); - i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS); - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of timer 2 */ - + i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS); i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, APCI1500_RW_CPT_TMR2_CMD_STATUS); - i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS); - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of timer 3 */ - + i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS); i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, APCI1500_RW_CPT_TMR3_CMD_STATUS); - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Authorizes the main interrupt on the board */ - outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xd0, APCI1500_RW_MASTER_INTERRUPT_CONTROL); /* Enables the PCI interrupt */ outl(0x3000, devpriv->i_IobaseAmcc + 0x38); @@ -1953,15 +1511,10 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) i_RegValue = z8536_read(dev, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); if ((i_RegValue & 0x60) == 0x60) { - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of port A */ i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, + APCI1500_RW_PORT_A_COMMAND_AND_STATUS); i_InterruptMask = i_InterruptMask | 1; if (i_Logic == APCI1500_OR_PRIORITY) { i_RegValue = z8536_read(dev, @@ -1980,15 +1533,10 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) i_RegValue = z8536_read(dev, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); if ((i_RegValue & 0x60) == 0x60) { - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of port B */ i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, + APCI1500_RW_PORT_B_COMMAND_AND_STATUS); /* Reads port B */ i_RegValue = inb((unsigned int) devpriv->iobase + @@ -2018,43 +1566,28 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS); if ((i_RegValue & 0x60) == 0x60) { - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of timer 1 */ i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, + APCI1500_RW_CPT_TMR1_CMD_STATUS); i_InterruptMask = i_InterruptMask | 4; } i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS); if ((i_RegValue & 0x60) == 0x60) { - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of timer 2 */ i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, + APCI1500_RW_CPT_TMR2_CMD_STATUS); i_InterruptMask = i_InterruptMask | 8; } i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS); if ((i_RegValue & 0x60) == 0x60) { - /* Selects the command and status register of timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); /* Deletes the interrupt of timer 3 */ i_RegValue = (i_RegValue & 0x0F) | 0x20; - outb(i_RegValue, - devpriv->iobase + - APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, i_RegValue, + APCI1500_RW_CPT_TMR3_CMD_STATUS); if (i_CounterLogic == APCI1500_COUNTER) i_InterruptMask = i_InterruptMask | 0x10; else @@ -2062,13 +1595,9 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) } send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ - /* Enable all Interrupts */ - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* Authorizes the main interrupt on the board */ - outb(0xD0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xd0, APCI1500_RW_MASTER_INTERRUPT_CONTROL); } else { dev_warn(dev->class_dev, "Interrupt from unknown source\n"); @@ -2105,155 +1634,67 @@ static int apci1500_reset(struct comedi_device *dev) outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the master configuration control register */ - outb(APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0xF4, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xf4, APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - /* Selects the mode specification register of port A */ - outb(APCI1500_RW_PORT_A_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the data path polarity register of port A */ - outb(APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x10, APCI1500_RW_PORT_A_SPECIFICATION); /* High level of port A means 1 */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - /* Selects the data direction register of port A */ - outb(APCI1500_RW_PORT_A_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY); /* All bits used as inputs */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_DIRECTION); /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of port A: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the handshake specification register of port A */ - outb(APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x20, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); + /* Deactivates the interrupt management of port A */ + z8536_write(dev, 0xe0, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); /* Deletes the register */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION); - /* Selects the mode specification register of port B */ - outb(APCI1500_RW_PORT_B_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0x10, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data path polarity register of port B */ - outb(APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x10, APCI1500_RW_PORT_B_SPECIFICATION); /* A high level of port B means 1 */ - outb(0x7F, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data direction register of port B */ - outb(APCI1500_RW_PORT_B_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x7f, APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY); /* All bits used as inputs */ - outb(0xFF, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0xff, APCI1500_RW_PORT_B_DATA_DIRECTION); /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of port B: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the handshake specification register of port B */ - outb(APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x20, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); + /* Deactivates the interrupt management of port B */ + z8536_write(dev, 0xe0, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); /* Deletes the register */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION); - /* Selects the data path polarity register of port C */ - outb(APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); /* High level of port C means 1 */ - outb(0x9, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the data direction register of port C */ - outb(APCI1500_RW_PORT_C_DATA_DIRECTION, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x09, APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY); /* All bits used as inputs except channel 1 */ - outb(0x0E, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the special IO register of port C */ - outb(APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x0e, APCI1500_RW_PORT_C_DATA_DIRECTION); /* Deletes it */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL); + /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates the interrupt management of timer 1 */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR1_CMD_STATUS); + /* Deactivates the interrupt management of timer 1 */ + z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR1_CMD_STATUS); + /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates Timer 2 interrupt management: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR2_CMD_STATUS); + /* Deactivates Timer 2 interrupt management */ + z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR2_CMD_STATUS); + /* Deletes IP and IUS */ - outb(0x20, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of Timer 3 */ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates interrupt management of timer 3: */ - outb(0xE0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR3_CMD_STATUS); + /* Deactivates interrupt management of timer 3 */ + z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR3_CMD_STATUS); + /* Deletes all interrupts */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); + /* reset all the digital outputs */ outw(0x0, devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP); - /* Disable the board interrupt */ - /* Selects the master interrupt control register */ - outb(APCI1500_RW_MASTER_INTERRUPT_CONTROL, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates all interrupts */ - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port A */ - outb(APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates all interrupts */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of port B */ - outb(APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates all interrupts */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 1 */ - outb(APCI1500_RW_CPT_TMR1_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates all interrupts */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 2 */ - outb(APCI1500_RW_CPT_TMR2_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Deactivates all interrupts */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - /* Selects the command and status register of timer 3*/ - outb(APCI1500_RW_CPT_TMR3_CMD_STATUS, - devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + /* Deactivates all interrupts */ - outb(0x00, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); + z8536_write(dev, 0x00, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); + z8536_write(dev, 0x00, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); + z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR1_CMD_STATUS); + z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR2_CMD_STATUS); + z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR3_CMD_STATUS); + return 0; } -- cgit v0.10.2 From 34373cd08810fcf7b55a89866081e09e91e43ace Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 3 Dec 2014 11:25:34 -0700 Subject: staging: comedi: hwdrv_apci1500: introduce z8536_reset() Introduce a helper function to reset the Z8536 CIO device. Spinlock the initial reset of the Z8536 chip that puts it in State 0. The z8536_{read,write} operations already do the spinlock to protect the indirect register access. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 248fae5..26b46c5 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -155,6 +155,76 @@ static void z8536_write(struct comedi_device *dev, spin_unlock_irqrestore(&dev->spinlock, flags); } +static void z8536_reset(struct comedi_device *dev) +{ + struct apci1500_private *devpriv = dev->private; + unsigned long flags; + + /* + * Even if the state of the Z8536 is not known, the following + * sequence will reset it and put it in State 0. + */ + spin_lock_irqsave(&dev->spinlock, flags); + inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + spin_unlock_irqrestore(&dev->spinlock, flags); + + z8536_write(dev, 0xf4, APCI1500_RW_MASTER_CONFIGURATION_CONTROL); + + z8536_write(dev, 0x10, APCI1500_RW_PORT_A_SPECIFICATION); + /* High level of port A means 1 */ + z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY); + /* All bits used as inputs */ + z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_DIRECTION); + /* Deletes IP and IUS */ + z8536_write(dev, 0x20, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); + /* Deactivates the interrupt management of port A */ + z8536_write(dev, 0xe0, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); + /* Deletes the register */ + z8536_write(dev, 0x00, APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION); + + z8536_write(dev, 0x10, APCI1500_RW_PORT_B_SPECIFICATION); + /* A high level of port B means 1 */ + z8536_write(dev, 0x7f, APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY); + /* All bits used as inputs */ + z8536_write(dev, 0xff, APCI1500_RW_PORT_B_DATA_DIRECTION); + /* Deletes IP and IUS */ + z8536_write(dev, 0x20, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); + /* Deactivates the interrupt management of port B */ + z8536_write(dev, 0xe0, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); + /* Deletes the register */ + z8536_write(dev, 0x00, APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION); + + /* High level of port C means 1 */ + z8536_write(dev, 0x09, APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY); + /* All bits used as inputs except channel 1 */ + z8536_write(dev, 0x0e, APCI1500_RW_PORT_C_DATA_DIRECTION); + /* Deletes it */ + z8536_write(dev, 0x00, APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL); + + /* Deletes IP and IUS */ + z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR1_CMD_STATUS); + /* Deactivates the interrupt management of timer 1 */ + z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR1_CMD_STATUS); + + /* Deletes IP and IUS */ + z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR2_CMD_STATUS); + /* Deactivates Timer 2 interrupt management */ + z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR2_CMD_STATUS); + + /* Deletes IP and IUS */ + z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR3_CMD_STATUS); + /* Deactivates interrupt management of timer 3 */ + z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR3_CMD_STATUS); + + /* Deletes all interrupts */ + z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); +} + /* * An event can be generated for each port. The first event is related to the * first 8 channels (port 1) and the second to the following 6 channels (port 2) @@ -530,65 +600,8 @@ static int apci1500_di_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct apci1500_private *devpriv = dev->private; - int i_DummyRead = 0; - /* Software reset */ - i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - z8536_write(dev, 0xf4, APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - z8536_write(dev, 0x10, APCI1500_RW_PORT_A_SPECIFICATION); - /* High level of port A means 1 */ - z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY); - /* All bits used as inputs */ - z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_DIRECTION); - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - /* Deactivates the interrupt management of port A */ - z8536_write(dev, 0xe0, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - /* Deletes the register */ - z8536_write(dev, 0x00, APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION); - - z8536_write(dev, 0x10, APCI1500_RW_PORT_B_SPECIFICATION); - /* A high level of port B means 1 */ - z8536_write(dev, 0x7f, APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY); - /* All bits used as inputs */ - z8536_write(dev, 0xff, APCI1500_RW_PORT_B_DATA_DIRECTION); - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - /* Deactivates the interrupt management of port B */ - z8536_write(dev, 0xe0, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - /* Deletes the register */ - z8536_write(dev, 0x00, APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION); - - /* High level of port C means 1 */ - z8536_write(dev, 0x09, APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY); - /* All bits used as inputs except channel 1 */ - z8536_write(dev, 0x0e, APCI1500_RW_PORT_C_DATA_DIRECTION); - /* Deletes it */ - z8536_write(dev, 0x00, APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL); - - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR1_CMD_STATUS); - /* Deactivates the interrupt management of timer 1 */ - z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR1_CMD_STATUS); - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR2_CMD_STATUS); - /* Deactivates Timer 2 interrupt management */ - z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR2_CMD_STATUS); - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR3_CMD_STATUS); - /* Deactivates interrupt management of timer 3 */ - z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR3_CMD_STATUS); - - /* Deletes all interrupts */ - z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); + z8536_reset(dev); return insn->n; } @@ -1610,7 +1623,6 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) static int apci1500_reset(struct comedi_device *dev) { struct apci1500_private *devpriv = dev->private; - int i_DummyRead = 0; i_TimerCounter1Init = 0; i_TimerCounter2Init = 0; @@ -1627,63 +1639,7 @@ static int apci1500_reset(struct comedi_device *dev) i_WatchdogCounter3Enabled = 0; /* Software reset */ - i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - i_DummyRead = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - - z8536_write(dev, 0xf4, APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - z8536_write(dev, 0x10, APCI1500_RW_PORT_A_SPECIFICATION); - /* High level of port A means 1 */ - z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY); - /* All bits used as inputs */ - z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_DIRECTION); - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - /* Deactivates the interrupt management of port A */ - z8536_write(dev, 0xe0, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - /* Deletes the register */ - z8536_write(dev, 0x00, APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION); - - z8536_write(dev, 0x10, APCI1500_RW_PORT_B_SPECIFICATION); - /* A high level of port B means 1 */ - z8536_write(dev, 0x7f, APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY); - /* All bits used as inputs */ - z8536_write(dev, 0xff, APCI1500_RW_PORT_B_DATA_DIRECTION); - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - /* Deactivates the interrupt management of port B */ - z8536_write(dev, 0xe0, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - /* Deletes the register */ - z8536_write(dev, 0x00, APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION); - - /* High level of port C means 1 */ - z8536_write(dev, 0x09, APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY); - /* All bits used as inputs except channel 1 */ - z8536_write(dev, 0x0e, APCI1500_RW_PORT_C_DATA_DIRECTION); - /* Deletes it */ - z8536_write(dev, 0x00, APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL); - - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR1_CMD_STATUS); - /* Deactivates the interrupt management of timer 1 */ - z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR1_CMD_STATUS); - - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR2_CMD_STATUS); - /* Deactivates Timer 2 interrupt management */ - z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR2_CMD_STATUS); - - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR3_CMD_STATUS); - /* Deactivates interrupt management of timer 3 */ - z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR3_CMD_STATUS); - - /* Deletes all interrupts */ - z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); + z8536_reset(dev); /* reset all the digital outputs */ outw(0x0, devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP); -- cgit v0.10.2 From ad84f9bc2b53c27111f40d14d226a7f7635faa30 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 3 Dec 2014 11:25:35 -0700 Subject: staging: comedi: addi_apci_1500: tidy up PCI Bar 1 register map For aesthetics, convert the enum for the PCI Bar 1 register map to defines and move them to the main driver source file. Rename the registers. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 26b46c5..d5d959c 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -51,16 +51,6 @@ #define TRIGGER 2 /* - * Zillog I/O enumeration - */ -enum { - APCI1500_Z8536_PORT_C, - APCI1500_Z8536_PORT_B, - APCI1500_Z8536_PORT_A, - APCI1500_Z8536_CONTROL_REGISTER -}; - -/* * Z8536 CIO Internal Address */ enum { @@ -136,8 +126,8 @@ static unsigned int z8536_read(struct comedi_device *dev, unsigned int reg) unsigned int val; spin_lock_irqsave(&dev->spinlock, flags); - outb(reg, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - val = inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(reg, devpriv->iobase + APCI1500_Z8536_CTRL_REG); + val = inb(devpriv->iobase + APCI1500_Z8536_CTRL_REG); spin_unlock_irqrestore(&dev->spinlock, flags); return val; @@ -150,8 +140,8 @@ static void z8536_write(struct comedi_device *dev, unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); - outb(reg, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(val, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + outb(reg, devpriv->iobase + APCI1500_Z8536_CTRL_REG); + outb(val, devpriv->iobase + APCI1500_Z8536_CTRL_REG); spin_unlock_irqrestore(&dev->spinlock, flags); } @@ -165,12 +155,12 @@ static void z8536_reset(struct comedi_device *dev) * sequence will reset it and put it in State 0. */ spin_lock_irqsave(&dev->spinlock, flags); - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - inb(devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(1, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); - outb(0, devpriv->iobase + APCI1500_Z8536_CONTROL_REGISTER); + inb(devpriv->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, devpriv->iobase + APCI1500_Z8536_CTRL_REG); + inb(devpriv->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, devpriv->iobase + APCI1500_Z8536_CTRL_REG); + outb(1, devpriv->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, devpriv->iobase + APCI1500_Z8536_CTRL_REG); spin_unlock_irqrestore(&dev->spinlock, flags); z8536_write(dev, 0xf4, APCI1500_RW_MASTER_CONFIGURATION_CONTROL); @@ -1551,9 +1541,8 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) z8536_write(dev, i_RegValue, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); /* Reads port B */ - i_RegValue = - inb((unsigned int) devpriv->iobase + - APCI1500_Z8536_PORT_B); + i_RegValue = inb(devpriv->iobase + + APCI1500_Z8536_PORTB_REG); i_RegValue = i_RegValue & 0xC0; /* Tests if this is an external error */ diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 30b132c..52df495 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -7,6 +7,14 @@ #include "comedi_fc.h" #include "amcc_s5933.h" +/* + * PCI Bar 1 Register map (devpriv->iobase) + */ +#define APCI1500_Z8536_PORTC_REG 0x00 +#define APCI1500_Z8536_PORTB_REG 0x01 +#define APCI1500_Z8536_PORTA_REG 0x02 +#define APCI1500_Z8536_CTRL_REG 0x03 + struct apci1500_private { int iobase; int i_IobaseAmcc; -- cgit v0.10.2 From c80a255e4a664be6a295280cd17be475c5105ad9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 3 Dec 2014 11:25:36 -0700 Subject: staging: comedi: addi_apci_1500: remove private data 'iobase' This member of the private data is the same as the comedi_device 'iobase'. Remove the private data member and use that instead. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index d5d959c..ea6d98f 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -121,13 +121,12 @@ static int i_TimerCounter1Enabled, i_TimerCounter2Enabled, static unsigned int z8536_read(struct comedi_device *dev, unsigned int reg) { - struct apci1500_private *devpriv = dev->private; unsigned long flags; unsigned int val; spin_lock_irqsave(&dev->spinlock, flags); - outb(reg, devpriv->iobase + APCI1500_Z8536_CTRL_REG); - val = inb(devpriv->iobase + APCI1500_Z8536_CTRL_REG); + outb(reg, dev->iobase + APCI1500_Z8536_CTRL_REG); + val = inb(dev->iobase + APCI1500_Z8536_CTRL_REG); spin_unlock_irqrestore(&dev->spinlock, flags); return val; @@ -136,18 +135,16 @@ static unsigned int z8536_read(struct comedi_device *dev, unsigned int reg) static void z8536_write(struct comedi_device *dev, unsigned int val, unsigned int reg) { - struct apci1500_private *devpriv = dev->private; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); - outb(reg, devpriv->iobase + APCI1500_Z8536_CTRL_REG); - outb(val, devpriv->iobase + APCI1500_Z8536_CTRL_REG); + outb(reg, dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(val, dev->iobase + APCI1500_Z8536_CTRL_REG); spin_unlock_irqrestore(&dev->spinlock, flags); } static void z8536_reset(struct comedi_device *dev) { - struct apci1500_private *devpriv = dev->private; unsigned long flags; /* @@ -155,12 +152,12 @@ static void z8536_reset(struct comedi_device *dev) * sequence will reset it and put it in State 0. */ spin_lock_irqsave(&dev->spinlock, flags); - inb(devpriv->iobase + APCI1500_Z8536_CTRL_REG); - outb(0, devpriv->iobase + APCI1500_Z8536_CTRL_REG); - inb(devpriv->iobase + APCI1500_Z8536_CTRL_REG); - outb(0, devpriv->iobase + APCI1500_Z8536_CTRL_REG); - outb(1, devpriv->iobase + APCI1500_Z8536_CTRL_REG); - outb(0, devpriv->iobase + APCI1500_Z8536_CTRL_REG); + inb(dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); + inb(dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(1, dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); spin_unlock_irqrestore(&dev->spinlock, flags); z8536_write(dev, 0xf4, APCI1500_RW_MASTER_CONFIGURATION_CONTROL); @@ -1541,7 +1538,7 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) z8536_write(dev, i_RegValue, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); /* Reads port B */ - i_RegValue = inb(devpriv->iobase + + i_RegValue = inb(dev->iobase + APCI1500_Z8536_PORTB_REG); i_RegValue = i_RegValue & 0xC0; diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 52df495..d8a6170 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -8,7 +8,7 @@ #include "amcc_s5933.h" /* - * PCI Bar 1 Register map (devpriv->iobase) + * PCI Bar 1 Register map (dev->iobase) */ #define APCI1500_Z8536_PORTC_REG 0x00 #define APCI1500_Z8536_PORTB_REG 0x01 @@ -16,7 +16,6 @@ #define APCI1500_Z8536_CTRL_REG 0x03 struct apci1500_private { - int iobase; int i_IobaseAmcc; int i_IobaseAddon; int i_IobaseReserved; @@ -43,7 +42,6 @@ static int apci1500_auto_attach(struct comedi_device *dev, return ret; dev->iobase = pci_resource_start(pcidev, 1); - devpriv->iobase = dev->iobase; devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0); devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2); devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3); -- cgit v0.10.2 From aa6d4eb21586d8117b19187411f307d4599cc1d9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 3 Dec 2014 11:25:37 -0700 Subject: staging: comedi: addi_apci_1500: remove private data 'i_IobaseReserved' This member of the private data is set but not used by the driver. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index d8a6170..4b2e3fb 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -18,7 +18,6 @@ struct apci1500_private { int i_IobaseAmcc; int i_IobaseAddon; - int i_IobaseReserved; unsigned char b_OutputMemoryStatus; struct task_struct *tsk_Current; }; @@ -44,7 +43,6 @@ static int apci1500_auto_attach(struct comedi_device *dev, dev->iobase = pci_resource_start(pcidev, 1); devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0); devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2); - devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3); if (pcidev->irq > 0) { ret = request_irq(pcidev->irq, apci1500_interrupt, IRQF_SHARED, -- cgit v0.10.2 From 784801d7dcc16dfd3c12ac993f0d5949cdb67dd9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 3 Dec 2014 11:25:38 -0700 Subject: staging: comedi: addi_apci_1500: use amcc_s5933.h defines PCI Bar 0 accesses the AMCC S5933 PCI controller used on this board. Use the defines from amcc_35933.h and remove the "magic" numbers. Rename the CamelCase private data member 'i_IobaseAmcc' used to hold the address for PCI Bar 0. Remove the unnecessary 'ui_Status' local variable in apci1500_do_bits() that is used to hold the result of some dummy reads. Rename the CamelCase local variable 'ui_InterruptStatus' that is used to check the interrupt from the amcc chip. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index ea6d98f..ac51181 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -1422,12 +1422,11 @@ static int apci1500_do_bits(struct comedi_device *dev, unsigned int *data) { struct apci1500_private *devpriv = dev->private; - unsigned int ui_Status; int i_RegValue; int i_Constant; devpriv->tsk_Current = current; - outl(0x0, devpriv->i_IobaseAmcc + 0x38); + outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR); if (data[0] == 1) { i_Constant = 0xC0; } else { @@ -1481,10 +1480,12 @@ static int apci1500_do_bits(struct comedi_device *dev, z8536_write(dev, 0xd0, APCI1500_RW_MASTER_INTERRUPT_CONTROL); /* Enables the PCI interrupt */ - outl(0x3000, devpriv->i_IobaseAmcc + 0x38); - ui_Status = inl(devpriv->i_IobaseAmcc + 0x10); - ui_Status = inl(devpriv->i_IobaseAmcc + 0x38); - outl(0x23000, devpriv->i_IobaseAmcc + 0x38); + outl(0x2000 | INTCSR_INBOX_FULL_INT, + devpriv->amcc + AMCC_OP_REG_INTCSR); + inl(devpriv->amcc + AMCC_OP_REG_IMB1); + inl(devpriv->amcc + AMCC_OP_REG_INTCSR); + outl(INTCSR_INBOX_INTR_STATUS | 0x2000 | INTCSR_INBOX_FULL_INT, + devpriv->amcc + AMCC_OP_REG_INTCSR); return insn->n; } @@ -1494,17 +1495,17 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) struct comedi_device *dev = d; struct apci1500_private *devpriv = dev->private; - unsigned int ui_InterruptStatus = 0; + unsigned int status; int i_RegValue = 0; /* Clear the interrupt mask */ i_InterruptMask = 0; /* Read the board interrupt status */ - ui_InterruptStatus = inl(devpriv->i_IobaseAmcc + 0x38); + status = inl(devpriv->amcc + AMCC_OP_REG_INTCSR); /* Test if board generated a interrupt */ - if ((ui_InterruptStatus & 0x800000) == 0x800000) { + if (status & INTCSR_INTR_ASSERTED) { /* Disable all Interrupt */ /* Selects the master interrupt control register */ /* Disables the main interrupt on the board */ @@ -1547,7 +1548,7 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) if (i_RegValue) { /* Disable the interrupt */ /* Selects the command and status register of port B */ - outl(0x0, devpriv->i_IobaseAmcc + 0x38); + outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR); if (i_RegValue & 0x80) { i_InterruptMask = diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 4b2e3fb..9571d50 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -8,6 +8,11 @@ #include "amcc_s5933.h" /* + * PCI Bar 0 Register map (devpriv->amcc) + * see amcc_s5933.h for register and bit defines + */ + +/* * PCI Bar 1 Register map (dev->iobase) */ #define APCI1500_Z8536_PORTC_REG 0x00 @@ -16,7 +21,7 @@ #define APCI1500_Z8536_CTRL_REG 0x03 struct apci1500_private { - int i_IobaseAmcc; + unsigned long amcc; int i_IobaseAddon; unsigned char b_OutputMemoryStatus; struct task_struct *tsk_Current; @@ -41,7 +46,7 @@ static int apci1500_auto_attach(struct comedi_device *dev, return ret; dev->iobase = pci_resource_start(pcidev, 1); - devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0); + devpriv->amcc = pci_resource_start(pcidev, 0); devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2); if (pcidev->irq > 0) { -- cgit v0.10.2 From af798116f56429d5eef766e715c3dd3a0a22bffc Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 3 Dec 2014 11:25:39 -0700 Subject: staging: comedi: addi_apci_1500: rename private data 'i_IobaseAddon' Rename this CamelCase member of the private data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index ac51181..7eb7d9e 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -600,7 +600,7 @@ static int apci1500_di_insn_bits(struct comedi_device *dev, { struct apci1500_private *devpriv = dev->private; - data[1] = inw(devpriv->i_IobaseAddon + APCI1500_DIGITAL_IP); + data[1] = inw(devpriv->addon + APCI1500_DIGITAL_IP); return insn->n; } @@ -641,8 +641,7 @@ static int apci1500_do_write(struct comedi_device *dev, if (data[3] == 0) { if (data[1] == 0) { data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; - outw(data[0], - devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP); + outw(data[0], devpriv->addon + APCI1500_DIGITAL_OP); } else { if (data[1] == 1) { switch (ui_NoOfChannel) { @@ -677,8 +676,7 @@ static int apci1500_do_write(struct comedi_device *dev, } outw(data[0], - devpriv->i_IobaseAddon + - APCI1500_DIGITAL_OP); + devpriv->addon + APCI1500_DIGITAL_OP); } else { dev_warn(dev->class_dev, "Specified channel not supported\n"); @@ -697,8 +695,7 @@ static int apci1500_do_write(struct comedi_device *dev, 0xffffffff; data[0] = data[0] & ui_Temp; outw(data[0], - devpriv->i_IobaseAddon + - APCI1500_DIGITAL_OP); + devpriv->addon + APCI1500_DIGITAL_OP); } else { if (data[1] == 1) { switch (ui_NoOfChannel) { @@ -752,9 +749,8 @@ static int apci1500_do_write(struct comedi_device *dev, } - outw(data[0], - devpriv->i_IobaseAddon + - APCI1500_DIGITAL_OP); + outw(data[0], devpriv->addon + + APCI1500_DIGITAL_OP); } else { dev_warn(dev->class_dev, "Specified channel not supported\n"); @@ -797,7 +793,7 @@ static int apci1500_timer_config(struct comedi_device *dev, /* Selection of the input clock */ if (data[0] == 0 || data[0] == 1 || data[0] == 2) { - outw(data[0], devpriv->i_IobaseAddon + APCI1500_CLK_SELECT); + outw(data[0], devpriv->addon + APCI1500_CLK_SELECT); } else { if (data[0] != 3) { dev_warn(dev->class_dev, @@ -1629,7 +1625,7 @@ static int apci1500_reset(struct comedi_device *dev) z8536_reset(dev); /* reset all the digital outputs */ - outw(0x0, devpriv->i_IobaseAddon + APCI1500_DIGITAL_OP); + outw(0x0, devpriv->addon + APCI1500_DIGITAL_OP); /* Deactivates all interrupts */ z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 9571d50..9cb80e0 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -22,7 +22,7 @@ struct apci1500_private { unsigned long amcc; - int i_IobaseAddon; + unsigned long addon; unsigned char b_OutputMemoryStatus; struct task_struct *tsk_Current; }; @@ -47,7 +47,7 @@ static int apci1500_auto_attach(struct comedi_device *dev, dev->iobase = pci_resource_start(pcidev, 1); devpriv->amcc = pci_resource_start(pcidev, 0); - devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2); + devpriv->addon = pci_resource_start(pcidev, 2); if (pcidev->irq > 0) { ret = request_irq(pcidev->irq, apci1500_interrupt, IRQF_SHARED, -- cgit v0.10.2 From 18be14034bf2364d9f100148ddd2594d81ab2855 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 3 Dec 2014 11:25:40 -0700 Subject: staging: comedi: addi_apci_1500: tidy up PCI Bar 2 register map Move the PCI Bar 1 register map defines to the main driver source file. For aesthetics, rename the defines. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 7eb7d9e..a888768 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -26,12 +26,9 @@ /* DIGITAL INPUT-OUTPUT DEFINE */ -#define APCI1500_DIGITAL_OP 2 -#define APCI1500_DIGITAL_IP 0 #define APCI1500_AND 2 #define APCI1500_OR 4 #define APCI1500_OR_PRIORITY 6 -#define APCI1500_CLK_SELECT 0 #define COUNTER1 0 #define COUNTER2 1 #define COUNTER3 2 @@ -600,7 +597,7 @@ static int apci1500_di_insn_bits(struct comedi_device *dev, { struct apci1500_private *devpriv = dev->private; - data[1] = inw(devpriv->addon + APCI1500_DIGITAL_IP); + data[1] = inw(devpriv->addon + APCI1500_DI_REG); return insn->n; } @@ -641,7 +638,7 @@ static int apci1500_do_write(struct comedi_device *dev, if (data[3] == 0) { if (data[1] == 0) { data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; - outw(data[0], devpriv->addon + APCI1500_DIGITAL_OP); + outw(data[0], devpriv->addon + APCI1500_DO_REG); } else { if (data[1] == 1) { switch (ui_NoOfChannel) { @@ -675,8 +672,7 @@ static int apci1500_do_write(struct comedi_device *dev, } - outw(data[0], - devpriv->addon + APCI1500_DIGITAL_OP); + outw(data[0], devpriv->addon + APCI1500_DO_REG); } else { dev_warn(dev->class_dev, "Specified channel not supported\n"); @@ -694,8 +690,7 @@ static int apci1500_do_write(struct comedi_device *dev, (data[0] << ui_NoOfChannel) ^ 0xffffffff; data[0] = data[0] & ui_Temp; - outw(data[0], - devpriv->addon + APCI1500_DIGITAL_OP); + outw(data[0], devpriv->addon + APCI1500_DO_REG); } else { if (data[1] == 1) { switch (ui_NoOfChannel) { @@ -749,8 +744,8 @@ static int apci1500_do_write(struct comedi_device *dev, } - outw(data[0], devpriv->addon + - APCI1500_DIGITAL_OP); + outw(data[0], + devpriv->addon + APCI1500_DO_REG); } else { dev_warn(dev->class_dev, "Specified channel not supported\n"); @@ -793,7 +788,7 @@ static int apci1500_timer_config(struct comedi_device *dev, /* Selection of the input clock */ if (data[0] == 0 || data[0] == 1 || data[0] == 2) { - outw(data[0], devpriv->addon + APCI1500_CLK_SELECT); + outw(data[0], devpriv->addon + APCI1500_CLK_SEL_REG); } else { if (data[0] != 3) { dev_warn(dev->class_dev, @@ -1625,7 +1620,7 @@ static int apci1500_reset(struct comedi_device *dev) z8536_reset(dev); /* reset all the digital outputs */ - outw(0x0, devpriv->addon + APCI1500_DIGITAL_OP); + outw(0x0, devpriv->addon + APCI1500_DO_REG); /* Deactivates all interrupts */ z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 9cb80e0..6892c0a 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -20,6 +20,13 @@ #define APCI1500_Z8536_PORTA_REG 0x02 #define APCI1500_Z8536_CTRL_REG 0x03 +/* + * PCI Bar 2 Register map (devpriv->addon) + */ +#define APCI1500_CLK_SEL_REG 0x00 +#define APCI1500_DI_REG 0x00 +#define APCI1500_DO_REG 0x02 + struct apci1500_private { unsigned long amcc; unsigned long addon; -- cgit v0.10.2 From eae27ff76798ca1f83106692e6991298018f48d4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 3 Dec 2014 11:25:41 -0700 Subject: staging: comedi: addi_apci_1500: remove APCI1500_ADDRESS_RANGE This define is not used by the driver. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index a888768..35281fb 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -21,9 +21,6 @@ * */ -/* Card Specific information */ -#define APCI1500_ADDRESS_RANGE 4 - /* DIGITAL INPUT-OUTPUT DEFINE */ #define APCI1500_AND 2 -- cgit v0.10.2 From d6dc9aa657088e326159df7459713a4b57a17cab Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 3 Dec 2014 11:25:42 -0700 Subject: staging: comedi: addi_apci_1500: handle shared interrupt The interrupt used by this driver is shared. If the board did not cause the interrupt the driver should return IRQ_NONE so that another driver can handle it. Fix the interrupt handler so this happens. Tidy up the interrupt handler a bit. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c index 35281fb..5bf943d 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c @@ -1483,115 +1483,104 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) struct comedi_device *dev = d; struct apci1500_private *devpriv = dev->private; - unsigned int status; - int i_RegValue = 0; + unsigned int val; /* Clear the interrupt mask */ i_InterruptMask = 0; - /* Read the board interrupt status */ - status = inl(devpriv->amcc + AMCC_OP_REG_INTCSR); - - /* Test if board generated a interrupt */ - if (status & INTCSR_INTR_ASSERTED) { - /* Disable all Interrupt */ - /* Selects the master interrupt control register */ - /* Disables the main interrupt on the board */ - i_RegValue = z8536_read(dev, - APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - if ((i_RegValue & 0x60) == 0x60) { - /* Deletes the interrupt of port A */ - i_RegValue = (i_RegValue & 0x0F) | 0x20; - z8536_write(dev, i_RegValue, - APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - i_InterruptMask = i_InterruptMask | 1; - if (i_Logic == APCI1500_OR_PRIORITY) { - i_RegValue = z8536_read(dev, - APCI1500_RW_PORT_A_SPECIFICATION); + val = inl(devpriv->amcc + AMCC_OP_REG_INTCSR); + if (!(val & INTCSR_INTR_ASSERTED)) + return IRQ_NONE; - i_RegValue = z8536_read(dev, - APCI1500_RW_PORT_A_INTERRUPT_CONTROL); + /* Disable all Interrupt */ + /* Selects the master interrupt control register */ + /* Disables the main interrupt on the board */ + val = z8536_read(dev, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); + if ((val & 0x60) == 0x60) { + /* Deletes the interrupt of port A */ + val &= 0x0f; + val |= 0x20; + z8536_write(dev, val, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); + i_InterruptMask = i_InterruptMask | 1; + if (i_Logic == APCI1500_OR_PRIORITY) { + val = z8536_read(dev, APCI1500_RW_PORT_A_SPECIFICATION); - i_InputChannel = 1 + (i_RegValue >> 1); + val = z8536_read(dev, + APCI1500_RW_PORT_A_INTERRUPT_CONTROL); - } else { - i_InputChannel = 0; - } - } - - i_RegValue = z8536_read(dev, - APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - if ((i_RegValue & 0x60) == 0x60) { - /* Deletes the interrupt of port B */ - i_RegValue = (i_RegValue & 0x0F) | 0x20; - z8536_write(dev, i_RegValue, - APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - /* Reads port B */ - i_RegValue = inb(dev->iobase + - APCI1500_Z8536_PORTB_REG); - - i_RegValue = i_RegValue & 0xC0; - /* Tests if this is an external error */ - - if (i_RegValue) { - /* Disable the interrupt */ - /* Selects the command and status register of port B */ - outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR); - - if (i_RegValue & 0x80) { - i_InterruptMask = - i_InterruptMask | 0x40; - } + i_InputChannel = 1 + (val >> 1); - if (i_RegValue & 0x40) { - i_InterruptMask = - i_InterruptMask | 0x80; - } - } else { - i_InterruptMask = i_InterruptMask | 2; - } + } else { + i_InputChannel = 0; } + } - i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS); - if ((i_RegValue & 0x60) == 0x60) { - /* Deletes the interrupt of timer 1 */ - i_RegValue = (i_RegValue & 0x0F) | 0x20; - z8536_write(dev, i_RegValue, - APCI1500_RW_CPT_TMR1_CMD_STATUS); - i_InterruptMask = i_InterruptMask | 4; + val = z8536_read(dev, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); + if ((val & 0x60) == 0x60) { + /* Deletes the interrupt of port B */ + val &= 0x0f; + val |= 0x20; + z8536_write(dev, val, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); + + /* Reads port B */ + val = inb(dev->iobase + APCI1500_Z8536_PORTB_REG); + val &= 0xc0; + /* Tests if this is an external error */ + if (val) { + /* Disable the interrupt */ + /* Selects the command and status register of port B */ + outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR); + + if (val & 0x80) + i_InterruptMask |= 0x40; + + if (val & 0x40) { + i_InterruptMask |= 0x80; + } + } else { + i_InterruptMask |= 0x02; } + } - i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS); - if ((i_RegValue & 0x60) == 0x60) { - /* Deletes the interrupt of timer 2 */ - i_RegValue = (i_RegValue & 0x0F) | 0x20; - z8536_write(dev, i_RegValue, - APCI1500_RW_CPT_TMR2_CMD_STATUS); - i_InterruptMask = i_InterruptMask | 8; - } + val = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS); + if ((val & 0x60) == 0x60) { + /* Deletes the interrupt of timer 1 */ + val &= 0x0f; + val |= 0x20; + z8536_write(dev, val, APCI1500_RW_CPT_TMR1_CMD_STATUS); - i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS); - if ((i_RegValue & 0x60) == 0x60) { - /* Deletes the interrupt of timer 3 */ - i_RegValue = (i_RegValue & 0x0F) | 0x20; - z8536_write(dev, i_RegValue, - APCI1500_RW_CPT_TMR3_CMD_STATUS); - if (i_CounterLogic == APCI1500_COUNTER) - i_InterruptMask = i_InterruptMask | 0x10; - else - i_InterruptMask = i_InterruptMask | 0x20; - } + i_InterruptMask |= 0x04; + } - send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ + val = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS); + if ((val & 0x60) == 0x60) { + /* Deletes the interrupt of timer 2 */ + val &= 0x0f; + val |= 0x20; + z8536_write(dev, val, APCI1500_RW_CPT_TMR2_CMD_STATUS); - /* Authorizes the main interrupt on the board */ - z8536_write(dev, 0xd0, APCI1500_RW_MASTER_INTERRUPT_CONTROL); - } else { - dev_warn(dev->class_dev, - "Interrupt from unknown source\n"); + i_InterruptMask |= 0x08; + } + val = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS); + if ((val & 0x60) == 0x60) { + /* Deletes the interrupt of timer 3 */ + val &= 0x0f; + val |= 0x20; + z8536_write(dev, val, APCI1500_RW_CPT_TMR3_CMD_STATUS); + + if (i_CounterLogic == APCI1500_COUNTER) + i_InterruptMask |= 0x10; + else + i_InterruptMask |= 0x20; } + /* send signal to the sample */ + send_sig(SIGIO, devpriv->tsk_Current, 0); + + /* Authorizes the main interrupt on the board */ + z8536_write(dev, 0xd0, APCI1500_RW_MASTER_INTERRUPT_CONTROL); + return IRQ_HANDLED; } -- cgit v0.10.2 From ddd54d6518ea613d0d73326daf5eb7c950d303dc Mon Sep 17 00:00:00 2001 From: drumber-1 Date: Wed, 3 Dec 2014 13:33:57 +0000 Subject: Staging: comedi: fix spacing coding style issue in s626.c This is a patch to the s626.c file that fixes a spacing error found by the checkpatch.pl tool Signed-off-by: Jacob L Close Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 14932c5..fc497dd 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -118,7 +118,7 @@ static void s626_mc_enable(struct comedi_device *dev, static void s626_mc_disable(struct comedi_device *dev, unsigned int cmd, unsigned int reg) { - writel(cmd << 16 , dev->mmio + reg); + writel(cmd << 16, dev->mmio + reg); mmiowb(); } -- cgit v0.10.2 From 9cc841b158655af02f3900ebc0cd917957b951c0 Mon Sep 17 00:00:00 2001 From: Frederic Jacob Date: Thu, 18 Dec 2014 00:15:07 -0500 Subject: Staging: comedi: fix blank line coding style in comedi_bond.c This is a patch to the comedi_bond.c file that fixes up a blank line after declaration warning found by the checkpatch.pl tool Signed-off-by: Frederic Jacob Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 85b2f4a..221d381 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -261,6 +261,7 @@ static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it) { /* Append dev:subdev to devpriv->name */ char buf[20]; + snprintf(buf, sizeof(buf), "%u:%u ", bdev->minor, bdev->subdev); strlcat(devpriv->name, buf, -- cgit v0.10.2 From fc1964a5f44caf8c9accbc6b390d51b10ef0e718 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Thu, 25 Dec 2014 12:28:28 -0800 Subject: staging: comedi: dmm32at: fix style issues Before: 1 ERROR: code indent should use tabs where possible 1 WARNING: please, no spaces at the start of a line After: (none) Signed-off-by: David Decotigny Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 6df298a..31919b8 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -365,7 +365,7 @@ static void dmm32at_setaitimer(struct comedi_device *dev, unsigned int nansec) /* enable the ai conversion interrupt and the clock to start scans */ outb(DMM32AT_INTCLK_ADINT | DMM32AT_INTCLK_CLKEN | DMM32AT_INTCLK_CLKSEL, - dev->iobase + DMM32AT_INTCLK_REG); + dev->iobase + DMM32AT_INTCLK_REG); } static int dmm32at_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) -- cgit v0.10.2 From 1308a4877345469b21164a81c79b0e91989b3e43 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:29 +0000 Subject: staging: comedi: 8255_pci: rewrite comedi driver comment block Rewrite the comedi "driver" comment block to conform to the usual format for comedi driver comment blocks and reformat it to use the usual block comment style. In particular, the "Devices:" line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). The original comment indicated the number of DIO channels in each item on the "Devices:" line. Move this information into separate paragraphs. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 8b95898..9847642 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -22,33 +22,44 @@ */ /* -Driver: 8255_pci -Description: Generic PCI based 8255 Digital I/O boards -Devices: (ADLink) PCI-7224 [adl_pci-7224] - 24 channels - (ADLink) PCI-7248 [adl_pci-7248] - 48 channels - (ADLink) PCI-7296 [adl_pci-7296] - 96 channels - (Measurement Computing) PCI-DIO24 [cb_pci-dio24] - 24 channels - (Measurement Computing) PCI-DIO24H [cb_pci-dio24h] - 24 channels - (Measurement Computing) PCI-DIO48H [cb_pci-dio48h] - 48 channels - (Measurement Computing) PCI-DIO96H [cb_pci-dio96h] - 96 channels - (National Instruments) PCI-DIO-96 [ni_pci-dio-96] - 96 channels - (National Instruments) PCI-DIO-96B [ni_pci-dio-96b] - 96 channels - (National Instruments) PXI-6508 [ni_pxi-6508] - 96 channels - (National Instruments) PCI-6503 [ni_pci-6503] - 24 channels - (National Instruments) PCI-6503B [ni_pci-6503b] - 24 channels - (National Instruments) PCI-6503X [ni_pci-6503x] - 24 channels - (National Instruments) PXI-6503 [ni_pxi-6503] - 24 channels -Author: H Hartley Sweeten -Updated: Wed, 12 Sep 2012 11:52:01 -0700 -Status: untested - -Some of these boards also have an 8254 programmable timer/counter -chip. This chip is not currently supported by this driver. - -Interrupt support for these boards is also not currently supported. - -Configuration Options: not applicable, uses PCI auto config -*/ + * Driver: 8255_pci + * Description: Generic PCI based 8255 Digital I/O boards + * Devices: [ADLink] PCI-7224 (adl_pci-7224), PCI-7248 (adl_pci-7248), + * PCI-7296 (adl_pci-7296), + * [Measurement Computing] PCI-DIO24 (cb_pci-dio24), + * PCI-DIO24H (cb_pci-dio24h), PCI-DIO48H (cb_pci-dio48h), + * PCI-DIO96H (cb_pci-dio96h), + * [National Instruments] PCI-DIO-96 (ni_pci-dio-96), + * PCI-DIO-96B (ni_pci-dio-96b), PXI-6508 (ni_pxi-6508), + * PCI-6503 (ni_pci-6503), PCI-6503B (ni_pci-6503b), + * PCI-6503X (ni_pci-6503x), PXI-6503 (ni_pxi-6503) + * Author: H Hartley Sweeten + * Updated: Wed, 12 Sep 2012 11:52:01 -0700 + * Status: untested + * + * These boards have one or more 8255 digital I/O chips, each of which + * is supported as a separate 24-channel DIO subdevice. + * + * Boards with 24 DIO channels (1 DIO subdevice): + * + * PCI-7224, PCI-DIO24, PCI-DIO24H, PCI-6503, PCI-6503B, PCI-6503X, + * PXI-6503 + * + * Boards with 48 DIO channels (2 DIO subdevices): + * + * PCI-7248, PCI-DIO48H + * + * Boards with 96 DIO channels (4 DIO subdevices): + * + * PCI-7296, PCI-DIO96H, PCI-DIO-96, PCI-DIO-96B, PXI-6508 + * + * Some of these boards also have an 8254 programmable timer/counter + * chip. This chip is not currently supported by this driver. + * + * Interrupt support for these boards is also not currently supported. + * + * Configuration Options: not applicable, uses PCI auto config. + */ #include #include -- cgit v0.10.2 From 43fe80b4498dae554ef0fa5dbfa4938fa791d989 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:30 +0000 Subject: staging: comedi: adl_pci6208: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index 528f15c..a3ea4b7 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -19,8 +19,7 @@ /* * Driver: adl_pci6208 * Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards - * Devices: (ADLink) PCI-6208 [adl_pci6208] - * (ADLink) PCI-6216 [adl_pci6216] + * Devices: [ADLink] PCI-6208 (adl_pci6208), PCI-6216 (adl_pci6216) * Author: nsyeow * Updated: Fri, 30 Jan 2004 14:44:27 +0800 * Status: untested -- cgit v0.10.2 From cd44161e8d78d348ef049c62a670d04a6e0ecec0 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:31 +0000 Subject: staging: comedi: adl_pci7x3x: rewrite comedi driver comment block Rewrite the comedi "driver" comment block to conform to the usual format for comedi driver comment blocks and reformat it to use the usual block comment style. In particular, the "Devices:" line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). The original comment indicated the number of input and output channels in each item on the "Devices:" line. Move this information into a separate paragraph moved from a block comment found elsewhere in the driver. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c index fb8e5f5..618e641 100644 --- a/drivers/staging/comedi/drivers/adl_pci7x3x.c +++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c @@ -22,27 +22,35 @@ */ /* -Driver: adl_pci7x3x -Description: 32/64-Channel Isolated Digital I/O Boards -Devices: (ADLink) PCI-7230 [adl_pci7230] - 16 input / 16 output - (ADLink) PCI-7233 [adl_pci7233] - 32 input - (ADLink) PCI-7234 [adl_pci7234] - 32 output - (ADLink) PCI-7432 [adl_pci7432] - 32 input / 32 output - (ADLink) PCI-7433 [adl_pci7433] - 64 input - (ADLink) PCI-7434 [adl_pci7434] - 64 output -Author: H Hartley Sweeten -Updated: Thu, 02 Aug 2012 14:27:46 -0700 -Status: untested - -The PCI-7230, PCI-7432 and PCI-7433 boards also support external -interrupt signals on digital input channels 0 and 1. The PCI-7233 -has dual-interrupt sources for change-of-state (COS) on any 16 -digital input channels of LSB and for COS on any 16 digital input -lines of MSB. Interrupts are not currently supported by this -driver. - -Configuration Options: not applicable, uses comedi PCI auto config -*/ + * Driver: adl_pci7x3x + * Description: 32/64-Channel Isolated Digital I/O Boards + * Devices: [ADLink] PCI-7230 (adl_pci7230), PCI-7233 (adl_pci7233), + * PCI-7234 (adl_pci7234), PCI-7432 (adl_pci7432), PCI-7433 (adl_pci7433), + * PCI-7434 (adl_pci7434) + * Author: H Hartley Sweeten + * Updated: Thu, 02 Aug 2012 14:27:46 -0700 + * Status: untested + * + * One or two subdevices are setup by this driver depending on + * the number of digital inputs and/or outputs provided by the + * board. Each subdevice has a maximum of 32 channels. + * + * PCI-7230 - 2 subdevices: 0 - 16 input, 1 - 16 output + * PCI-7233 - 1 subdevice: 0 - 32 input + * PCI-7234 - 1 subdevice: 0 - 32 output + * PCI-7432 - 2 subdevices: 0 - 32 input, 1 - 32 output + * PCI-7433 - 2 subdevices: 0 - 32 input, 1 - 32 input + * PCI-7434 - 2 subdevices: 0 - 32 output, 1 - 32 output + * + * The PCI-7230, PCI-7432 and PCI-7433 boards also support external + * interrupt signals on digital input channels 0 and 1. The PCI-7233 + * has dual-interrupt sources for change-of-state (COS) on any 16 + * digital input channels of LSB and for COS on any 16 digital input + * lines of MSB. Interrupts are not currently supported by this + * driver. + * + * Configuration Options: not applicable, uses comedi PCI auto config + */ #include #include @@ -155,18 +163,6 @@ static int adl_pci7x3x_auto_attach(struct comedi_device *dev, return ret; dev->iobase = pci_resource_start(pcidev, 2); - /* - * One or two subdevices are setup by this driver depending on - * the number of digital inputs and/or outputs provided by the - * board. Each subdevice has a maximum of 32 channels. - * - * PCI-7230 - 2 subdevices: 0 - 16 input, 1 - 16 output - * PCI-7233 - 1 subdevice: 0 - 32 input - * PCI-7234 - 1 subdevice: 0 - 32 output - * PCI-7432 - 2 subdevices: 0 - 32 input, 1 - 32 output - * PCI-7433 - 2 subdevices: 0 - 32 input, 1 - 32 input - * PCI-7434 - 2 subdevices: 0 - 32 output, 1 - 32 output - */ ret = comedi_alloc_subdevices(dev, board->nsubdevs); if (ret) return ret; -- cgit v0.10.2 From 8abf08e5a789edd82f091a2c2519cee67bcdede5 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:32 +0000 Subject: staging: comedi: adl_pci8164: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index 72bccb4..cc6c53b 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -18,7 +18,7 @@ /* * Driver: adl_pci8164 * Description: Driver for the Adlink PCI-8164 4 Axes Motion Control board - * Devices: (ADLink) PCI-8164 [adl_pci8164] + * Devices: [ADLink] PCI-8164 (adl_pci8164) * Author: Michel Lachaine * Status: experimental * Updated: Mon, 14 Apr 2008 15:10:32 +0100 -- cgit v0.10.2 From f101264d54d3b29f4de4b38942462092936ecf1e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:33 +0000 Subject: staging: comedi: adv_pci1723: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 65f854e..f1945be 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -20,7 +20,7 @@ * Driver: adv_pci1723 * Description: Advantech PCI-1723 * Author: yonggang , Ian Abbott - * Devices: (Advantech) PCI-1723 [adv_pci1723] + * Devices: [Advantech] PCI-1723 (adv_pci1723) * Updated: Mon, 14 Apr 2008 15:12:56 +0100 * Status: works * -- cgit v0.10.2 From 16cdcb1f31be13e108360dc75a7dc7997cf371f8 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:34 +0000 Subject: staging: comedi: adv_pci1724: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c index a8d2840..a3573ea 100644 --- a/drivers/staging/comedi/drivers/adv_pci1724.c +++ b/drivers/staging/comedi/drivers/adv_pci1724.c @@ -22,7 +22,7 @@ /* * Driver: adv_pci1724 * Description: Advantech PCI-1724U - * Devices: (Advantech) PCI-1724U [adv_pci1724] + * Devices: [Advantech] PCI-1724U (adv_pci1724) * Author: Frank Mori Hess * Updated: 2013-02-09 * Status: works -- cgit v0.10.2 From cd07d33a66a0c88bc53dcceab910f1b7d18b1c80 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:35 +0000 Subject: staging: comedi: c6xdigio: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index e7cb703..1a109e3 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -22,7 +22,7 @@ * Description: Mechatronic Systems Inc. C6x_DIGIO DSP daughter card * Author: Dan Block * Status: unknown - * Devices: (Mechatronic Systems Inc.) C6x_DIGIO DSP daughter card [c6xdigio] + * Devices: [Mechatronic Systems Inc.] C6x_DIGIO DSP daughter card (c6xdigio) * Updated: Sun Nov 20 20:18:34 EST 2005 * * Configuration Options: -- cgit v0.10.2 From fb1b86c693bb1a9bf87b3fd955d72d3f11a099da Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:36 +0000 Subject: staging: comedi: cb_pcidda: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 01875d7..2b2cfcd 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -22,12 +22,10 @@ /* * Driver: cb_pcidda * Description: MeasurementComputing PCI-DDA series - * Devices: (Measurement Computing) PCI-DDA08/12 [pci-dda08/12] - * (Measurement Computing) PCI-DDA04/12 [pci-dda04/12] - * (Measurement Computing) PCI-DDA02/12 [pci-dda02/12] - * (Measurement Computing) PCI-DDA08/16 [pci-dda08/16] - * (Measurement Computing) PCI-DDA04/16 [pci-dda04/16] - * (Measurement Computing) PCI-DDA02/16 [pci-dda02/16] + * Devices: [Measurement Computing] PCI-DDA08/12 (pci-dda08/12), + * PCI-DDA04/12 (pci-dda04/12), PCI-DDA02/12 (pci-dda02/12), + * PCI-DDA08/16 (pci-dda08/16), PCI-DDA04/16 (pci-dda04/16), + * PCI-DDA02/16 (pci-dda02/16) * Author: Ivan Martinez * Frank Mori Hess * Status: works -- cgit v0.10.2 From db908f5551c60779970905833812eb601134bdbb Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:37 +0000 Subject: staging: comedi: comedi_parport: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 3bac903..ceef693 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -24,7 +24,7 @@ * Description: Standard PC parallel port * Author: ds * Status: works in immediate mode - * Devices: (standard) parallel port [comedi_parport] + * Devices: [standard] parallel port (comedi_parport) * Updated: Tue, 30 Apr 2002 21:11:45 -0700 * * A cheap and easy way to get a few more digital I/O lines. Steal -- cgit v0.10.2 From 03405eef4722af91fb035d08c116950a73553f11 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:38 +0000 Subject: staging: comedi: dac02: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dac02.c b/drivers/staging/comedi/drivers/dac02.c index beb36c8..a6798ad 100644 --- a/drivers/staging/comedi/drivers/dac02.c +++ b/drivers/staging/comedi/drivers/dac02.c @@ -24,7 +24,7 @@ /* * Driver: dac02 * Description: Comedi driver for DAC02 compatible boards - * Devices: (Keithley Metrabyte) DAC-02 [dac02] + * Devices: [Keithley Metrabyte] DAC-02 (dac02) * Author: H Hartley Sweeten * Updated: Tue, 11 Mar 2014 11:27:19 -0700 * Status: unknown -- cgit v0.10.2 From 026d6713d274ae5e48127d68dfe7a82952a7e3a0 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:39 +0000 Subject: staging: comedi: das08: remove comedi driver comment block This is a module containing common code for the "das08_cs", "das08_isa" and "das08_pci" comedi drivers. It does not need its own comedi "driver" comment block, so remove it. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 20a9f0e..c78c0df 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -1,6 +1,6 @@ /* * comedi/drivers/das08.c - * comedi driver for common DAS08 support (used by ISA/PCI/PCMCIA drivers) + * comedi module for common DAS08 support (used by ISA/PCI/PCMCIA drivers) * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 2000 David A. Schleef @@ -18,21 +18,6 @@ * GNU General Public License for more details. */ -/* - * Driver: das08 - * Description: DAS-08 compatible boards - * Devices: various, see das08_isa, das08_cs, and das08_pci drivers - * Author: Warren Jasper, ds, Frank Hess - * Updated: Fri, 31 Aug 2012 19:19:06 +0100 - * Status: works - * - * This driver is used by the das08_isa, das08_cs, and das08_pci - * drivers to provide the common support for the DAS-08 hardware. - * - * The driver doesn't support asynchronous commands, since the - * cheap das08 hardware doesn't really support them. - */ - #include #include "../comedidev.h" -- cgit v0.10.2 From fc0871696c788828e9f367d90cd3a7b5a01fc616 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:40 +0000 Subject: staging: comedi: das08_isa: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c index e4ba268..2d9a31d 100644 --- a/drivers/staging/comedi/drivers/das08_isa.c +++ b/drivers/staging/comedi/drivers/das08_isa.c @@ -21,18 +21,12 @@ /* * Driver: das08_isa * Description: DAS-08 ISA/PC-104 compatible boards - * Devices: (Keithley Metrabyte) DAS08 [isa-das08], - * (ComputerBoards) DAS08 [isa-das08] - * (ComputerBoards) DAS08-PGM [das08-pgm] - * (ComputerBoards) DAS08-PGH [das08-pgh] - * (ComputerBoards) DAS08-PGL [das08-pgl] - * (ComputerBoards) DAS08-AOH [das08-aoh] - * (ComputerBoards) DAS08-AOL [das08-aol] - * (ComputerBoards) DAS08-AOM [das08-aom] - * (ComputerBoards) DAS08/JR-AO [das08/jr-ao] - * (ComputerBoards) DAS08/JR-16-AO [das08jr-16-ao] - * (ComputerBoards) PC104-DAS08 [pc104-das08] - * (ComputerBoards) DAS08/JR/16 [das08jr/16] + * Devices: [Keithley Metrabyte] DAS08 (isa-das08), + * [ComputerBoards] DAS08 (isa-das08), DAS08-PGM (das08-pgm), + * DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh), + * DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao), + * DAS08/JR-16-AO (das08jr-16-ao), PC104-DAS08 (pc104-das08), + * DAS08/JR/16 (das08jr/16) * Author: Warren Jasper, ds, Frank Hess * Updated: Fri, 31 Aug 2012 19:19:06 +0100 * Status: works -- cgit v0.10.2 From 7ba7eea07ba310db2643340dfce8d1b76c78064f Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:41 +0000 Subject: staging: comedi: das08_pci: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c index 0987ce55..b2ea10b 100644 --- a/drivers/staging/comedi/drivers/das08_pci.c +++ b/drivers/staging/comedi/drivers/das08_pci.c @@ -21,7 +21,7 @@ /* * Driver: das08_pci * Description: DAS-08 PCI compatible boards - * Devices: (ComputerBoards) PCI-DAS08 [pci-das08] + * Devices: [ComputerBoards] PCI-DAS08 (pci-das08) * Author: Warren Jasper, ds, Frank Hess * Updated: Fri, 31 Aug 2012 19:19:06 +0100 * Status: works -- cgit v0.10.2 From c3c4f0bfe9f19c2da586ac3bf39aa1e31fcff3ed Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:42 +0000 Subject: staging: comedi: das16: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 2436057..64b0ada 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -22,28 +22,17 @@ * Driver: das16 * Description: DAS16 compatible boards * Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze - * Devices: (Keithley Metrabyte) DAS-16 [das-16] - * (Keithley Metrabyte) DAS-16G [das-16g] - * (Keithley Metrabyte) DAS-16F [das-16f] - * (Keithley Metrabyte) DAS-1201 [das-1201] - * (Keithley Metrabyte) DAS-1202 [das-1202] - * (Keithley Metrabyte) DAS-1401 [das-1401] - * (Keithley Metrabyte) DAS-1402 [das-1402] - * (Keithley Metrabyte) DAS-1601 [das-1601] - * (Keithley Metrabyte) DAS-1602 [das-1602] - * (ComputerBoards) PC104-DAS16/JR [pc104-das16jr] - * (ComputerBoards) PC104-DAS16JR/16 [pc104-das16jr/16] - * (ComputerBoards) CIO-DAS16 [cio-das16] - * (ComputerBoards) CIO-DAS16F [cio-das16/f] - * (ComputerBoards) CIO-DAS16/JR [cio-das16/jr] - * (ComputerBoards) CIO-DAS16JR/16 [cio-das16jr/16] - * (ComputerBoards) CIO-DAS1401/12 [cio-das1401/12] - * (ComputerBoards) CIO-DAS1402/12 [cio-das1402/12] - * (ComputerBoards) CIO-DAS1402/16 [cio-das1402/16] - * (ComputerBoards) CIO-DAS1601/12 [cio-das1601/12] - * (ComputerBoards) CIO-DAS1602/12 [cio-das1602/12] - * (ComputerBoards) CIO-DAS1602/16 [cio-das1602/16] - * (ComputerBoards) CIO-DAS16/330 [cio-das16/330] + * Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g), + * DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202), + * DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601), + * DAS-1602 (das-1602), + * [ComputerBoards] PC104-DAS16/JR (pc104-das16jr), + * PC104-DAS16JR/16 (pc104-das16jr/16), CIO-DAS16 (cio-das16), + * CIO-DAS16F (cio-das16/f), CIO-DAS16/JR (cio-das16/jr), + * CIO-DAS16JR/16 (cio-das16jr/16), CIO-DAS1401/12 (cio-das1401/12), + * CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16), + * CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12), + * CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330) * Status: works * Updated: 2003-10-12 * -- cgit v0.10.2 From d21f819c9aaaf9aa6baf2c598c863b742c56a760 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:43 +0000 Subject: staging: comedi: das6402: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index 780f4f6..b8755b5 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -20,8 +20,8 @@ /* * Driver: das6402 * Description: Keithley Metrabyte DAS6402 (& compatibles) - * Devices: (Keithley Metrabyte) DAS6402-12 (das6402-12) - * (Keithley Metrabyte) DAS6402-16 (das6402-16) + * Devices: [Keithley Metrabyte] DAS6402-12 (das6402-12), + * DAS6402-16 (das6402-16) * Author: H Hartley Sweeten * Updated: Fri, 14 Mar 2014 10:18:43 -0700 * Status: unknown -- cgit v0.10.2 From df4d44edbc258e4620e9fa7de2a876d81ca48dfa Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:44 +0000 Subject: staging: comedi: dmm32at: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 31919b8..1af0066 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -19,7 +19,7 @@ /* * Driver: dmm32at * Description: Diamond Systems Diamond-MM-32-AT - * Devices: (Diamond Systems) Diamond-MM-32-AT [dmm32at] + * Devices: [Diamond Systems] Diamond-MM-32-AT (dmm32at) * Author: Perry J. Piplani * Updated: Fri Jun 4 09:13:24 CDT 2004 * Status: experimental -- cgit v0.10.2 From f8e82bb315d1d999481e29149f1709ebdc247c11 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:45 +0000 Subject: staging: comedi: dt282x: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 2be98bb..cfa0f97 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -20,22 +20,12 @@ * Driver: dt282x * Description: Data Translation DT2821 series (including DT-EZ) * Author: ds - * Devices: (Data Translation) DT2821 [dt2821] - * (Data Translation) DT2821-F-16SE [dt2821-f] - * (Data Translation) DT2821-F-8DI [dt2821-f] - * (Data Translation) DT2821-G-16SE [dt2821-g] - * (Data Translation) DT2821-G-8DI [dt2821-g] - * (Data Translation) DT2823 [dt2823] - * (Data Translation) DT2824-PGH [dt2824-pgh] - * (Data Translation) DT2824-PGL [dt2824-pgl] - * (Data Translation) DT2825 [dt2825] - * (Data Translation) DT2827 [dt2827] - * (Data Translation) DT2828 [dt2828] - * (Data Translation) DT2928 [dt2829] - * (Data Translation) DT21-EZ [dt21-ez] - * (Data Translation) DT23-EZ [dt23-ez] - * (Data Translation) DT24-EZ [dt24-ez] - * (Data Translation) DT24-EZ-PGL [dt24-ez-pgl] + * Devices: [Data Translation] DT2821 (dt2821), DT2821-F-16SE (dt2821-f), + * DT2821-F-8DI (dt2821-f), DT2821-G-16SE (dt2821-g), + * DT2821-G-8DI (dt2821-g), DT2823 (dt2823), DT2824-PGH (dt2824-pgh), + * DT2824-PGL (dt2824-pgl), DT2825 (dt2825), DT2827 (dt2827), + * DT2828 (dt2828), DT2928 (dt2829), DT21-EZ (dt21-ez), DT23-EZ (dt23-ez), + * DT24-EZ (dt24-ez), DT24-EZ-PGL (dt24-ez-pgl) * Status: complete * Updated: Wed, 22 Aug 2001 17:11:34 -0700 * -- cgit v0.10.2 From f94a8c8749b7a75175019968a8f37621f0034270 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:46 +0000 Subject: staging: comedi: dyna_pci10xx: rewrite comedi driver comment block Rewrite the comedi "driver" comment block to conform to the usual format for comedi driver comment blocks and reformat it to use the usual block comment style. In particular, the "Devices:" line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Change the original "Devices:" line to a "Description:" line. Remove the "Version:" line as we don't care about driver version numbers in the kernel. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index 1b6324c..6c1e442 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -14,24 +14,23 @@ */ /* - Driver: dyna_pci10xx - Devices: Dynalog India PCI DAQ Cards, http://www.dynalogindia.com/ - Author: Prashant Shah - Developed at Automation Labs, Chemical Dept., IIT Bombay, India. - Prof. Kannan Moudgalya - http://www.iitb.ac.in - Status: Stable - Version: 1.0 - Device Supported : - - Dynalog PCI 1050 - - Notes : - - Dynalog India Pvt. Ltd. does not have a registered PCI Vendor ID and - they are using the PLX Technlogies Vendor ID since that is the PCI Chip used - in the card. - - Dynalog India Pvt. Ltd. has provided the internal register specification for - their cards in their manuals. -*/ + * Driver: dyna_pci10xx + * Description: Dynalog India PCI DAQ Cards, http://www.dynalogindia.com/ + * Devices: [Dynalog] PCI-1050 (dyna_pci1050) + * Author: Prashant Shah + * Status: Stable + * + * Developed at Automation Labs, Chemical Dept., IIT Bombay, India. + * Prof. Kannan Moudgalya + * http://www.iitb.ac.in + * + * Notes : + * - Dynalog India Pvt. Ltd. does not have a registered PCI Vendor ID and + * they are using the PLX Technlogies Vendor ID since that is the PCI Chip + * used in the card. + * - Dynalog India Pvt. Ltd. has provided the internal register specification + * for their cards in their manuals. + */ #include #include -- cgit v0.10.2 From 2a669fac0c31f3ef8c5d43f4ffec1854c8de57c2 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:47 +0000 Subject: staging: comedi: ii_pci20kc: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 1085d66..0768bc42 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -9,7 +9,7 @@ /* * Driver: ii_pci20kc * Description: Intelligent Instruments PCI-20001C carrier board - * Devices: (Intelligent Instrumentation) PCI-20001C [ii_pci20kc] + * Devices: [Intelligent Instrumentation] PCI-20001C (ii_pci20kc) * Author: Markus Kempf * Status: works * -- cgit v0.10.2 From b717ffee979f54bb1c0e937555f3c86b464ecb03 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:48 +0000 Subject: staging: comedi: ke_counter: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index 77e94a3..3c19e0f 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -19,7 +19,7 @@ /* * Driver: ke_counter * Description: Driver for Kolter Electronic Counter Card - * Devices: (Kolter Electronic) PCI Counter Card [ke_counter] + * Devices: [Kolter Electronic] PCI Counter Card (ke_counter) * Author: Michael Hillmann * Updated: Mon, 14 Apr 2008 15:42:42 +0100 * Status: tested -- cgit v0.10.2 From 5714f93463fdb2f471719226eaea34f66160c420 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:49 +0000 Subject: staging: comedi: me_daq: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index b5278c1..bffc161 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -19,8 +19,7 @@ /* * Driver: me_daq * Description: Meilhaus PCI data acquisition cards - * Devices: (Meilhaus) ME-2600i [me-2600i] - * (Meilhaus) ME-2000i [me-2000i] + * Devices: [Meilhaus] ME-2600i (me-2600i), ME-2000i (me-2000i) * Author: Michael Hillmann * Status: experimental * -- cgit v0.10.2 From 63f9384faf566ff91bd621ce528f6b2c4fcf83d9 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:50 +0000 Subject: staging: comedi: mf6x4: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/mf6x4.c b/drivers/staging/comedi/drivers/mf6x4.c index af21bc1..db972bc 100644 --- a/drivers/staging/comedi/drivers/mf6x4.c +++ b/drivers/staging/comedi/drivers/mf6x4.c @@ -18,7 +18,7 @@ /* * Driver: mf6x4 * Description: Humusoft MF634 and MF624 Data acquisition card driver - * Devices: Humusoft MF634, Humusoft MF624 + * Devices: [Humusoft] MF634 (mf634), MF624 (mf624) * Author: Rostislav Lisovy * Status: works * Updated: -- cgit v0.10.2 From bd3a1db5787f8fff01def47d735b6496e39dcbe7 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:51 +0000 Subject: staging: comedi: ni_6527: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index f99847f..530f716 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -19,8 +19,7 @@ /* * Driver: ni_6527 * Description: National Instruments 6527 - * Devices: (National Instruments) PCI-6527 [pci-6527] - * (National Instruments) PXI-6527 [pxi-6527] + * Devices: [National Instruments] PCI-6527 (pci-6527), PXI-6527 (pxi-6527) * Author: David A. Schleef * Updated: Sat, 25 Jan 2003 13:24:40 -0800 * Status: works -- cgit v0.10.2 From 0e147538c1f4da4b04604fcb842cccd21b08eb65 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:52 +0000 Subject: staging: comedi: ni_65xx: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index bcb326e..9e8462b 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -25,28 +25,10 @@ * Author: Jon Grierson , * Frank Mori Hess * Status: testing - * Devices: (National Instruments) PCI-6509 [ni_65xx] - * (National Instruments) PXI-6509 [ni_65xx] - * (National Instruments) PCI-6510 [ni_65xx] - * (National Instruments) PCI-6511 [ni_65xx] - * (National Instruments) PXI-6511 [ni_65xx] - * (National Instruments) PCI-6512 [ni_65xx] - * (National Instruments) PXI-6512 [ni_65xx] - * (National Instruments) PCI-6513 [ni_65xx] - * (National Instruments) PXI-6513 [ni_65xx] - * (National Instruments) PCI-6514 [ni_65xx] - * (National Instruments) PXI-6514 [ni_65xx] - * (National Instruments) PCI-6515 [ni_65xx] - * (National Instruments) PXI-6515 [ni_65xx] - * (National Instruments) PCI-6516 [ni_65xx] - * (National Instruments) PCI-6517 [ni_65xx] - * (National Instruments) PCI-6518 [ni_65xx] - * (National Instruments) PCI-6519 [ni_65xx] - * (National Instruments) PCI-6520 [ni_65xx] - * (National Instruments) PCI-6521 [ni_65xx] - * (National Instruments) PXI-6521 [ni_65xx] - * (National Instruments) PCI-6528 [ni_65xx] - * (National Instruments) PXI-6528 [ni_65xx] + * Devices: [National Instruments] PCI-6509 (ni_65xx), PXI-6509, PCI-6510, + * PCI-6511, PXI-6511, PCI-6512, PXI-6512, PCI-6513, PXI-6513, PCI-6514, + * PXI-6514, PCI-6515, PXI-6515, PCI-6516, PCI-6517, PCI-6518, PCI-6519, + * PCI-6520, PCI-6521, PXI-6521, PCI-6528, PXI-6528 * Updated: Mon, 21 Jul 2014 12:49:58 +0000 * * Configuration Options: not applicable, uses PCI auto config -- cgit v0.10.2 From fe8fd0c830841664c039bf3a8d4b4e1f847df226 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:53 +0000 Subject: staging: comedi: ni_65xx: use board names on "Devices:" line All the supported devices listed on the "Devices:" line currently use the comedi driver name as the comedi board name. Historically, this documented the name that should be passed to the "comedi_config" program to "attach" the device via the COMEDI_DEVCONFIG ioctl. Some drivers expected the driver name and others expected the board name. Since this driver no longer supports the legacy "attach" mechanism, change the "Devices:" list to show the board names, as that is probably more useful. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 9e8462b..67cb758 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -25,10 +25,14 @@ * Author: Jon Grierson , * Frank Mori Hess * Status: testing - * Devices: [National Instruments] PCI-6509 (ni_65xx), PXI-6509, PCI-6510, - * PCI-6511, PXI-6511, PCI-6512, PXI-6512, PCI-6513, PXI-6513, PCI-6514, - * PXI-6514, PCI-6515, PXI-6515, PCI-6516, PCI-6517, PCI-6518, PCI-6519, - * PCI-6520, PCI-6521, PXI-6521, PCI-6528, PXI-6528 + * Devices: [National Instruments] PCI-6509 (pci-6509), PXI-6509 (pxi-6509), + * PCI-6510 (pci-6510), PCI-6511 (pci-6511), PXI-6511 (pxi-6511), + * PCI-6512 (pci-6512), PXI-6512 (pxi-6512), PCI-6513 (pci-6513), + * PXI-6513 (pxi-6513), PCI-6514 (pci-6514), PXI-6514 (pxi-6514), + * PCI-6515 (pxi-6515), PXI-6515 (pxi-6515), PCI-6516 (pci-6516), + * PCI-6517 (pci-6517), PCI-6518 (pci-6518), PCI-6519 (pci-6519), + * PCI-6520 (pci-6520), PCI-6521 (pci-6521), PXI-6521 (pxi-6521), + * PCI-6528 (pci-6528), PXI-6528 (pxi-6528) * Updated: Mon, 21 Jul 2014 12:49:58 +0000 * * Configuration Options: not applicable, uses PCI auto config -- cgit v0.10.2 From d292585627c2ef51ee7231b1f7148feea5f2cf48 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:54 +0000 Subject: staging: comedi: ni_at_ao: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 05370a4..9eeaf3c 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -19,8 +19,7 @@ /* * Driver: ni_at_ao * Description: National Instruments AT-AO-6/10 - * Devices: (National Instruments) AT-AO-6 [at-ao-6] - * (National Instruments) AT-AO-10 [at-ao-10] + * Devices: [National Instruments] AT-AO-6 (at-ao-6), AT-AO-10 (at-ao-10) * Status: should work * Author: David A. Schleef * Updated: Sun Dec 26 12:26:28 EST 2004 -- cgit v0.10.2 From d49ebefeeb165873c1b06b9869498bc32a2699dd Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:55 +0000 Subject: staging: comedi: ni_labpc: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 1fbfdb4..59da404 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -17,9 +17,8 @@ /* * Driver: ni_labpc * Description: National Instruments Lab-PC (& compatibles) - * Devices: (National Instruments) Lab-PC-1200 [lab-pc-1200] - * (National Instruments) Lab-PC-1200AI [lab-pc-1200ai] - * (National Instruments) Lab-PC+ [lab-pc+] + * Devices: [National Instruments] Lab-PC-1200 (lab-pc-1200), + * Lab-PC-1200AI (lab-pc-1200ai), Lab-PC+ (lab-pc+) * Author: Frank Mori Hess * Status: works * -- cgit v0.10.2 From 7b8bffe8bc1f4fe1e072d4405da9b530ecd424d1 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:56 +0000 Subject: staging: comedi: ni_labpc_pci: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index 3fc4204..a9f408a 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -17,7 +17,7 @@ /* * Driver: ni_labpc_pci * Description: National Instruments Lab-PC PCI-1200 - * Devices: (National Instruments) PCI-1200 [ni_pci-1200] + * Devices: [National Instruments] PCI-1200 (ni_pci-1200) * Author: Frank Mori Hess * Status: works * -- cgit v0.10.2 From 9ade47ab81f53008af52d25569458e0d02336bb6 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:57 +0000 Subject: staging: comedi: ni_tio: change comedi "driver" comment to "module" This module contains support code for some other comedi drivers, but isn't a comedi driver itself, so doesn't need a comedi "driver" comment. To preserve the details in the original comment, change it into a comedi "module" comment (which I've just invented) by changing the "Driver:" line into a "Module:" line and removing the "Devices:" line. Also reformat it to use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 0525292..c20c51b 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -16,29 +16,28 @@ */ /* -Driver: ni_tio -Description: National Instruments general purpose counters -Devices: -Author: J.P. Mellor , - Herman.Bruyninckx@mech.kuleuven.ac.be, - Wim.Meeussen@mech.kuleuven.ac.be, - Klaas.Gadeyne@mech.kuleuven.ac.be, - Frank Mori Hess -Updated: Thu Nov 16 09:50:32 EST 2006 -Status: works - -This module is not used directly by end-users. Rather, it -is used by other drivers (for example ni_660x and ni_pcimio) -to provide support for NI's general purpose counters. It was -originally based on the counter code from ni_660x.c and -ni_mio_common.c. - -References: -DAQ 660x Register-Level Programmer Manual (NI 370505A-01) -DAQ 6601/6602 User Manual (NI 322137B-01) -340934b.pdf DAQ-STC reference manual + * Module: ni_tio + * Description: National Instruments general purpose counters + * Author: J.P. Mellor , + * Herman.Bruyninckx@mech.kuleuven.ac.be, + * Wim.Meeussen@mech.kuleuven.ac.be, + * Klaas.Gadeyne@mech.kuleuven.ac.be, + * Frank Mori Hess + * Updated: Thu Nov 16 09:50:32 EST 2006 + * Status: works + * + * This module is not used directly by end-users. Rather, it + * is used by other drivers (for example ni_660x and ni_pcimio) + * to provide support for NI's general purpose counters. It was + * originally based on the counter code from ni_660x.c and + * ni_mio_common.c. + * + * References: + * DAQ 660x Register-Level Programmer Manual (NI 370505A-01) + * DAQ 6601/6602 User Manual (NI 322137B-01) + * 340934b.pdf DAQ-STC reference manual + */ -*/ /* TODO: Support use of both banks X and Y -- cgit v0.10.2 From 6bd4fa872e971ce1569a6c012fff7c90f348dfd2 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:58 +0000 Subject: staging: comedi: ni_tiocmd: change comedi "driver" comment to "module" This module contains support code for some other comedi drivers, but isn't a comedi driver itself, so doesn't need a comedi "driver" comment. To preserve the details in the original comment, change it into a comedi "module" comment (which I've just invented) by changing the "Driver:" line into a "Module:" line and removing the "Devices:" line. Also reformat it to use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 6037bec..d36c3ab 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -16,29 +16,28 @@ */ /* -Driver: ni_tiocmd -Description: National Instruments general purpose counters command support -Devices: -Author: J.P. Mellor , - Herman.Bruyninckx@mech.kuleuven.ac.be, - Wim.Meeussen@mech.kuleuven.ac.be, - Klaas.Gadeyne@mech.kuleuven.ac.be, - Frank Mori Hess -Updated: Fri, 11 Apr 2008 12:32:35 +0100 -Status: works - -This module is not used directly by end-users. Rather, it -is used by other drivers (for example ni_660x and ni_pcimio) -to provide command support for NI's general purpose counters. -It was originally split out of ni_tio.c to stop the 'ni_tio' -module depending on the 'mite' module. - -References: -DAQ 660x Register-Level Programmer Manual (NI 370505A-01) -DAQ 6601/6602 User Manual (NI 322137B-01) -340934b.pdf DAQ-STC reference manual + * Module: ni_tiocmd + * Description: National Instruments general purpose counters command support + * Author: J.P. Mellor , + * Herman.Bruyninckx@mech.kuleuven.ac.be, + * Wim.Meeussen@mech.kuleuven.ac.be, + * Klaas.Gadeyne@mech.kuleuven.ac.be, + * Frank Mori Hess + * Updated: Fri, 11 Apr 2008 12:32:35 +0100 + * Status: works + * + * This module is not used directly by end-users. Rather, it + * is used by other drivers (for example ni_660x and ni_pcimio) + * to provide command support for NI's general purpose counters. + * It was originally split out of ni_tio.c to stop the 'ni_tio' + * module depending on the 'mite' module. + * + * References: + * DAQ 660x Register-Level Programmer Manual (NI 370505A-01) + * DAQ 6601/6602 User Manual (NI 322137B-01) + * 340934b.pdf DAQ-STC reference manual + */ -*/ /* TODO: Support use of both banks X and Y -- cgit v0.10.2 From 70193d959968fee89ea98d83b654ae5bdfb157b0 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:54:59 +0000 Subject: staging: comedi: pcl711: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 938aebc..cb7e4c3 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -22,10 +22,8 @@ /* * Driver: pcl711 * Description: Advantech PCL-711 and 711b, ADLink ACL-8112 - * Devices: (Advantech) PCL-711 [pcl711] - * (Advantech) PCL-711B [pcl711b] - * (AdLink) ACL-8112HG [acl8112hg] - * (AdLink) ACL-8112DG [acl8112dg] + * Devices: [Advantech] PCL-711 (pcl711), PCL-711B (pcl711b), + * [ADLink] ACL-8112HG (acl8112hg), ACL-8112DG (acl8112dg) * Author: David A. Schleef * Janne Jalkanen * Eric Bunn -- cgit v0.10.2 From e5350ef27e84164e160f5cfc54702ab479b94dd4 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:00 +0000 Subject: staging: comedi: pcl724: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index fcc4408..74b07e1 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -8,14 +8,10 @@ /* * Driver: pcl724 * Description: Comedi driver for 8255 based ISA DIO boards - * Devices: (Advantech) PCL-724 [pcl724] - * (Advantech) PCL-722 [pcl722] - * (Advantech) PCL-731 [pcl731] - * (ADLink) ACL-7122 [acl7122] - * (ADLink) ACL-7124 [acl7124] - * (ADLink) PET-48DIO [pet48dio] - * (WinSystems) PCM-IO48 [pcmio48] - * (Diamond Systems) ONYX-MM-DIO [onyx-mm-dio] + * Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731), + * [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio), + * [WinSystems] PCM-IO48 (pcmio48), + * [Diamond Systems] ONYX-MM-DIO (onyx-mm-dio) * Author: Michal Dobes * Status: untested * -- cgit v0.10.2 From 7231e901111be7ec30eb09236a674ff82c31f807 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:01 +0000 Subject: staging: comedi: pcl726: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index 86f713f..4079815 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -21,11 +21,8 @@ * Description: Advantech PCL-726 & compatibles * Author: David A. Schleef * Status: untested - * Devices: (Advantech) PCL-726 [pcl726] - * (Advantech) PCL-727 [pcl727] - * (Advantech) PCL-728 [pcl728] - * (ADLink) ACL-6126 [acl6126] - * (ADLink) ACL-6128 [acl6128] + * Devices: [Advantech] PCL-726 (pcl726), PCL-727 (pcl727), PCL-728 (pcl728), + * [ADLink] ACL-6126 (acl6126), ACL-6128 (acl6128) * * Configuration Options: * [0] - IO Base -- cgit v0.10.2 From 835aa9aa5a5306176e216527f95b4500aa27410e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:02 +0000 Subject: staging: comedi: pcl730: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Group boards from the same manufacturer together on the "Devices:" line to avoid repeating the "[Manufacturer]" tag unnecessarily. Also fix a couple of typos in the board names on the "Devices:" line: "p16r16dio" was used twice, but one of them should be "p8r8dio"; "prearl-mm-p" should be "pearl-mm-p". Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index a6c5770..ce958ee 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -7,19 +7,12 @@ /* * Driver: pcl730 * Description: Advantech PCL-730 (& compatibles) - * Devices: (Advantech) PCL-730 [pcl730] - * (ICP) ISO-730 [iso730] - * (Adlink) ACL-7130 [acl7130] - * (Advantech) PCM-3730 [pcm3730] - * (Advantech) PCL-725 [pcl725] - * (ICP) P8R8-DIO [p16r16dio] - * (Adlink) ACL-7225b [acl7225b] - * (ICP) P16R16-DIO [p16r16dio] - * (Advantech) PCL-733 [pcl733] - * (Advantech) PCL-734 [pcl734] - * (Diamond Systems) OPMM-1616-XT [opmm-1616-xt] - * (Diamond Systems) PEARL-MM-P [prearl-mm-p] - * (Diamond Systems) IR104-PBF [ir104-pbf] + * Devices: [Advantech] PCL-730 (pcl730), PCM-3730 (pcm3730), PCL-725 (pcl725), + * PCL-733 (pcl733), PCL-734 (pcl734), + * [ADLink] ACL-7130 (acl7130), ACL-7225b (acl7225b), + * [ICP] ISO-730 (iso730), P8R8-DIO (p8r8dio), P16R16-DIO (p16r16dio), + * [Diamond Systems] OPMM-1616-XT (opmm-1616-xt), PEARL-MM-P (pearl-mm-p), + * IR104-PBF (ir104-pbf), * Author: José Luis Sánchez (jsanchezv@teleline.es) * Status: untested * -- cgit v0.10.2 From f15ceb484abd46ad8e5a1d69c5e68c1d011a943a Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:03 +0000 Subject: staging: comedi: pcmad: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index e3ac8ac..12f94fe 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -19,8 +19,7 @@ /* * Driver: pcmad * Description: Winsystems PCM-A/D12, PCM-A/D16 - * Devices: (Winsystems) PCM-A/D12 [pcmad12] - * (Winsystems) PCM-A/D16 [pcmad16] + * Devices: [Winsystems] PCM-A/D12 (pcmad12), PCM-A/D16 (pcmad16) * Author: ds * Status: untested * -- cgit v0.10.2 From 8d4e620e2db639439d12a16909b33a803187c1e8 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:04 +0000 Subject: staging: comedi: pcmda12: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 59108c0..d86c5e2 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -19,7 +19,7 @@ /* * Driver: pcmda12 * Description: A driver for the Winsystems PCM-D/A-12 - * Devices: (Winsystems) PCM-D/A-12 [pcmda12] + * Devices: [Winsystems] PCM-D/A-12 (pcmda12) * Author: Calin Culianu * Updated: Fri, 13 Jan 2006 12:01:01 -0500 * Status: works -- cgit v0.10.2 From c07e5ede8f00a9a66147f8f461e69828deb3029a Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:05 +0000 Subject: staging: comedi: pcmmio: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index f0059e9..2c0e7ec 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -19,7 +19,7 @@ /* * Driver: pcmmio * Description: A driver for the PCM-MIO multifunction board - * Devices: (Winsystems) PCM-MIO [pcmmio] + * Devices: [Winsystems] PCM-MIO (pcmmio) * Author: Calin Culianu * Updated: Wed, May 16 2007 16:21:10 -0500 * Status: works -- cgit v0.10.2 From daea70e488bd2e2a6df6f1ba7304ed31b4bb79cb Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:06 +0000 Subject: staging: comedi: pcmuio: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 0f5483b..a1641d9 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -19,8 +19,7 @@ /* * Driver: pcmuio * Description: Winsystems PC-104 based 48/96-channel DIO boards. - * Devices: (Winsystems) PCM-UIO48A [pcmuio48] - * (Winsystems) PCM-UIO96A [pcmuio96] + * Devices: [Winsystems] PCM-UIO48A (pcmuio48), PCM-UIO96A (pcmuio96) * Author: Calin Culianu * Updated: Fri, 13 Jan 2006 12:01:01 -0500 * Status: works -- cgit v0.10.2 From 9c3ac117364cc051f198332d9fbb16115db1f303 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:07 +0000 Subject: staging: comedi: rtd520: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 581aa58..06ae436 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -19,10 +19,8 @@ /* * Driver: rtd520 * Description: Real Time Devices PCI4520/DM7520 - * Devices: (Real Time Devices) DM7520HR-1 [DM7520] - * (Real Time Devices) DM7520HR-8 [DM7520] - * (Real Time Devices) PCI4520 [PCI4520] - * (Real Time Devices) PCI4520-8 [PCI4520] + * Devices: [Real Time Devices] DM7520HR-1 (DM7520), DM7520HR-8, + * PCI4520 (PCI4520), PCI4520-8 * Author: Dan Christian * Status: Works. Only tested on DM7520-8. Not SMP safe. * -- cgit v0.10.2 From 9001ea3c838d83147e771d7b7ac4e8e5f5dca547 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:08 +0000 Subject: staging: comedi: rti800: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index 67b4b37..340ac77 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -19,8 +19,7 @@ /* * Driver: rti800 * Description: Analog Devices RTI-800/815 - * Devices: (Analog Devices) RTI-800 [rti800] - * (Analog Devices) RTI-815 [rti815] + * Devices: [Analog Devices] RTI-800 (rti800), RTI-815 (rti815) * Author: David A. Schleef * Status: unknown * Updated: Fri, 05 Sep 2008 14:50:44 +0100 -- cgit v0.10.2 From 36847203fe2569a1746efa1fa3188f870fd5ce80 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:09 +0000 Subject: staging: comedi: rti802: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 96c3974..6db58fc 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -20,7 +20,7 @@ * Driver: rti802 * Description: Analog Devices RTI-802 * Author: Anders Blomdell - * Devices: (Analog Devices) RTI-802 [rti802] + * Devices: [Analog Devices] RTI-802 (rti802) * Status: works * * Configuration Options: -- cgit v0.10.2 From f79e1d3c43632f2d6e60f393aa3c659f7499ab58 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:10 +0000 Subject: staging: comedi: usbdux: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 4737dbf..0683d6a 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -16,10 +16,11 @@ /* * Driver: usbdux * Description: University of Stirling USB DAQ & INCITE Technology Limited - * Devices: (ITL) USB-DUX [usbdux] + * Devices: [ITL] USB-DUX (usbdux) * Author: Bernd Porr * Updated: 10 Oct 2014 * Status: Stable + * * Connection scheme for the counter at the digital port: * 0=/CLK0, 1=UP/DOWN0, 2=RESET0, 4=/CLK1, 5=UP/DOWN1, 6=RESET1. * The sampling rate of the counter is approximately 500Hz. -- cgit v0.10.2 From 504a1aa71b6a36bcf1eb7e8a060175a06126fc78 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:11 +0000 Subject: staging: comedi: usbduxfast: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Also change "USB-DUX" to "USB-DUX-FAST" to distinguish it from the other USB-DUX models. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index ddc4cb9..85071da 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -15,7 +15,7 @@ /* * Driver: usbduxfast * Description: University of Stirling USB DAQ & INCITE Technology Limited - * Devices: (ITL) USB-DUX [usbduxfast] + * Devices: [ITL] USB-DUX-FAST (usbduxfast) * Author: Bernd Porr * Updated: 10 Oct 2014 * Status: stable -- cgit v0.10.2 From 2d3c50bb0e80a10515a0e40d59f8c34fa5c2f0c9 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:12 +0000 Subject: staging: comedi: usbduxsigma: rewrite "Devices:" line Rewrite the "Devices:" line in the comedi "driver" comment to conform to the usual comedi format for this line. The line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Also change "USB-DUX" to "USB-DUX-SIGMA" to distinguish it from the other USB-DUX models. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index dc19435..17e5a81 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -16,7 +16,7 @@ /* * Driver: usbduxsigma * Description: University of Stirling USB DAQ & INCITE Technology Limited - * Devices: (ITL) USB-DUX [usbduxsigma] + * Devices: [ITL] USB-DUX-SIGMA (usbduxsigma) * Author: Bernd Porr * Updated: 10 Oct 2014 * Status: stable -- cgit v0.10.2 From b1ad96846bc08ded159dfd9700727c225abb9c04 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 5 Jan 2015 17:55:13 +0000 Subject: staging: comedi: vm80xx: rewrite comedi driver comment block Rewrite the comedi "driver" comment block to conform to the usual format for comedi driver comment blocks and reformat it to use the usual block comment style. In particular, the "Devices:" line should be a comma-separated list where the first item is in the following format: [Manufacturer] BOARD-NAME (comedi-board-name) The "[Manufacturer]" and/or "(comedi-board-name)" parts may be omitted from following items, in which case the parts from the preceding item are used. The "Devices:" line may be continued continued over several lines by using one or more spaces at the start of each continuation line (not counting the space after the "*" in the block comment). Note that the comedi board names I've added to the "Devices:" line don't quite match the board names reported by the driver itself, as they contain parentheses and I don't want nested parentheses on the "Devices:" line (mostly because it confuses a script I use to extract supported devices from the driver comments). Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index a19a56e..5312e0f 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -18,21 +18,22 @@ GNU General Public License for more details. */ /* -Driver: vmk80xx -Description: Velleman USB Board Low-Level Driver -Devices: K8055/K8061 aka VM110/VM140 -Author: Manuel Gebele -Updated: Sun, 10 May 2009 11:14:59 +0200 -Status: works - -Supports: - - analog input - - analog output - - digital input - - digital output - - counter - - pwm -*/ + * Driver: vmk80xx + * Description: Velleman USB Board Low-Level Driver + * Devices: [Velleman] K8055 (K8055/VM110), K8061 (K8061/VM140), + * VM110 (K8055/VM110), VM140 (K8061/VM140) + * Author: Manuel Gebele + * Updated: Sun, 10 May 2009 11:14:59 +0200 + * Status: works + * + * Supports: + * - analog input + * - analog output + * - digital input + * - digital output + * - counter + * - pwm + */ #include #include -- cgit v0.10.2 From 3b78602f7dfdb187c62923213f19c7e39f300d70 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 7 Jan 2015 17:19:26 -0700 Subject: staging: comedi: aio_iiro_16: fix subdevice 0 'type' Subdevice 0 is a digial output not a digital I/O subdevice. Fix the type and, for aesthetics, rename the (*insn_bits) function used to set the outputs. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 7b5ed43..87d1372 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -39,10 +39,10 @@ Configuration Options: #define AIO_IIRO_16_RELAY_8_15 0x04 #define AIO_IIRO_16_INPUT_8_15 0x05 -static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int aio_iiro_16_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { if (comedi_dio_update_state(s, data)) { outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7); @@ -82,12 +82,12 @@ static int aio_iiro_16_attach(struct comedi_device *dev, return ret; s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DIO; + s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = aio_iiro_16_dio_insn_bits_write; + s->insn_bits = aio_iiro_16_do_insn_bits; s = &dev->subdevices[1]; s->type = COMEDI_SUBD_DIO; -- cgit v0.10.2 From aba97d74034d73d2e1c63cd5da73a51d014c092e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 7 Jan 2015 17:19:27 -0700 Subject: staging: comedi: aio_iiro_16: fix subdevice 1 'type' Subdevice 1 is a digial input not a digital I/O subdevice. Fix the type and, for aesthetics, rename the (*insn_bits) function used to read the inputs. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 87d1372..2cfbb61 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -55,10 +55,10 @@ static int aio_iiro_16_do_insn_bits(struct comedi_device *dev, return insn->n; } -static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) +static int aio_iiro_16_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { data[1] = 0; data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_0_7); @@ -90,12 +90,12 @@ static int aio_iiro_16_attach(struct comedi_device *dev, s->insn_bits = aio_iiro_16_do_insn_bits; s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DIO; + s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = aio_iiro_16_dio_insn_bits_read; + s->insn_bits = aio_iiro_16_di_insn_bits; return 0; } -- cgit v0.10.2 From 0f0d2b1ba105e2f64f053f1d87fff60dde92f590 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 7 Jan 2015 17:19:28 -0700 Subject: staging: comedi: aio_iiro_16: tidy up subdevice init For aesthetics, add some white space to the subdevice initialization. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 2cfbb61..3637269 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -81,21 +81,23 @@ static int aio_iiro_16_attach(struct comedi_device *dev, if (ret) return ret; + /* Digital Output subdevice */ s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = aio_iiro_16_do_insn_bits; - + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = aio_iiro_16_do_insn_bits; + + /* Digital Input subdevice */ s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = aio_iiro_16_di_insn_bits; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = aio_iiro_16_di_insn_bits; return 0; } -- cgit v0.10.2 From 9cdb432c6d64e967a03513de258273d01b8b1852 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 7 Jan 2015 17:19:29 -0700 Subject: staging: comedi: aio_iiro_16: tidy up multi-line comments Tidy up the multi-line comments to follow the kernel CodingStyle. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 3637269..96ea174 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -1,34 +1,29 @@ /* - - comedi/drivers/aio_iiro_16.c - - Driver for Access I/O Products PC-104 AIO-IIRO-16 Digital I/O board - Copyright (C) 2006 C&C Technologies, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * aio_iiro_16.c + * Comedi driver for Access I/O Products 104-IIRO-16 board + * Copyright (C) 2006 C&C Technologies, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ /* - -Driver: aio_iiro_16 -Description: Access I/O Products PC-104 IIRO16 Relay And Isolated Input Board -Author: Zachary Ware -Devices: - [Access I/O] PC-104 AIO12-8 -Status: experimental - -Configuration Options: - [0] - I/O port base address - -*/ + * Driver: aio_iiro_16 + * Description: Access I/O Products PC/104 Isolated Input/Relay Output Board + * Author: Zachary Ware + * Devices: [Access I/O] 104-IIRO-16 (aio_iiro_16) + * Status: experimental + * + * Configuration Options: + * [0] - I/O port base address + */ #include #include "../comedidev.h" -- cgit v0.10.2 From 21f1801fcbb970ed46ad4cd90585cec3b69e23cc Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 7 Jan 2015 17:19:30 -0700 Subject: staging: comedi: aio_iiro_16: read intial state of the digital outputs The relay registers are readable. Read them during the attach to get the initial state of the digital outputs. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 96ea174..8cd5f11 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -85,6 +85,10 @@ static int aio_iiro_16_attach(struct comedi_device *dev, s->range_table = &range_digital; s->insn_bits = aio_iiro_16_do_insn_bits; + /* get the initial state of the relays */ + s->state = inb(dev->iobase + AIO_IIRO_16_RELAY_0_7) | + (inb(dev->iobase + AIO_IIRO_16_RELAY_8_15) << 8); + /* Digital Input subdevice */ s = &dev->subdevices[1]; s->type = COMEDI_SUBD_DI; -- cgit v0.10.2 From ffe1cb9a3ed83c753183015b31dfb6fc148403f7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 7 Jan 2015 17:19:31 -0700 Subject: staging: comedi: aio_iiro_16: introduce aio_iiro_enable_irq() This board supports interrupts on change of state of the digital inputs. Introduce a helper function to enable/disable the interrupt. Use the new helper function to ensure that interrupts are initially disabled during the driver (*attach). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 8cd5f11..f84fb74 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -34,6 +34,14 @@ #define AIO_IIRO_16_RELAY_8_15 0x04 #define AIO_IIRO_16_INPUT_8_15 0x05 +static void aio_iiro_enable_irq(struct comedi_device *dev, bool enable) +{ + if (enable) + inb(dev->iobase + AIO_IIRO_16_IRQ); + else + outb(0, dev->iobase + AIO_IIRO_16_IRQ); +} + static int aio_iiro_16_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -72,6 +80,8 @@ static int aio_iiro_16_attach(struct comedi_device *dev, if (ret) return ret; + aio_iiro_enable_irq(dev, false); + ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; -- cgit v0.10.2 From ad7a370c8be47247f68f7187cc82f4f25a347116 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 7 Jan 2015 17:19:32 -0700 Subject: staging: comedi: aio_iiro_16: add command support for change of state detection This board supports interrupts on change of state of the digital inputs. Add the necessary subdevice support and interrupt handler to allow async commands to detect the change of state. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index f84fb74..ae67006 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -23,16 +23,49 @@ * * Configuration Options: * [0] - I/O port base address + * [1] - IRQ (optional) + * + * The board supports interrupts on change of state of the digital inputs. + * The sample data returned by the async command indicates which inputs + * changed state: + * + * Bit 7 - IRQ Enable (1) / Disable (0) + * Bit 1 - Input 8-15 Changed State (1 = Changed, 0 = No Change) + * Bit 0 - Input 0-7 Changed State (1 = Changed, 0 = No Change) */ #include +#include + #include "../comedidev.h" -#define AIO_IIRO_16_RELAY_0_7 0x00 -#define AIO_IIRO_16_INPUT_0_7 0x01 -#define AIO_IIRO_16_IRQ 0x02 -#define AIO_IIRO_16_RELAY_8_15 0x04 -#define AIO_IIRO_16_INPUT_8_15 0x05 +#include "comedi_fc.h" + +#define AIO_IIRO_16_RELAY_0_7 0x00 +#define AIO_IIRO_16_INPUT_0_7 0x01 +#define AIO_IIRO_16_IRQ 0x02 +#define AIO_IIRO_16_RELAY_8_15 0x04 +#define AIO_IIRO_16_INPUT_8_15 0x05 +#define AIO_IIRO_16_STATUS 0x07 +#define AIO_IIRO_16_STATUS_IRQE BIT(7) +#define AIO_IIRO_16_STATUS_INPUT_8_15 BIT(1) +#define AIO_IIRO_16_STATUS_INPUT_0_7 BIT(0) + +static irqreturn_t aio_iiro_16_cos(int irq, void *d) +{ + struct comedi_device *dev = d; + struct comedi_subdevice *s = dev->read_subdev; + unsigned int status; + + status = inb(dev->iobase + AIO_IIRO_16_STATUS); + if (!(status & AIO_IIRO_16_STATUS_IRQE)) + return IRQ_NONE; + + comedi_buf_write_samples(s, &status, 1); + comedi_handle_events(dev, s); + + return IRQ_HANDLED; +} static void aio_iiro_enable_irq(struct comedi_device *dev, bool enable) { @@ -42,6 +75,60 @@ static void aio_iiro_enable_irq(struct comedi_device *dev, bool enable) outb(0, dev->iobase + AIO_IIRO_16_IRQ); } +static int aio_iiro_16_cos_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + aio_iiro_enable_irq(dev, false); + + return 0; +} + +static int aio_iiro_16_cos_cmd(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + aio_iiro_enable_irq(dev, true); + + return 0; +} + +static int aio_iiro_16_cos_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + int err = 0; + + /* Step 1 : check if triggers are trivially valid */ + + err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); + err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); + err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); + err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + + if (err) + return 1; + + /* Step 2a : make sure trigger sources are unique */ + /* Step 2b : and mutually compatible */ + + /* Step 3: check if arguments are trivially valid */ + + err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); + err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); + + if (err) + return 3; + + /* Step 4: fix up any arguments */ + + /* Step 5: check channel list if it exists */ + + return 0; +} + static int aio_iiro_16_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -82,6 +169,17 @@ static int aio_iiro_16_attach(struct comedi_device *dev, aio_iiro_enable_irq(dev, false); + /* + * Digital input change of state interrupts are optionally supported + * using IRQ 2-7, 10-12, 14, or 15. + */ + if ((1 << it->options[1]) & 0xdcfc) { + ret = request_irq(it->options[1], aio_iiro_16_cos, 0, + dev->board_name, dev); + if (ret == 0) + dev->irq = it->options[1]; + } + ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; @@ -107,6 +205,14 @@ static int aio_iiro_16_attach(struct comedi_device *dev, s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = aio_iiro_16_di_insn_bits; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 1; + s->do_cmdtest = aio_iiro_16_cos_cmdtest; + s->do_cmd = aio_iiro_16_cos_cmd; + s->cancel = aio_iiro_16_cos_cancel; + } return 0; } -- cgit v0.10.2 From a52355ee8f9534a52fcf111fbe42b6bde7c622ff Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 7 Jan 2015 17:19:33 -0700 Subject: staging: comedi: aio_iiro_16: update the MODULE_DESCRIPTION Update the MODULE_DESCRIPTION to something more useful than the generic "Comedi low-level driver". Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index ae67006..d8884a3 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -226,5 +226,5 @@ static struct comedi_driver aio_iiro_16_driver = { module_comedi_driver(aio_iiro_16_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Access I/O Products 104-IIRO-16 board"); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From b65ab1242960935f9811c5569fdf8526d0fd33ad Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:36 -0500 Subject: staging: unisys: fix line spacing in visorchipset_umode.h Just get rid of the extra blank lines in this file. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchipset/visorchipset_umode.h b/drivers/staging/unisys/visorchipset/visorchipset_umode.h index 06ba5b7..6cf6eccb 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_umode.h +++ b/drivers/staging/unisys/visorchipset/visorchipset_umode.h @@ -26,8 +26,6 @@ #ifndef __VISORCHIPSET_UMODE_H #define __VISORCHIPSET_UMODE_H - - /** The user-mode program can access the control channel buffer directly * via this memory map. */ -- cgit v0.10.2 From d5d83a16214f35fba4f331d4e3db87759a4b52f8 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:37 -0500 Subject: staging: unisys: fix line spacing in globals.h Get rid of the extra blank lines in globals.h. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchipset/globals.h b/drivers/staging/unisys/visorchipset/globals.h index 0fe1459..a1d35d4 100644 --- a/drivers/staging/unisys/visorchipset/globals.h +++ b/drivers/staging/unisys/visorchipset/globals.h @@ -15,7 +15,6 @@ * details. */ - #ifndef __VISORCHIPSET_GLOBALS_H__ #define __VISORCHIPSET_GLOBALS_H__ @@ -28,7 +27,6 @@ #define MYDRVNAME "visorchipset" - /* module parameters */ extern int visorchipset_testvnic; -- cgit v0.10.2 From 31fb74639ded552f97d0216ae0653cddcb9d0919 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:38 -0500 Subject: staging: unisys: remove testing.h Nobody is using this file so remove it and the reference to it in visorchipset_main.c. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchipset/testing.h b/drivers/staging/unisys/visorchipset/testing.h deleted file mode 100644 index 573aa8b..0000000 --- a/drivers/staging/unisys/visorchipset/testing.h +++ /dev/null @@ -1,43 +0,0 @@ -/* testing.h - * - * Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __VISORCHIPSET_TESTING_H__ -#define __VISORCHIPSET_TESTING_H__ - -#define VISORCHIPSET_TEST_PROC -#include -#include "globals.h" -#include "controlvmchannel.h" - -void test_produce_test_message(struct controlvm_message *msg, - int isLocalTestAddr); -BOOL test_consume_test_message(struct controlvm_message *msg); -void test_manufacture_vnic_client_add(void *p); -void test_manufacture_vnic_client_add_phys(HOSTADDRESS addr); -void test_manufacture_preamble_messages(void); -void test_manufacture_device_attach(ulong busNo, ulong devNo); -void test_manufacture_device_add(ulong busNo, ulong devNo, uuid_le dataTypeGuid, - void *pChannel); -void test_manufacture_add_bus(ulong busNo, ulong maxDevices, - uuid_le id, u8 *name, BOOL isServer); -void test_manufacture_device_destroy(ulong busNo, ulong devNo); -void test_manufacture_bus_destroy(ulong busNo); -void test_manufacture_detach_externalPort(ulong switchNo, ulong externalPortNo); -void test_manufacture_detach_internalPort(ulong switchNo, ulong internalPortNo); -void test_cleanup(void); - -#endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 7e6be32..2651f89 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -20,7 +20,6 @@ #include "procobjecttree.h" #include "visorchannel.h" #include "periodic_work.h" -#include "testing.h" #include "file.h" #include "parser.h" #include "uniklog.h" -- cgit v0.10.2 From de6d15ee0eabf0d092350ae0cbff04dfce3c7217 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:39 -0500 Subject: staging: unisys: get rid of channel stub The functions in channels/* aren't used in a lot of places. In fact, the functions in channel.c can be moved to uislib/uisqueue.c, and the rest of the files in channels can be eliminated. This patch deletes the channels directory and files, removes it from all Kconfigs that referenced them, removes the reference in the Makefile, and moves the functions inside of channels.c to uislib/uisqueue.c. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig index ac080c9..19fcb34 100644 --- a/drivers/staging/unisys/Kconfig +++ b/drivers/staging/unisys/Kconfig @@ -12,7 +12,6 @@ if UNISYSSPAR source "drivers/staging/unisys/visorutil/Kconfig" source "drivers/staging/unisys/visorchannel/Kconfig" source "drivers/staging/unisys/visorchipset/Kconfig" -source "drivers/staging/unisys/channels/Kconfig" source "drivers/staging/unisys/uislib/Kconfig" source "drivers/staging/unisys/virtpci/Kconfig" source "drivers/staging/unisys/virthba/Kconfig" diff --git a/drivers/staging/unisys/Makefile b/drivers/staging/unisys/Makefile index b988d69..68b9925 100644 --- a/drivers/staging/unisys/Makefile +++ b/drivers/staging/unisys/Makefile @@ -4,7 +4,6 @@ obj-$(CONFIG_UNISYS_VISORUTIL) += visorutil/ obj-$(CONFIG_UNISYS_VISORCHANNEL) += visorchannel/ obj-$(CONFIG_UNISYS_VISORCHIPSET) += visorchipset/ -obj-$(CONFIG_UNISYS_CHANNELSTUB) += channels/ obj-$(CONFIG_UNISYS_UISLIB) += uislib/ obj-$(CONFIG_UNISYS_VIRTPCI) += virtpci/ obj-$(CONFIG_UNISYS_VIRTHBA) += virthba/ diff --git a/drivers/staging/unisys/channels/Kconfig b/drivers/staging/unisys/channels/Kconfig deleted file mode 100644 index 179c6ce..0000000 --- a/drivers/staging/unisys/channels/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -# -# Unisys channels configuration -# - -config UNISYS_CHANNELSTUB - tristate "Unisys channelstub driver" - depends on UNISYSSPAR && UNISYS_VISORUTIL - ---help--- - If you say Y here, you will enable the Unisys channels driver. - diff --git a/drivers/staging/unisys/channels/Makefile b/drivers/staging/unisys/channels/Makefile deleted file mode 100644 index adc1842..0000000 --- a/drivers/staging/unisys/channels/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for Unisys channelstub -# - -obj-$(CONFIG_UNISYS_CHANNELSTUB) += visorchannelstub.o - -visorchannelstub-y := channel.o chanstub.o - -ccflags-y += -Idrivers/staging/unisys/include -ccflags-y += -Idrivers/staging/unisys/common-spar/include -ccflags-y += -Idrivers/staging/unisys/common-spar/include/channels diff --git a/drivers/staging/unisys/channels/channel.c b/drivers/staging/unisys/channels/channel.c deleted file mode 100644 index 74cc4d6..0000000 --- a/drivers/staging/unisys/channels/channel.c +++ /dev/null @@ -1,219 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#include -#ifdef CONFIG_MODVERSIONS -#include -#endif -#include -#include /* for module_init and module_exit */ -#include /* for memcpy */ -#include - -/* Implementation of exported functions for Supervisor channels */ -#include "channel.h" - -/* - * Routine Description: - * Tries to insert the prebuilt signal pointed to by pSignal into the nth - * Queue of the Channel pointed to by pChannel - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * pSignal: (IN) pointer to the signal - * - * Assumptions: - * - pChannel, Queue and pSignal are valid. - * - If insertion fails due to a full queue, the caller will determine the - * retry policy (e.g. wait & try again, report an error, etc.). - * - * Return value: - * 1 if the insertion succeeds, 0 if the queue was full. - */ -unsigned char spar_signal_insert(struct channel_header __iomem *ch, u32 queue, - void *sig) -{ - void __iomem *psignal; - unsigned int head, tail, nof; - - struct signal_queue_header __iomem *pqhdr = - (struct signal_queue_header __iomem *) - ((char __iomem *)ch + readq(&ch->ch_space_offset)) - + queue; - - /* capture current head and tail */ - head = readl(&pqhdr->head); - tail = readl(&pqhdr->tail); - - /* queue is full if (head + 1) % n equals tail */ - if (((head + 1) % readl(&pqhdr->max_slots)) == tail) { - nof = readq(&pqhdr->num_overflows) + 1; - writeq(nof, &pqhdr->num_overflows); - return 0; - } - - /* increment the head index */ - head = (head + 1) % readl(&pqhdr->max_slots); - - /* copy signal to the head location from the area pointed to - * by pSignal - */ - psignal = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) + - (head * readl(&pqhdr->signal_size)); - memcpy_toio(psignal, sig, readl(&pqhdr->signal_size)); - - mb(); /* channel synch */ - writel(head, &pqhdr->head); - - writeq(readq(&pqhdr->num_sent) + 1, &pqhdr->num_sent); - return 1; -} -EXPORT_SYMBOL_GPL(spar_signal_insert); - -/* - * Routine Description: - * Removes one signal from Channel pChannel's nth Queue at the - * time of the call and copies it into the memory pointed to by - * pSignal. - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * pSignal: (IN) pointer to where the signals are to be copied - * - * Assumptions: - * - pChannel and Queue are valid. - * - pSignal points to a memory area large enough to hold queue's SignalSize - * - * Return value: - * 1 if the removal succeeds, 0 if the queue was empty. - */ -unsigned char -spar_signal_remove(struct channel_header __iomem *ch, u32 queue, void *sig) -{ - void __iomem *psource; - unsigned int head, tail; - struct signal_queue_header __iomem *pqhdr = - (struct signal_queue_header __iomem *)((char __iomem *)ch + - readq(&ch->ch_space_offset)) + queue; - - /* capture current head and tail */ - head = readl(&pqhdr->head); - tail = readl(&pqhdr->tail); - - /* queue is empty if the head index equals the tail index */ - if (head == tail) { - writeq(readq(&pqhdr->num_empty) + 1, &pqhdr->num_empty); - return 0; - } - - /* advance past the 'empty' front slot */ - tail = (tail + 1) % readl(&pqhdr->max_slots); - - /* copy signal from tail location to the area pointed to by pSignal */ - psource = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) + - (tail * readl(&pqhdr->signal_size)); - memcpy_fromio(sig, psource, readl(&pqhdr->signal_size)); - - mb(); /* channel synch */ - writel(tail, &pqhdr->tail); - - writeq(readq(&pqhdr->num_received) + 1, - &pqhdr->num_received); - return 1; -} -EXPORT_SYMBOL_GPL(spar_signal_remove); - -/* - * Routine Description: - * Removes all signals present in Channel pChannel's nth Queue at the - * time of the call and copies them into the memory pointed to by - * pSignal. Returns the # of signals copied as the value of the routine. - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * pSignal: (IN) pointer to where the signals are to be copied - * - * Assumptions: - * - pChannel and Queue are valid. - * - pSignal points to a memory area large enough to hold Queue's MaxSignals - * # of signals, each of which is Queue's SignalSize. - * - * Return value: - * # of signals copied. - */ -unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue, - void *sig) -{ - void *psource; - unsigned int head, tail, count = 0; - struct signal_queue_header *pqhdr = - (struct signal_queue_header *)((char *)ch + - ch->ch_space_offset) + queue; - - /* capture current head and tail */ - head = pqhdr->head; - tail = pqhdr->tail; - - /* queue is empty if the head index equals the tail index */ - if (head == tail) - return 0; - - while (head != tail) { - /* advance past the 'empty' front slot */ - tail = (tail + 1) % pqhdr->max_slots; - - /* copy signal from tail location to the area pointed - * to by pSignal - */ - psource = - (char *)pqhdr + pqhdr->sig_base_offset + - (tail * pqhdr->signal_size); - memcpy((char *)sig + (pqhdr->signal_size * count), - psource, pqhdr->signal_size); - - mb(); /* channel synch */ - pqhdr->tail = tail; - - count++; - pqhdr->num_received++; - } - - return count; -} - -/* - * Routine Description: - * Determine whether a signal queue is empty. - * - * Parameters: - * pChannel: (IN) points to the IO Channel - * Queue: (IN) nth Queue of the IO Channel - * - * Return value: - * 1 if the signal queue is empty, 0 otherwise. - */ -unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch, - u32 queue) -{ - struct signal_queue_header __iomem *pqhdr = - (struct signal_queue_header __iomem *)((char __iomem *)ch + - readq(&ch->ch_space_offset)) + queue; - return readl(&pqhdr->head) == readl(&pqhdr->tail); -} -EXPORT_SYMBOL_GPL(spar_signalqueue_empty); - diff --git a/drivers/staging/unisys/channels/chanstub.c b/drivers/staging/unisys/channels/chanstub.c deleted file mode 100644 index b6fd126..0000000 --- a/drivers/staging/unisys/channels/chanstub.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#define EXPORT_SYMTAB -#include -#ifdef CONFIG_MODVERSIONS -#include -#endif -#include -#include /* for module_init and module_exit */ -#include /* for memcpy */ -#include - -#include "channel.h" -#include "chanstub.h" -#include "timskmod.h" -#include "version.h" - -static __init int -channel_mod_init(void) -{ - if (!unisys_spar_platform) - return -ENODEV; - return 0; -} - -static __exit void -channel_mod_exit(void) -{ -} - -unsigned char -SignalInsert_withLock(struct channel_header __iomem *pChannel, u32 Queue, - void *pSignal, spinlock_t *lock) -{ - unsigned char result; - unsigned long flags; - - spin_lock_irqsave(lock, flags); - result = spar_signal_insert(pChannel, Queue, pSignal); - spin_unlock_irqrestore(lock, flags); - return result; -} - -unsigned char -SignalRemove_withLock(struct channel_header __iomem *pChannel, u32 Queue, - void *pSignal, spinlock_t *lock) -{ - unsigned char result; - - spin_lock(lock); - result = spar_signal_remove(pChannel, Queue, pSignal); - spin_unlock(lock); - return result; -} - -module_init(channel_mod_init); -module_exit(channel_mod_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Bryan Glaudel"); -MODULE_ALIAS("uischan"); - /* this is extracted during depmod and kept in modules.dep */ diff --git a/drivers/staging/unisys/channels/chanstub.h b/drivers/staging/unisys/channels/chanstub.h deleted file mode 100644 index 1531759..0000000 --- a/drivers/staging/unisys/channels/chanstub.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2010 - 2013 UNISYS CORPORATION - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - */ - -#ifndef __CHANSTUB_H__ -#define __CHANSTUB_H__ -unsigned char SignalInsert_withLock(struct channel_header __iomem *pChannel, - u32 Queue, void *pSignal, spinlock_t *lock); -unsigned char SignalRemove_withLock(struct channel_header __iomem *pChannel, - u32 Queue, void *pSignal, spinlock_t *lock); - -#endif diff --git a/drivers/staging/unisys/uislib/Kconfig b/drivers/staging/unisys/uislib/Kconfig index 6b134e2..a712eb8 100644 --- a/drivers/staging/unisys/uislib/Kconfig +++ b/drivers/staging/unisys/uislib/Kconfig @@ -4,7 +4,7 @@ config UNISYS_UISLIB tristate "Unisys uislib driver" - depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_CHANNELSTUB && HAS_IOMEM + depends on UNISYSSPAR && UNISYS_VISORCHIPSET && HAS_IOMEM ---help--- If you say Y here, you will enable the Unisys uislib driver. diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 7c87452..9bcaa0f 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -41,7 +41,6 @@ #include "sparstop.h" #include "visorchipset.h" -#include "chanstub.h" #include "version.h" #include "guestlinuxdebug.h" diff --git a/drivers/staging/unisys/uislib/uisqueue.c b/drivers/staging/unisys/uislib/uisqueue.c index f9f8442..69151e4 100644 --- a/drivers/staging/unisys/uislib/uisqueue.c +++ b/drivers/staging/unisys/uislib/uisqueue.c @@ -21,8 +21,6 @@ #include "uisutils.h" -#include "chanstub.h" - /* this is shorter than using __FILE__ (full path name) in * debug/info/error messages */ #define CURRENT_FILE_PC UISLIB_PC_uisqueue_c @@ -33,6 +31,199 @@ /*****************************************************/ /* Exported functions */ /*****************************************************/ + +/* + * Routine Description: + * Tries to insert the prebuilt signal pointed to by pSignal into the nth + * Queue of the Channel pointed to by pChannel + * + * Parameters: + * pChannel: (IN) points to the IO Channel + * Queue: (IN) nth Queue of the IO Channel + * pSignal: (IN) pointer to the signal + * + * Assumptions: + * - pChannel, Queue and pSignal are valid. + * - If insertion fails due to a full queue, the caller will determine the + * retry policy (e.g. wait & try again, report an error, etc.). + * + * Return value: + * 1 if the insertion succeeds, 0 if the queue was full. + */ +unsigned char spar_signal_insert(struct channel_header __iomem *ch, u32 queue, + void *sig) +{ + void __iomem *psignal; + unsigned int head, tail, nof; + + struct signal_queue_header __iomem *pqhdr = + (struct signal_queue_header __iomem *) + ((char __iomem *)ch + readq(&ch->ch_space_offset)) + + queue; + + /* capture current head and tail */ + head = readl(&pqhdr->head); + tail = readl(&pqhdr->tail); + + /* queue is full if (head + 1) % n equals tail */ + if (((head + 1) % readl(&pqhdr->max_slots)) == tail) { + nof = readq(&pqhdr->num_overflows) + 1; + writeq(nof, &pqhdr->num_overflows); + return 0; + } + + /* increment the head index */ + head = (head + 1) % readl(&pqhdr->max_slots); + + /* copy signal to the head location from the area pointed to + * by pSignal + */ + psignal = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) + + (head * readl(&pqhdr->signal_size)); + memcpy_toio(psignal, sig, readl(&pqhdr->signal_size)); + + mb(); /* channel synch */ + writel(head, &pqhdr->head); + + writeq(readq(&pqhdr->num_sent) + 1, &pqhdr->num_sent); + return 1; +} +EXPORT_SYMBOL_GPL(spar_signal_insert); + +/* + * Routine Description: + * Removes one signal from Channel pChannel's nth Queue at the + * time of the call and copies it into the memory pointed to by + * pSignal. + * + * Parameters: + * pChannel: (IN) points to the IO Channel + * Queue: (IN) nth Queue of the IO Channel + * pSignal: (IN) pointer to where the signals are to be copied + * + * Assumptions: + * - pChannel and Queue are valid. + * - pSignal points to a memory area large enough to hold queue's SignalSize + * + * Return value: + * 1 if the removal succeeds, 0 if the queue was empty. + */ +unsigned char +spar_signal_remove(struct channel_header __iomem *ch, u32 queue, void *sig) +{ + void __iomem *psource; + unsigned int head, tail; + struct signal_queue_header __iomem *pqhdr = + (struct signal_queue_header __iomem *)((char __iomem *)ch + + readq(&ch->ch_space_offset)) + queue; + + /* capture current head and tail */ + head = readl(&pqhdr->head); + tail = readl(&pqhdr->tail); + + /* queue is empty if the head index equals the tail index */ + if (head == tail) { + writeq(readq(&pqhdr->num_empty) + 1, &pqhdr->num_empty); + return 0; + } + + /* advance past the 'empty' front slot */ + tail = (tail + 1) % readl(&pqhdr->max_slots); + + /* copy signal from tail location to the area pointed to by pSignal */ + psource = (char __iomem *)pqhdr + readq(&pqhdr->sig_base_offset) + + (tail * readl(&pqhdr->signal_size)); + memcpy_fromio(sig, psource, readl(&pqhdr->signal_size)); + + mb(); /* channel synch */ + writel(tail, &pqhdr->tail); + + writeq(readq(&pqhdr->num_received) + 1, + &pqhdr->num_received); + return 1; +} +EXPORT_SYMBOL_GPL(spar_signal_remove); + +/* + * Routine Description: + * Removes all signals present in Channel pChannel's nth Queue at the + * time of the call and copies them into the memory pointed to by + * pSignal. Returns the # of signals copied as the value of the routine. + * + * Parameters: + * pChannel: (IN) points to the IO Channel + * Queue: (IN) nth Queue of the IO Channel + * pSignal: (IN) pointer to where the signals are to be copied + * + * Assumptions: + * - pChannel and Queue are valid. + * - pSignal points to a memory area large enough to hold Queue's MaxSignals + * # of signals, each of which is Queue's SignalSize. + * + * Return value: + * # of signals copied. + */ +unsigned int spar_signal_remove_all(struct channel_header *ch, u32 queue, + void *sig) +{ + void *psource; + unsigned int head, tail, count = 0; + struct signal_queue_header *pqhdr = + (struct signal_queue_header *)((char *)ch + + ch->ch_space_offset) + queue; + + /* capture current head and tail */ + head = pqhdr->head; + tail = pqhdr->tail; + + /* queue is empty if the head index equals the tail index */ + if (head == tail) + return 0; + + while (head != tail) { + /* advance past the 'empty' front slot */ + tail = (tail + 1) % pqhdr->max_slots; + + /* copy signal from tail location to the area pointed + * to by pSignal + */ + psource = + (char *)pqhdr + pqhdr->sig_base_offset + + (tail * pqhdr->signal_size); + memcpy((char *)sig + (pqhdr->signal_size * count), + psource, pqhdr->signal_size); + + mb(); /* channel synch */ + pqhdr->tail = tail; + + count++; + pqhdr->num_received++; + } + + return count; +} + +/* + * Routine Description: + * Determine whether a signal queue is empty. + * + * Parameters: + * pChannel: (IN) points to the IO Channel + * Queue: (IN) nth Queue of the IO Channel + * + * Return value: + * 1 if the signal queue is empty, 0 otherwise. + */ +unsigned char spar_signalqueue_empty(struct channel_header __iomem *ch, + u32 queue) +{ + struct signal_queue_header __iomem *pqhdr = + (struct signal_queue_header __iomem *)((char __iomem *)ch + + readq(&ch->ch_space_offset)) + queue; + return readl(&pqhdr->head) == readl(&pqhdr->tail); +} +EXPORT_SYMBOL_GPL(spar_signalqueue_empty); + unsigned long long uisqueue_interlocked_or(unsigned long long __iomem *tgt, unsigned long long set) diff --git a/drivers/staging/unisys/virthba/Kconfig b/drivers/staging/unisys/virthba/Kconfig index c0d7986..9af98fc 100644 --- a/drivers/staging/unisys/virthba/Kconfig +++ b/drivers/staging/unisys/virthba/Kconfig @@ -4,7 +4,7 @@ config UNISYS_VIRTHBA tristate "Unisys virthba driver" - depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_CHANNELSTUB && UNISYS_UISLIB && UNISYS_VIRTPCI && SCSI + depends on UNISYSSPAR && UNISYS_VISORCHIPSET && UNISYS_UISLIB && UNISYS_VIRTPCI && SCSI ---help--- If you say Y here, you will enable the Unisys virthba driver. -- cgit v0.10.2 From ce572c96f8f7ebebaa078dd820bacc3e4e8e35e0 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:40 -0500 Subject: staging: unisys: remove unused types from visorchipset.h Delete the following unused types, and unused function prototypes: VISORCHIPSET_SWITCH_INFO VISORCHIPSET_EXTERNALPORT_INFO VISORCHIPSET_INTERNALPORT_INFO visorchipset_get_switch_info() visorchipset_get_externalport_info() Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index 46dad63..98f3ba4 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -158,61 +158,6 @@ findbus(struct list_head *list, u32 bus_no) return NULL; } -/** Attributes for a particular Supervisor switch. - */ -struct visorchipset_switch_info { - u32 switch_no; - struct visorchipset_state state; - uuid_le switch_type_uuid; - u8 *authservice1; - u8 *authservice2; - u8 *authservice3; - u8 *security_context; - u64 reserved; - u32 reserved2; /* control_vm_id */ - struct device dev; - BOOL dev_exists; - struct controlvm_message_header pending_msg_hdr; -}; - -/** Attributes for a particular Supervisor external port, which is connected - * to a specific switch. - */ -struct visorchipset_externalport_info { - u32 switch_no; - u32 external_port_no; - struct visorchipset_state state; - uuid_le network_zone_uuid; - int pd_port; - u8 *ip; - u8 *ip_netmask; - u8 *ip_broadcast; - u8 *ip_network; - u8 *ip_gateway; - u8 *ip_dns; - u64 reserved1; - u32 reserved2; /* control_vm_id */ - struct device dev; - BOOL dev_exists; - struct controlvm_message_header pending_msg_hdr; -}; - -/** Attributes for a particular Supervisor internal port, which is how a - * device connects to a particular switch. - */ -struct visorchipset_internalport_info { - u32 switch_no; - u32 internal_port_no; - struct visorchipset_state state; - u32 bus_no; /* valid only when state.attached == 1 */ - u32 dev_no; /* valid only when state.attached == 1 */ - u64 reserved1; - u32 reserved2; /* CONTROLVM_ID */ - struct controlvm_message_header pending_msg_hdr; - MYPROCOBJECT *proc_object; - -}; - /* These functions will be called from within visorchipset when certain * events happen. (The implementation of these functions is outside of * visorchipset.) -- cgit v0.10.2 From b0231f396e12a1c61c3f68538cab4dc67412b9bd Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:41 -0500 Subject: staging: unisys: add comment to spinlock in struct charqueue Add a comment to the charqueue's spinlock to explain that it is a lock for the structure. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorutil/charqueue.c b/drivers/staging/unisys/visorutil/charqueue.c index 1ce7003..ac7acb7 100644 --- a/drivers/staging/unisys/visorutil/charqueue.c +++ b/drivers/staging/unisys/visorutil/charqueue.c @@ -28,7 +28,7 @@ struct charqueue { int alloc_size; int nslots; - spinlock_t lock; + spinlock_t lock; /* read/write lock for this structure */ int head, tail; unsigned char buf[0]; }; -- cgit v0.10.2 From b41b1ad5abaa1247c548ffd726539eece12c46ac Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:42 -0500 Subject: staging: unisys: clean up typecasts in uislib.c Remove all extraneous spaces from typecasts in uislib.c. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 9bcaa0f..c28d6f3 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -136,8 +136,8 @@ init_vbus_channel(u64 channelAddr, u32 channelBytes) if (!pChan) { LOGERR("CONTROLVM_BUS_CREATE error: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed", - (unsigned long long) channelAddr, - (unsigned long long) channelBytes); + (unsigned long long)channelAddr, + (unsigned long long)channelBytes); rc = NULL; goto Away; } @@ -194,10 +194,10 @@ create_bus(struct controlvm_message *msg, char *buf) bus->local_vnic = 1; } else bus->bus_no = bus->guest_handle = busNo; - sprintf(bus->name, "%d", (int) bus->bus_no); + sprintf(bus->name, "%d", (int)bus->bus_no); bus->device_count = deviceCount; bus->device = - (struct device_info **) ((char *) bus + sizeof(struct bus_info)); + (struct device_info **)((char *)bus + sizeof(struct bus_info)); bus->bus_inst_uuid = msg->cmd.create_bus.bus_inst_uuid; bus->bus_channel_bytes = 0; bus->bus_channel = NULL; @@ -373,7 +373,7 @@ create_device(struct controlvm_message *msg, char *buf) dev->bus_no = busNo; dev->dev_no = devNo; sema_init(&dev->interrupt_callback_lock, 1); /* unlocked */ - sprintf(dev->devid, "vbus%u:dev%u", (unsigned) busNo, (unsigned) devNo); + sprintf(dev->devid, "vbus%u:dev%u", (unsigned)busNo, (unsigned)devNo); /* map the channel memory for the device. */ if (msg->hdr.flags.test_message) dev->chanptr = (void __iomem *)__va(dev->channel_addr); @@ -955,7 +955,7 @@ uislib_client_inject_add_vhba(u32 bus_no, u32 dev_no, msg.cmd.create_device.channel_addr = phys_chan_addr; if (chan_bytes < MIN_IO_CHANNEL_SIZE) { LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n", - chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE); + chan_bytes, (unsigned int)MIN_IO_CHANNEL_SIZE); POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, chan_bytes, MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR); return 0; @@ -1014,7 +1014,7 @@ uislib_client_inject_add_vnic(u32 bus_no, u32 dev_no, msg.cmd.create_device.channel_addr = phys_chan_addr; if (chan_bytes < MIN_IO_CHANNEL_SIZE) { LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n", - chan_bytes, (unsigned int) MIN_IO_CHANNEL_SIZE); + chan_bytes, (unsigned int)MIN_IO_CHANNEL_SIZE); POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, chan_bytes, MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR); return 0; @@ -1225,14 +1225,14 @@ find_dev(u32 busNo, u32 devNo) if (devNo >= bus->device_count) { LOGERR("%s bad busNo, devNo=%d,%d", __func__, - (int) (busNo), (int) (devNo)); + (int)(busNo), (int)(devNo)); goto Away; } dev = bus->device[devNo]; if (!dev) LOGERR("%s bad busNo, devNo=%d,%d", __func__, - (int) (busNo), (int) (devNo)); + (int)(busNo), (int)(devNo)); goto Away; } } @@ -1396,8 +1396,8 @@ uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no, dev = find_dev(bus_no, dev_no); if (!dev) { - LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (bus_no), - (int) (dev_no)); + LOGERR("%s busNo=%d, devNo=%d", __func__, (int)(bus_no), + (int)(dev_no)); return; } down(&Lock_Polling_Device_Channels); @@ -1421,8 +1421,8 @@ uislib_disable_channel_interrupts(u32 bus_no, u32 dev_no) dev = find_dev(bus_no, dev_no); if (!dev) { - LOGERR("%s busNo=%d, devNo=%d", __func__, (int) (bus_no), - (int) (dev_no)); + LOGERR("%s busNo=%d, devNo=%d", __func__, (int)(bus_no), + (int)(dev_no)); return; } down(&Lock_Polling_Device_Channels); @@ -1478,21 +1478,21 @@ uislib_mod_init(void) LOGINF("MONITORAPIS"); LOGINF("sizeof(struct uiscmdrsp):%lu bytes\n", - (ulong) sizeof(struct uiscmdrsp)); + (ulong)sizeof(struct uiscmdrsp)); LOGINF("sizeof(struct phys_info):%lu\n", - (ulong) sizeof(struct phys_info)); + (ulong)sizeof(struct phys_info)); LOGINF("sizeof(uiscmdrsp_scsi):%lu\n", - (ulong) sizeof(struct uiscmdrsp_scsi)); + (ulong)sizeof(struct uiscmdrsp_scsi)); LOGINF("sizeof(uiscmdrsp_net):%lu\n", - (ulong) sizeof(struct uiscmdrsp_net)); + (ulong)sizeof(struct uiscmdrsp_net)); LOGINF("sizeof(CONTROLVM_MESSAGE):%lu bytes\n", - (ulong) sizeof(struct controlvm_message)); + (ulong)sizeof(struct controlvm_message)); LOGINF("sizeof(struct spar_controlvm_channel_protocol):%lu bytes\n", - (ulong) sizeof(struct spar_controlvm_channel_protocol)); + (ulong)sizeof(struct spar_controlvm_channel_protocol)); LOGINF("sizeof(CHANNEL_HEADER):%lu bytes\n", - (ulong) sizeof(struct channel_header)); + (ulong)sizeof(struct channel_header)); LOGINF("sizeof(struct spar_io_channel_protocol):%lu bytes\n", - (ulong) sizeof(struct spar_io_channel_protocol)); + (ulong)sizeof(struct spar_io_channel_protocol)); LOGINF("SIZEOF_CMDRSP:%lu bytes\n", SIZEOF_CMDRSP); LOGINF("SIZEOF_PROTOCOL:%lu bytes\n", SIZEOF_PROTOCOL); -- cgit v0.10.2 From dddfe8e652bfae1bddb1626735bcb9714019c8d9 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:43 -0500 Subject: staging: unisys: fix alignment in uislib.c Fix almost all of the parenthesis alignment problems in uislib.c. The 2 remaining issues are in create_device(), which is heavily indented and needs to be refactored entirely anyway. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index c28d6f3..f25dd2f 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -114,7 +114,7 @@ static unsigned long long cycles_before_wait, wait_cycles; /*****************************************************/ static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset); + size_t len, loff_t *offset); static const struct file_operations debugfs_info_fops = { .read = info_debugfs_read, }; @@ -136,8 +136,8 @@ init_vbus_channel(u64 channelAddr, u32 channelBytes) if (!pChan) { LOGERR("CONTROLVM_BUS_CREATE error: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed", - (unsigned long long)channelAddr, - (unsigned long long)channelBytes); + (unsigned long long)channelAddr, + (unsigned long long)channelBytes); rc = NULL; goto Away; } @@ -161,7 +161,7 @@ create_bus(struct controlvm_message *msg, char *buf) if (MaxBusCount == BusListCount) { LOGERR("CONTROLVM_BUS_CREATE Failed: max buses:%d already created\n", - MaxBusCount); + MaxBusCount); POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, MaxBusCount, POSTCODE_SEVERITY_ERR); return CONTROLVM_RESP_ERROR_MAX_BUSES; @@ -301,7 +301,7 @@ destroy_bus(struct controlvm_message *msg, char *buf) for (i = 0; i < bus->device_count; i++) { if (bus->device[i] != NULL) { LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.", - i, busNo); + i, busNo); read_unlock(&BusListLock); return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED; } @@ -386,8 +386,8 @@ create_device(struct controlvm_message *msg, char *buf) minSize = pReqHandler->min_channel_bytes; if (minSize > msg->cmd.create_device.channel_bytes) { LOGERR("CONTROLVM_DEVICE_CREATE Failed: channel size is too small, channel size:0x%lx, required size:0x%lx", - (ulong) msg->cmd.create_device.channel_bytes, - (ulong) minSize); + (ulong) msg->cmd.create_device.channel_bytes, + (ulong) minSize); POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, POSTCODE_SEVERITY_ERR); result = CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL; @@ -398,8 +398,8 @@ create_device(struct controlvm_message *msg, char *buf) msg->cmd.create_device.channel_bytes); if (!dev->chanptr) { LOGERR("CONTROLVM_DEVICE_CREATE Failed: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed", - dev->channel_addr, - msg->cmd.create_device.channel_bytes); + dev->channel_addr, + msg->cmd.create_device.channel_bytes); result = CONTROLVM_RESP_ERROR_IOREMAP_FAILED; POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, POSTCODE_SEVERITY_ERR); @@ -415,7 +415,7 @@ create_device(struct controlvm_message *msg, char *buf) /* make sure the device number is valid */ if (devNo >= bus->device_count) { LOGERR("CONTROLVM_DEVICE_CREATE Failed: device (%d) >= deviceCount (%d).", - devNo, bus->device_count); + devNo, bus->device_count); result = CONTROLVM_RESP_ERROR_MAX_DEVICES; POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, @@ -426,7 +426,7 @@ create_device(struct controlvm_message *msg, char *buf) /* make sure this device is not already set */ if (bus->device[devNo]) { LOGERR("CONTROLVM_DEVICE_CREATE Failed: device %d is already exists.", - devNo); + devNo); POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, POSTCODE_SEVERITY_ERR); @@ -442,7 +442,7 @@ create_device(struct controlvm_message *msg, char *buf) struct guest_msgs cmd; if (!uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid)) { + spar_vhba_channel_protocol_uuid)) { wait_for_valid_guid(&(( struct channel_header __iomem *) (dev-> @@ -451,7 +451,7 @@ create_device(struct controlvm_message *msg, char *buf) if (!SPAR_VHBA_CHANNEL_OK_CLIENT (dev->chanptr)) { LOGERR("CONTROLVM_DEVICE_CREATE Failed:[CLIENT]VHBA dev %d chan invalid.", - devNo); + devNo); POSTCODE_LINUX_4 (DEVICE_CREATE_FAILURE_PC, devNo, busNo, @@ -477,7 +477,7 @@ create_device(struct controlvm_message *msg, char *buf) if (!SPAR_VNIC_CHANNEL_OK_CLIENT (dev->chanptr)) { LOGERR("CONTROLVM_DEVICE_CREATE Failed: VNIC[CLIENT] dev %d chan invalid.", - devNo); + devNo); POSTCODE_LINUX_4 (DEVICE_CREATE_FAILURE_PC, devNo, busNo, @@ -560,14 +560,14 @@ pause_device(struct controlvm_message *msg) /* make sure the device number is valid */ if (devNo >= bus->device_count) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device(%d) >= deviceCount(%d).", - devNo, bus->device_count); + devNo, bus->device_count); retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID; } else { /* make sure this device exists */ dev = bus->device[devNo]; if (!dev) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device %d does not exist.", - devNo); + devNo); retval = CONTROLVM_RESP_ERROR_ALREADY_DONE; } @@ -577,7 +577,7 @@ pause_device(struct controlvm_message *msg) } if (!bus) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: bus %d does not exist", - busNo); + busNo); retval = CONTROLVM_RESP_ERROR_BUS_INVALID; } read_unlock(&BusListLock); @@ -586,7 +586,7 @@ pause_device(struct controlvm_message *msg) * guest_msgs struct to callback */ if (!uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid)) { + spar_vhba_channel_protocol_uuid)) { cmd.msgtype = GUEST_PAUSE_VHBA; cmd.pause_vhba.chanptr = dev->chanptr; } else if (!uuid_le_cmp(dev->channel_uuid, @@ -628,14 +628,14 @@ resume_device(struct controlvm_message *msg) /* make sure the device number is valid */ if (devNo >= bus->device_count) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device(%d) >= deviceCount(%d).", - devNo, bus->device_count); + devNo, bus->device_count); retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID; } else { /* make sure this device exists */ dev = bus->device[devNo]; if (!dev) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device %d does not exist.", - devNo); + devNo); retval = CONTROLVM_RESP_ERROR_ALREADY_DONE; } @@ -646,7 +646,7 @@ resume_device(struct controlvm_message *msg) if (!bus) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: bus %d does not exist", - busNo); + busNo); retval = CONTROLVM_RESP_ERROR_BUS_INVALID; } read_unlock(&BusListLock); @@ -955,7 +955,7 @@ uislib_client_inject_add_vhba(u32 bus_no, u32 dev_no, msg.cmd.create_device.channel_addr = phys_chan_addr; if (chan_bytes < MIN_IO_CHANNEL_SIZE) { LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n", - chan_bytes, (unsigned int)MIN_IO_CHANNEL_SIZE); + chan_bytes, (unsigned int)MIN_IO_CHANNEL_SIZE); POSTCODE_LINUX_4(VHBA_CREATE_FAILURE_PC, chan_bytes, MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR); return 0; @@ -1014,7 +1014,7 @@ uislib_client_inject_add_vnic(u32 bus_no, u32 dev_no, msg.cmd.create_device.channel_addr = phys_chan_addr; if (chan_bytes < MIN_IO_CHANNEL_SIZE) { LOGERR("wrong channel size.chan_bytes = 0x%x IO_CHANNEL_SIZE= 0x%x\n", - chan_bytes, (unsigned int)MIN_IO_CHANNEL_SIZE); + chan_bytes, (unsigned int)MIN_IO_CHANNEL_SIZE); POSTCODE_LINUX_4(VNIC_CREATE_FAILURE_PC, chan_bytes, MIN_IO_CHANNEL_SIZE, POSTCODE_SEVERITY_ERR); return 0; @@ -1181,7 +1181,7 @@ err_done: static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset) + size_t len, loff_t *offset) { char *temp; int totalBytes = 0; -- cgit v0.10.2 From 20eca8f096867fdbd890a8c16a05fb0bd9a7ca06 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:44 -0500 Subject: staging: unisys: refactor create_bus() Fix the missing braces and logical continuation problems in create_bus(). Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index f25dd2f..1ddbe78 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -192,8 +192,10 @@ create_bus(struct controlvm_message *msg, char *buf) bus->guest_handle = 0; bus->bus_no = busNo; bus->local_vnic = 1; - } else - bus->bus_no = bus->guest_handle = busNo; + } else { + bus->bus_no = busNo; + bus->guest_handle = busNo; + } sprintf(bus->name, "%d", (int)bus->bus_no); bus->device_count = deviceCount; bus->device = @@ -220,8 +222,8 @@ create_bus(struct controlvm_message *msg, char *buf) kfree(bus); return CONTROLVM_RESP_ERROR_ALREADY_DONE; } - if ((msg->cmd.create_bus.channel_addr != 0) - && (msg->cmd.create_bus.channel_bytes != 0)) { + if ((msg->cmd.create_bus.channel_addr != 0) && + (msg->cmd.create_bus.channel_bytes != 0)) { bus->bus_channel_bytes = msg->cmd.create_bus.channel_bytes; bus->bus_channel = init_vbus_channel(msg->cmd.create_bus.channel_addr, @@ -256,9 +258,9 @@ create_bus(struct controlvm_message *msg, char *buf) /* add bus at the head of our list */ write_lock(&BusListLock); - if (!BusListHead) + if (!BusListHead) { BusListHead = bus; - else { + } else { bus->next = BusListHead; BusListHead = bus; } -- cgit v0.10.2 From c62bddfb6aea7e2fa5ba85f83f71e17e8e681e55 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:45 -0500 Subject: staging: unisys: fix strict checks in create_device() Use the variable name rather than the type, and add a set of missing brackets to the if statement in create_device(). Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 1ddbe78..8a48091 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -361,7 +361,7 @@ create_device(struct controlvm_message *msg, char *buf) POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, devNo, busNo, POSTCODE_SEVERITY_INFO); - dev = kzalloc(sizeof(struct device_info), GFP_ATOMIC); + dev = kzalloc(sizeof(*dev), GFP_ATOMIC); if (!dev) { LOGERR("CONTROLVM_DEVICE_CREATE Failed: kmalloc for dev failed.\n"); POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, @@ -377,9 +377,9 @@ create_device(struct controlvm_message *msg, char *buf) sema_init(&dev->interrupt_callback_lock, 1); /* unlocked */ sprintf(dev->devid, "vbus%u:dev%u", (unsigned)busNo, (unsigned)devNo); /* map the channel memory for the device. */ - if (msg->hdr.flags.test_message) + if (msg->hdr.flags.test_message) { dev->chanptr = (void __iomem *)__va(dev->channel_addr); - else { + } else { pReqHandler = req_handler_find(dev->channel_uuid); if (pReqHandler) /* generic service handler registered for this -- cgit v0.10.2 From d7024e331d3efd038c98afe4b99964222da54835 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:46 -0500 Subject: staging: unisys: remove extraneous blank lines in uislib.c Fix the line spacing errors in uislib.c. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 8a48091..e255f1f 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -875,7 +875,6 @@ uislib_client_inject_add_bus(u32 bus_no, uuid_le inst_uuid, } EXPORT_SYMBOL_GPL(uislib_client_inject_add_bus); - int uislib_client_inject_del_bus(u32 bus_no) { @@ -920,7 +919,6 @@ uislib_client_inject_resume_vhba(u32 bus_no, u32 dev_no) return rc; } return 0; - } EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vhba); @@ -1073,7 +1071,6 @@ uislib_client_inject_resume_vnic(u32 bus_no, u32 dev_no) return -1; } return 0; - } EXPORT_SYMBOL_GPL(uislib_client_inject_resume_vnic); @@ -1132,12 +1129,10 @@ info_debugfs_read_helper(char **buff, int *buff_len) read_lock(&BusListLock); for (bus = BusListHead; bus; bus = bus->next) { - if (PLINE(" bus=0x%p, busNo=%d, deviceCount=%d\n", bus, bus->bus_no, bus->device_count) < 0) goto err_done_unlock; - if (PLINE(" Devices:\n") < 0) goto err_done_unlock; @@ -1322,7 +1317,6 @@ Process_Incoming(void *v) } else dev->last_on_list_cnt++; } - } if (Incoming_ThreadInfo.should_stop) break; @@ -1473,7 +1467,6 @@ EXPORT_SYMBOL_GPL(uislib_force_channel_interrupt); static int __init uislib_mod_init(void) { - if (!unisys_spar_platform) return -ENODEV; -- cgit v0.10.2 From 2dcca2f7d6f03b1ce69113d4228e715ba923b4bf Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:47 -0500 Subject: staging: unisys: add missing brackets in info_debugfs_read() The if statement in info_debugfs_read() needs another set of brackets for the else clause. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index e255f1f..0930919 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -1202,8 +1202,9 @@ info_debugfs_read(struct file *file, char __user *buf, /* if the read fails, then -1 will be returned */ totalBytes = info_debugfs_read_helper(&temp, &remaining_bytes); ProcReadBufferValid = 1; - } else + } else { totalBytes = strlen(ProcReadBuffer); + } return simple_read_from_buffer(buf, len, offset, ProcReadBuffer, totalBytes); -- cgit v0.10.2 From f0b9a0f9e047574cc5a9070319d82627c8ba265c Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:48 -0500 Subject: staging: unisys: add missing brackets in Process_Incoming() Fix the brackets in the else clause in Process_Incoming(). Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 0930919..4d15844 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -1315,8 +1315,9 @@ Process_Incoming(void *v) &List_Polling_Device_Channels))) { new_tail = lelt; dev->moved_to_tail_cnt++; - } else + } else { dev->last_on_list_cnt++; + } } } if (Incoming_ThreadInfo.should_stop) -- cgit v0.10.2 From 2f652e0c836d939248c0058ed2396b23875a490a Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:49 -0500 Subject: staging: unisys: remove extra parens from uislib_enable_channel_interrupts() Get rid of the extra parenthesis in uislib_enable_channel_interrupts(). Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 4d15844..d6151ee 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -1403,7 +1403,7 @@ uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no, dev->interrupt = interrupt; dev->interrupt_context = interrupt_context; dev->polling = TRUE; - list_add_tail(&(dev->list_polling_device_channels), + list_add_tail(&dev->list_polling_device_channels, &List_Polling_Device_Channels); up(&Lock_Polling_Device_Channels); } -- cgit v0.10.2 From 5f1b9e63ef47351cd2d5941456e2cb51ea060cc8 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:50 -0500 Subject: staging: unisys: get rid of doubled assignment in uislib_mod_init() Split the doubled assignment in uislib_mod_init() into two separate assignments. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index d6151ee..0f33ac6 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -1495,7 +1495,8 @@ uislib_mod_init(void) /* initialize global pointers to NULL */ BusListHead = NULL; - BusListCount = MaxBusCount = 0; + BusListCount = 0; + MaxBusCount = 0; rwlock_init(&BusListLock); virt_control_chan_func = NULL; -- cgit v0.10.2 From b98ab24cdfe6817ac6ab4cc30566dde1f88f1589 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:51 -0500 Subject: staging: unisys: fix CamelCase global variable names in uislib.c Fix CamelCase names: ProcReadBufferValid => debug_buf_valid ProcReadBuffer => debug_buf BusListHead => bus_list BusListLock => bus_list_lock BusListCount => bus_list_count MaxBusCount => max_bus_count PhysicalDataChan => phys_data_chan PlatformNumber => platform_no Incoming_ThreadInfo => incoming_ti Incoming_Thread_Started => incoming_started List_Polling_Device_Channels => poll_dev_chan Lock_Polling_Device_Channels => poll_dev_lock Wakeup_Polling_Device_Channels => poll_dev_wake_q Go_Polling_Device_Channels => poll_dev_start Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 0f33ac6..ead0290 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -58,8 +58,8 @@ /* global function pointers that act as callback functions into virtpcimod */ int (*virt_control_chan_func)(struct guest_msgs *); -static int ProcReadBufferValid; -static char *ProcReadBuffer; /* Note this MUST be global, +static int debug_buf_valid; +static char *debug_buf; /* Note this MUST be global, * because the contents must */ static unsigned int chipset_inited; @@ -70,24 +70,24 @@ static unsigned int chipset_inited; UIS_THREAD_WAIT; \ } while (1) -static struct bus_info *BusListHead; -static rwlock_t BusListLock; -static int BusListCount; /* number of buses in the list */ -static int MaxBusCount; /* maximum number of buses expected */ -static u64 PhysicalDataChan; -static int PlatformNumber; +static struct bus_info *bus_list; +static rwlock_t bus_list_lock; +static int bus_list_count; /* number of buses in the list */ +static int max_bus_count; /* maximum number of buses expected */ +static u64 phys_data_chan; +static int platform_no; -static struct uisthread_info Incoming_ThreadInfo; -static BOOL Incoming_Thread_Started = FALSE; -static LIST_HEAD(List_Polling_Device_Channels); +static struct uisthread_info incoming_ti; +static BOOL incoming_started = FALSE; +static LIST_HEAD(poll_dev_chan); static unsigned long long tot_moved_to_tail_cnt; static unsigned long long tot_wait_cnt; static unsigned long long tot_wakeup_cnt; static unsigned long long tot_schedule_cnt; static int en_smart_wakeup = 1; -static DEFINE_SEMAPHORE(Lock_Polling_Device_Channels); /* unlocked */ -static DECLARE_WAIT_QUEUE_HEAD(Wakeup_Polling_Device_Channels); -static int Go_Polling_Device_Channels; +static DEFINE_SEMAPHORE(poll_dev_lock); /* unlocked */ +static DECLARE_WAIT_QUEUE_HEAD(poll_dev_wake_q); +static int poll_dev_start; #define CALLHOME_PROC_ENTRY_FN "callhome" #define CALLHOME_THROTTLED_PROC_ENTRY_FN "callhome_throttled" @@ -159,10 +159,10 @@ create_bus(struct controlvm_message *msg, char *buf) struct bus_info *tmp, *bus; size_t size; - if (MaxBusCount == BusListCount) { + if (max_bus_count == bus_list_count) { LOGERR("CONTROLVM_BUS_CREATE Failed: max buses:%d already created\n", - MaxBusCount); - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, MaxBusCount, + max_bus_count); + POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, max_bus_count, POSTCODE_SEVERITY_ERR); return CONTROLVM_RESP_ERROR_MAX_BUSES; } @@ -205,12 +205,12 @@ create_bus(struct controlvm_message *msg, char *buf) bus->bus_channel = NULL; /* add bus to our bus list - but check for duplicates first */ - read_lock(&BusListLock); - for (tmp = BusListHead; tmp; tmp = tmp->next) { + read_lock(&bus_list_lock); + for (tmp = bus_list; tmp; tmp = tmp->next) { if (tmp->bus_no == bus->bus_no) break; } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); if (tmp) { /* found a bus already in the list with same busNo - * reject add @@ -257,15 +257,15 @@ create_bus(struct controlvm_message *msg, char *buf) } /* add bus at the head of our list */ - write_lock(&BusListLock); - if (!BusListHead) { - BusListHead = bus; + write_lock(&bus_list_lock); + if (!bus_list) { + bus_list = bus; } else { - bus->next = BusListHead; - BusListHead = bus; + bus->next = bus_list; + bus_list = bus; } - BusListCount++; - write_unlock(&BusListLock); + bus_list_count++; + write_unlock(&bus_list_lock); POSTCODE_LINUX_3(BUS_CREATE_EXIT_PC, bus->bus_no, POSTCODE_SEVERITY_INFO); @@ -282,9 +282,9 @@ destroy_bus(struct controlvm_message *msg, char *buf) busNo = msg->cmd.destroy_bus.bus_no; - read_lock(&BusListLock); + read_lock(&bus_list_lock); - bus = BusListHead; + bus = bus_list; while (bus) { if (bus->bus_no == busNo) break; @@ -295,7 +295,7 @@ destroy_bus(struct controlvm_message *msg, char *buf) if (!bus) { LOGERR("CONTROLVM_BUS_DESTROY Failed: failed to find bus %d.\n", busNo); - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); return CONTROLVM_RESP_ERROR_ALREADY_DONE; } @@ -304,11 +304,11 @@ destroy_bus(struct controlvm_message *msg, char *buf) if (bus->device[i] != NULL) { LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.", i, busNo); - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED; } } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); if (msg->hdr.flags.server) goto remove; @@ -328,13 +328,13 @@ destroy_bus(struct controlvm_message *msg, char *buf) /* finally, remove the bus from the list */ remove: - write_lock(&BusListLock); + write_lock(&bus_list_lock); if (prev) /* not at head */ prev->next = bus->next; else - BusListHead = bus->next; - BusListCount--; - write_unlock(&BusListLock); + bus_list = bus->next; + bus_list_count--; + write_unlock(&bus_list_lock); if (bus->bus_channel) { uislib_iounmap(bus->bus_channel); @@ -411,8 +411,8 @@ create_device(struct controlvm_message *msg, char *buf) dev->instance_uuid = msg->cmd.create_device.dev_inst_uuid; dev->channel_bytes = msg->cmd.create_device.channel_bytes; - read_lock(&BusListLock); - for (bus = BusListHead; bus; bus = bus->next) { + read_lock(&bus_list_lock); + for (bus = bus_list; bus; bus = bus->next) { if (bus->bus_no == busNo) { /* make sure the device number is valid */ if (devNo >= bus->device_count) { @@ -422,7 +422,7 @@ create_device(struct controlvm_message *msg, char *buf) POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, POSTCODE_SEVERITY_ERR); - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); goto Away; } /* make sure this device is not already set */ @@ -433,10 +433,10 @@ create_device(struct controlvm_message *msg, char *buf) devNo, busNo, POSTCODE_SEVERITY_ERR); result = CONTROLVM_RESP_ERROR_ALREADY_DONE; - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); goto Away; } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); /* the msg is bound for virtpci; send * guest_msgs struct to callback */ @@ -527,7 +527,7 @@ create_device(struct controlvm_message *msg, char *buf) return CONTROLVM_RESP_SUCCESS; } } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); LOGERR("CONTROLVM_DEVICE_CREATE Failed: failed to find bus %d.", busNo); POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, @@ -556,8 +556,8 @@ pause_device(struct controlvm_message *msg) busNo = msg->cmd.device_change_state.bus_no; devNo = msg->cmd.device_change_state.dev_no; - read_lock(&BusListLock); - for (bus = BusListHead; bus; bus = bus->next) { + read_lock(&bus_list_lock); + for (bus = bus_list; bus; bus = bus->next) { if (bus->bus_no == busNo) { /* make sure the device number is valid */ if (devNo >= bus->device_count) { @@ -582,7 +582,7 @@ pause_device(struct controlvm_message *msg) busNo); retval = CONTROLVM_RESP_ERROR_BUS_INVALID; } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); if (retval == CONTROLVM_RESP_SUCCESS) { /* the msg is bound for virtpci; send * guest_msgs struct to callback @@ -624,8 +624,8 @@ resume_device(struct controlvm_message *msg) busNo = msg->cmd.device_change_state.bus_no; devNo = msg->cmd.device_change_state.dev_no; - read_lock(&BusListLock); - for (bus = BusListHead; bus; bus = bus->next) { + read_lock(&bus_list_lock); + for (bus = bus_list; bus; bus = bus->next) { if (bus->bus_no == busNo) { /* make sure the device number is valid */ if (devNo >= bus->device_count) { @@ -651,7 +651,7 @@ resume_device(struct controlvm_message *msg) busNo); retval = CONTROLVM_RESP_ERROR_BUS_INVALID; } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); /* the msg is bound for virtpci; send * guest_msgs struct to callback */ @@ -693,9 +693,9 @@ destroy_device(struct controlvm_message *msg, char *buf) busNo = msg->cmd.destroy_device.bus_no; devNo = msg->cmd.destroy_device.bus_no; - read_lock(&BusListLock); + read_lock(&bus_list_lock); LOGINF("destroy_device called for busNo=%u, devNo=%u", busNo, devNo); - for (bus = BusListHead; bus; bus = bus->next) { + for (bus = bus_list; bus; bus = bus->next) { if (bus->bus_no == busNo) { /* make sure the device number is valid */ if (devNo >= bus->device_count) { @@ -721,7 +721,7 @@ destroy_device(struct controlvm_message *msg, char *buf) busNo); retval = CONTROLVM_RESP_ERROR_BUS_INVALID; } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); if (retval == CONTROLVM_RESP_SUCCESS) { /* the msg is bound for virtpci; send * guest_msgs struct to callback @@ -774,9 +774,9 @@ init_chipset(struct controlvm_message *msg, char *buf) { POSTCODE_LINUX_2(CHIPSET_INIT_ENTRY_PC, POSTCODE_SEVERITY_INFO); - MaxBusCount = msg->cmd.init_chipset.bus_count; - PlatformNumber = msg->cmd.init_chipset.platform_number; - PhysicalDataChan = 0; + max_bus_count = msg->cmd.init_chipset.bus_count; + platform_no = msg->cmd.init_chipset.platform_number; + phys_data_chan = 0; /* We need to make sure we have our functions registered * before processing messages. If we are a test vehicle the @@ -1127,8 +1127,8 @@ info_debugfs_read_helper(char **buff, int *buff_len) if (PLINE("\nBuses:\n") < 0) goto err_done; - read_lock(&BusListLock); - for (bus = BusListHead; bus; bus = bus->next) { + read_lock(&bus_list_lock); + for (bus = bus_list; bus; bus = bus->next) { if (PLINE(" bus=0x%p, busNo=%d, deviceCount=%d\n", bus, bus->bus_no, bus->device_count) < 0) goto err_done_unlock; @@ -1152,7 +1152,7 @@ info_debugfs_read_helper(char **buff, int *buff_len) } } } - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); if (PLINE("UisUtils_Registered_Services: %d\n", atomic_read(&uisutils_registered_services)) < 0) @@ -1171,7 +1171,7 @@ info_debugfs_read_helper(char **buff, int *buff_len) return tot; err_done_unlock: - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); err_done: return -1; } @@ -1185,29 +1185,29 @@ info_debugfs_read(struct file *file, char __user *buf, int remaining_bytes = PROC_READ_BUFFER_SIZE; /* *start = buf; */ - if (ProcReadBuffer == NULL) { - DBGINF("ProcReadBuffer == NULL; allocating buffer.\n."); - ProcReadBuffer = vmalloc(PROC_READ_BUFFER_SIZE); + if (debug_buf == NULL) { + DBGINF("debug_buf == NULL; allocating buffer.\n."); + debug_buf = vmalloc(PROC_READ_BUFFER_SIZE); - if (ProcReadBuffer == NULL) { + if (debug_buf == NULL) { LOGERR("failed to allocate buffer to provide proc data.\n"); return -ENOMEM; } } - temp = ProcReadBuffer; + temp = debug_buf; - if ((*offset == 0) || (!ProcReadBufferValid)) { + if ((*offset == 0) || (!debug_buf_valid)) { DBGINF("calling info_debugfs_read_helper.\n"); /* if the read fails, then -1 will be returned */ totalBytes = info_debugfs_read_helper(&temp, &remaining_bytes); - ProcReadBufferValid = 1; + debug_buf_valid = 1; } else { - totalBytes = strlen(ProcReadBuffer); + totalBytes = strlen(debug_buf); } return simple_read_from_buffer(buf, len, offset, - ProcReadBuffer, totalBytes); + debug_buf, totalBytes); } static struct device_info * @@ -1216,8 +1216,8 @@ find_dev(u32 busNo, u32 devNo) struct bus_info *bus; struct device_info *dev = NULL; - read_lock(&BusListLock); - for (bus = BusListHead; bus; bus = bus->next) { + read_lock(&bus_list_lock); + for (bus = bus_list; bus; bus = bus->next) { if (bus->bus_no == busNo) { /* make sure the device number is valid */ if (devNo >= bus->device_count) { @@ -1235,7 +1235,7 @@ find_dev(u32 busNo, u32 devNo) } } Away: - read_unlock(&BusListLock); + read_unlock(&bus_list_lock); return dev; } @@ -1269,7 +1269,7 @@ Process_Incoming(void *v) UIS_DAEMONIZE("dev_incoming"); for (i = 0; i < 16; i++) { old_cycles = get_cycles(); - wait_event_timeout(Wakeup_Polling_Device_Channels, + wait_event_timeout(poll_dev_wake_q, 0, POLLJIFFIES_NORMAL); cur_cycles = get_cycles(); if (wait_cycles == 0) { @@ -1282,15 +1282,15 @@ Process_Incoming(void *v) LOGINF("wait_cycles=%llu", wait_cycles); cycles_before_wait = wait_cycles; idle_cycles = 0; - Go_Polling_Device_Channels = 0; + poll_dev_start = 0; while (1) { struct list_head *lelt, *tmp; struct device_info *dev = NULL; /* poll each channel for input */ - down(&Lock_Polling_Device_Channels); + down(&poll_dev_lock); new_tail = NULL; - list_for_each_safe(lelt, tmp, &List_Polling_Device_Channels) { + list_for_each_safe(lelt, tmp, &poll_dev_chan) { int rc = 0; dev = list_entry(lelt, struct device_info, @@ -1312,7 +1312,7 @@ Process_Incoming(void *v) if (! (list_is_last (lelt, - &List_Polling_Device_Channels))) { + &poll_dev_chan))) { new_tail = lelt; dev->moved_to_tail_cnt++; } else { @@ -1320,14 +1320,14 @@ Process_Incoming(void *v) } } } - if (Incoming_ThreadInfo.should_stop) + if (incoming_ti.should_stop) break; } if (new_tail != NULL) { tot_moved_to_tail_cnt++; - list_move_tail(new_tail, &List_Polling_Device_Channels); + list_move_tail(new_tail, &poll_dev_chan); } - up(&Lock_Polling_Device_Channels); + up(&poll_dev_lock); cur_cycles = get_cycles(); delta_cycles = cur_cycles - old_cycles; old_cycles = cur_cycles; @@ -1337,24 +1337,24 @@ Process_Incoming(void *v) * - there is no input waiting on any of the channels * - we have received a signal to stop this thread */ - if (Incoming_ThreadInfo.should_stop) + if (incoming_ti.should_stop) break; if (en_smart_wakeup == 0xFF) { LOGINF("en_smart_wakeup set to 0xff, to force exiting process_incoming"); break; } /* wait for POLLJIFFIES_NORMAL jiffies, or until - * someone wakes up Wakeup_Polling_Device_Channels, + * someone wakes up poll_dev_wake_q, * whichever comes first only do a wait when we have * been idle for cycles_before_wait cycles. */ if (idle_cycles > cycles_before_wait) { - Go_Polling_Device_Channels = 0; + poll_dev_start = 0; tot_wait_cnt++; - wait_event_timeout(Wakeup_Polling_Device_Channels, - Go_Polling_Device_Channels, + wait_event_timeout(poll_dev_wake_q, + poll_dev_start, POLLJIFFIES_NORMAL); - Go_Polling_Device_Channels = 1; + poll_dev_start = 1; } else { tot_schedule_cnt++; schedule(); @@ -1362,20 +1362,20 @@ Process_Incoming(void *v) } } DBGINF("exiting.\n"); - complete_and_exit(&Incoming_ThreadInfo.has_stopped, 0); + complete_and_exit(&incoming_ti.has_stopped, 0); } static BOOL Initialize_incoming_thread(void) { - if (Incoming_Thread_Started) + if (incoming_started) return TRUE; - if (!uisthread_start(&Incoming_ThreadInfo, + if (!uisthread_start(&incoming_ti, &Process_Incoming, NULL, "dev_incoming")) { LOGERR("uisthread_start Initialize_incoming_thread ****FAILED"); return FALSE; } - Incoming_Thread_Started = TRUE; + incoming_started = TRUE; return TRUE; } @@ -1398,14 +1398,14 @@ uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no, (int)(dev_no)); return; } - down(&Lock_Polling_Device_Channels); + down(&poll_dev_lock); Initialize_incoming_thread(); dev->interrupt = interrupt; dev->interrupt_context = interrupt_context; dev->polling = TRUE; list_add_tail(&dev->list_polling_device_channels, - &List_Polling_Device_Channels); - up(&Lock_Polling_Device_Channels); + &poll_dev_chan); + up(&poll_dev_lock); } EXPORT_SYMBOL_GPL(uislib_enable_channel_interrupts); @@ -1423,20 +1423,20 @@ uislib_disable_channel_interrupts(u32 bus_no, u32 dev_no) (int)(dev_no)); return; } - down(&Lock_Polling_Device_Channels); + down(&poll_dev_lock); list_del(&dev->list_polling_device_channels); dev->polling = FALSE; dev->interrupt = NULL; - up(&Lock_Polling_Device_Channels); + up(&poll_dev_lock); } EXPORT_SYMBOL_GPL(uislib_disable_channel_interrupts); static void do_wakeup_polling_device_channels(struct work_struct *dummy) { - if (!Go_Polling_Device_Channels) { - Go_Polling_Device_Channels = 1; - wake_up(&Wakeup_Polling_Device_Channels); + if (!poll_dev_start) { + poll_dev_start = 1; + wake_up(&poll_dev_wake_q); } } @@ -1451,7 +1451,7 @@ uislib_force_channel_interrupt(u32 bus_no, u32 dev_no) { if (en_smart_wakeup == 0) return; - if (Go_Polling_Device_Channels) + if (poll_dev_start) return; /* The point of using schedule_work() instead of just doing * the work inline is to force a slight delay before waking up @@ -1494,10 +1494,10 @@ uislib_mod_init(void) LOGINF("SIZEOF_PROTOCOL:%lu bytes\n", SIZEOF_PROTOCOL); /* initialize global pointers to NULL */ - BusListHead = NULL; - BusListCount = 0; - MaxBusCount = 0; - rwlock_init(&BusListLock); + bus_list = NULL; + bus_list_count = 0; + max_bus_count = 0; + rwlock_init(&bus_list_lock); virt_control_chan_func = NULL; /* Issue VMCALL_GET_CONTROLVM_ADDR to get CtrlChanPhysAddr and @@ -1512,7 +1512,7 @@ uislib_mod_init(void) platformnumber_debugfs_read = debugfs_create_u32( PLATFORMNUMBER_DEBUGFS_ENTRY_FN, 0444, dir_debugfs, - &PlatformNumber); + &platform_no); cycles_before_wait_debugfs_read = debugfs_create_u64( CYCLES_BEFORE_WAIT_DEBUGFS_ENTRY_FN, 0666, dir_debugfs, @@ -1530,9 +1530,9 @@ uislib_mod_init(void) static void __exit uislib_mod_exit(void) { - if (ProcReadBuffer) { - vfree(ProcReadBuffer); - ProcReadBuffer = NULL; + if (debug_buf) { + vfree(debug_buf); + debug_buf = NULL; } debugfs_remove(info_debugfs_entry); -- cgit v0.10.2 From eb4a1468029bb96ffd74f1047fba699aaa54295c Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:52 -0500 Subject: staging: unisys: refactor init_vbus_channel() Clean up the function definition so it's a single line. Remove the unnecessary goto statements and just return directly. Remove the unneeded local variable for the return result. Fix CamelCase parameters and local variable names: channelAddr => ch_addr channelBytes => ch_bytes pChan => ch Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index ead0290..08416d2 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -128,28 +128,22 @@ init_msg_header(struct controlvm_message *msg, u32 id, uint rsp, uint svr) msg->hdr.flags.server = svr; } -static __iomem void * -init_vbus_channel(u64 channelAddr, u32 channelBytes) +static __iomem void *init_vbus_channel(u64 ch_addr, u32 ch_bytes) { - void __iomem *rc = NULL; - void __iomem *pChan = uislib_ioremap_cache(channelAddr, channelBytes); + void __iomem *ch = uislib_ioremap_cache(ch_addr, ch_bytes); - if (!pChan) { + if (!ch) { LOGERR("CONTROLVM_BUS_CREATE error: ioremap_cache of channelAddr:%Lx for channelBytes:%llu failed", - (unsigned long long)channelAddr, - (unsigned long long)channelBytes); - rc = NULL; - goto Away; + (unsigned long long)ch_addr, + (unsigned long long)ch_bytes); + return NULL; } - if (!SPAR_VBUS_CHANNEL_OK_CLIENT(pChan)) { + if (!SPAR_VBUS_CHANNEL_OK_CLIENT(ch)) { ERRDRV("%s channel cannot be used", __func__); - uislib_iounmap(pChan); - rc = NULL; - goto Away; + uislib_iounmap(ch); + return NULL; } - rc = pChan; -Away: - return rc; + return ch; } static int -- cgit v0.10.2 From d0500864c63ca668dfcd53e40e469690eae593a3 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:53 -0500 Subject: staging: unisys: fix CamelCase in create_bus() Fix CamelCase local variable names: busNo => bus_no deviceCount => dev_count Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 08416d2..9c995c5 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -149,7 +149,7 @@ static __iomem void *init_vbus_channel(u64 ch_addr, u32 ch_bytes) static int create_bus(struct controlvm_message *msg, char *buf) { - u32 busNo, deviceCount; + u32 bus_no, dev_count; struct bus_info *tmp, *bus; size_t size; @@ -161,19 +161,19 @@ create_bus(struct controlvm_message *msg, char *buf) return CONTROLVM_RESP_ERROR_MAX_BUSES; } - busNo = msg->cmd.create_bus.bus_no; - deviceCount = msg->cmd.create_bus.dev_count; + bus_no = msg->cmd.create_bus.bus_no; + dev_count = msg->cmd.create_bus.dev_count; - POSTCODE_LINUX_4(BUS_CREATE_ENTRY_PC, busNo, deviceCount, + POSTCODE_LINUX_4(BUS_CREATE_ENTRY_PC, bus_no, dev_count, POSTCODE_SEVERITY_INFO); size = sizeof(struct bus_info) + - (deviceCount * sizeof(struct device_info *)); + (dev_count * sizeof(struct device_info *)); bus = kzalloc(size, GFP_ATOMIC); if (!bus) { LOGERR("CONTROLVM_BUS_CREATE Failed: kmalloc for bus failed.\n"); - POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, busNo, + POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); return CONTROLVM_RESP_ERROR_KMALLOC_FAILED; } @@ -184,14 +184,14 @@ create_bus(struct controlvm_message *msg, char *buf) if (msg->hdr.flags.test_message) { /* This implies we're the IOVM so set guest handle to 0... */ bus->guest_handle = 0; - bus->bus_no = busNo; + bus->bus_no = bus_no; bus->local_vnic = 1; } else { - bus->bus_no = busNo; - bus->guest_handle = busNo; + bus->bus_no = bus_no; + bus->guest_handle = bus_no; } sprintf(bus->name, "%d", (int)bus->bus_no); - bus->device_count = deviceCount; + bus->device_count = dev_count; bus->device = (struct device_info **)((char *)bus + sizeof(struct bus_info)); bus->bus_inst_uuid = msg->cmd.create_bus.bus_inst_uuid; @@ -206,7 +206,7 @@ create_bus(struct controlvm_message *msg, char *buf) } read_unlock(&bus_list_lock); if (tmp) { - /* found a bus already in the list with same busNo - + /* found a bus already in the list with same bus_no - * reject add */ LOGERR("CONTROLVM_BUS_CREATE Failed: bus %d already exists.\n", @@ -228,9 +228,9 @@ create_bus(struct controlvm_message *msg, char *buf) struct guest_msgs cmd; cmd.msgtype = GUEST_ADD_VBUS; - cmd.add_vbus.bus_no = busNo; + cmd.add_vbus.bus_no = bus_no; cmd.add_vbus.chanptr = bus->bus_channel; - cmd.add_vbus.dev_count = deviceCount; + cmd.add_vbus.dev_count = dev_count; cmd.add_vbus.bus_uuid = msg->cmd.create_bus.bus_data_type_uuid; cmd.add_vbus.instance_uuid = msg->cmd.create_bus.bus_inst_uuid; if (!virt_control_chan_func) { -- cgit v0.10.2 From e6c15b7b1f089700d0c2a664d6442fa97760ad3a Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:54 -0500 Subject: staging: unisys: fix CamelCase in destroy_bus() Fix the CamelCase local variable: busNo => bus_no Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 9c995c5..ab72e81 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -272,15 +272,15 @@ destroy_bus(struct controlvm_message *msg, char *buf) int i; struct bus_info *bus, *prev = NULL; struct guest_msgs cmd; - u32 busNo; + u32 bus_no; - busNo = msg->cmd.destroy_bus.bus_no; + bus_no = msg->cmd.destroy_bus.bus_no; read_lock(&bus_list_lock); bus = bus_list; while (bus) { - if (bus->bus_no == busNo) + if (bus->bus_no == bus_no) break; prev = bus; bus = bus->next; @@ -288,7 +288,7 @@ destroy_bus(struct controlvm_message *msg, char *buf) if (!bus) { LOGERR("CONTROLVM_BUS_DESTROY Failed: failed to find bus %d.\n", - busNo); + bus_no); read_unlock(&bus_list_lock); return CONTROLVM_RESP_ERROR_ALREADY_DONE; } @@ -297,7 +297,7 @@ destroy_bus(struct controlvm_message *msg, char *buf) for (i = 0; i < bus->device_count; i++) { if (bus->device[i] != NULL) { LOGERR("CONTROLVM_BUS_DESTROY Failed: device %i attached to bus %d.", - i, busNo); + i, bus_no); read_unlock(&bus_list_lock); return CONTROLVM_RESP_ERROR_BUS_DEVICE_ATTACHED; } @@ -310,7 +310,7 @@ destroy_bus(struct controlvm_message *msg, char *buf) /* client messages require us to call the virtpci callback associated with this bus. */ cmd.msgtype = GUEST_DEL_VBUS; - cmd.del_vbus.bus_no = busNo; + cmd.del_vbus.bus_no = bus_no; if (!virt_control_chan_func) { LOGERR("CONTROLVM_BUS_DESTROY Failed: virtpci callback not registered."); return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; -- cgit v0.10.2 From 8a05beb1156ac5b1c8dc8c1df9756b279ebe2a22 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:55 -0500 Subject: staging: unisys: refactor create_device() OK, lets clean up this messy function. The entire thing is reflowed so spacing and indentation is correct. Tests that created extra indentation were swapped for equivalent negative tests that did not create extra indentation. Use of cmp_uuid_le() were fixed to test specifically for the zero case, and not to lazily use !cmp_uuid_le(). CamelCase local variable names were fixed: busNo => bus_no devNo => dev_no minSize => min_size pReqHandler => req_handler Away => cleanup Finally, the struct guest_msgs cmd declaration was moved to the beginning of the function, and cringing and wincing at the function was significantly reduced. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index ab72e81..09a4680 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -339,26 +339,26 @@ remove: return CONTROLVM_RESP_SUCCESS; } -static int -create_device(struct controlvm_message *msg, char *buf) +static int create_device(struct controlvm_message *msg, char *buf) { struct device_info *dev; struct bus_info *bus; - u32 busNo, devNo; + struct guest_msgs cmd; + u32 bus_no, dev_no; int result = CONTROLVM_RESP_SUCCESS; - u64 minSize = MIN_IO_CHANNEL_SIZE; - struct req_handler_info *pReqHandler; + u64 min_size = MIN_IO_CHANNEL_SIZE; + struct req_handler_info *req_handler; - busNo = msg->cmd.create_device.bus_no; - devNo = msg->cmd.create_device.dev_no; + bus_no = msg->cmd.create_device.bus_no; + dev_no = msg->cmd.create_device.dev_no; - POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, devNo, busNo, + POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no, POSTCODE_SEVERITY_INFO); dev = kzalloc(sizeof(*dev), GFP_ATOMIC); if (!dev) { LOGERR("CONTROLVM_DEVICE_CREATE Failed: kmalloc for dev failed.\n"); - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); return CONTROLVM_RESP_ERROR_KMALLOC_FAILED; } @@ -366,28 +366,28 @@ create_device(struct controlvm_message *msg, char *buf) dev->channel_uuid = msg->cmd.create_device.data_type_uuid; dev->intr = msg->cmd.create_device.intr; dev->channel_addr = msg->cmd.create_device.channel_addr; - dev->bus_no = busNo; - dev->dev_no = devNo; + dev->bus_no = bus_no; + dev->dev_no = dev_no; sema_init(&dev->interrupt_callback_lock, 1); /* unlocked */ - sprintf(dev->devid, "vbus%u:dev%u", (unsigned)busNo, (unsigned)devNo); + sprintf(dev->devid, "vbus%u:dev%u", (unsigned)bus_no, (unsigned)dev_no); /* map the channel memory for the device. */ if (msg->hdr.flags.test_message) { dev->chanptr = (void __iomem *)__va(dev->channel_addr); } else { - pReqHandler = req_handler_find(dev->channel_uuid); - if (pReqHandler) + req_handler = req_handler_find(dev->channel_uuid); + if (req_handler) /* generic service handler registered for this * channel */ - minSize = pReqHandler->min_channel_bytes; - if (minSize > msg->cmd.create_device.channel_bytes) { + min_size = req_handler->min_channel_bytes; + if (min_size > msg->cmd.create_device.channel_bytes) { LOGERR("CONTROLVM_DEVICE_CREATE Failed: channel size is too small, channel size:0x%lx, required size:0x%lx", - (ulong) msg->cmd.create_device.channel_bytes, - (ulong) minSize); - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, - POSTCODE_SEVERITY_ERR); + (ulong)msg->cmd.create_device.channel_bytes, + (ulong)min_size); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); result = CONTROLVM_RESP_ERROR_CHANNEL_SIZE_TOO_SMALL; - goto Away; + goto cleanup; } dev->chanptr = uislib_ioremap_cache(dev->channel_addr, @@ -397,9 +397,9 @@ create_device(struct controlvm_message *msg, char *buf) dev->channel_addr, msg->cmd.create_device.channel_bytes); result = CONTROLVM_RESP_ERROR_IOREMAP_FAILED; - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, - POSTCODE_SEVERITY_ERR); - goto Away; + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); + goto cleanup; } } dev->instance_uuid = msg->cmd.create_device.dev_inst_uuid; @@ -407,128 +407,116 @@ create_device(struct controlvm_message *msg, char *buf) read_lock(&bus_list_lock); for (bus = bus_list; bus; bus = bus->next) { - if (bus->bus_no == busNo) { - /* make sure the device number is valid */ - if (devNo >= bus->device_count) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: device (%d) >= deviceCount (%d).", - devNo, bus->device_count); - result = CONTROLVM_RESP_ERROR_MAX_DEVICES; + if (bus->bus_no != bus_no) + continue; + /* make sure the device number is valid */ + if (dev_no >= bus->device_count) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: device (%d) >= deviceCount (%d).", + dev_no, bus->device_count); + result = CONTROLVM_RESP_ERROR_MAX_DEVICES; + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); + read_unlock(&bus_list_lock); + goto cleanup; + } + /* make sure this device is not already set */ + if (bus->device[dev_no]) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: device %d is already exists.", + dev_no); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, + dev_no, bus_no, + POSTCODE_SEVERITY_ERR); + result = CONTROLVM_RESP_ERROR_ALREADY_DONE; + read_unlock(&bus_list_lock); + goto cleanup; + } + read_unlock(&bus_list_lock); + /* the msg is bound for virtpci; send + * guest_msgs struct to callback + */ + if (msg->hdr.flags.server) { + bus->device[dev_no] = dev; + POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, dev_no, + bus_no, POSTCODE_SEVERITY_INFO); + return CONTROLVM_RESP_SUCCESS; + } + if (uuid_le_cmp(dev->channel_uuid, + spar_vhba_channel_protocol_uuid) == 0) { + wait_for_valid_guid(&((struct channel_header __iomem *) + (dev->chanptr))->chtype); + if (!SPAR_VHBA_CHANNEL_OK_CLIENT(dev->chanptr)) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed:[CLIENT]VHBA dev %d chan invalid.", + dev_no); POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, - devNo, busNo, + dev_no, bus_no, POSTCODE_SEVERITY_ERR); - read_unlock(&bus_list_lock); - goto Away; + result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID; + goto cleanup; } - /* make sure this device is not already set */ - if (bus->device[devNo]) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: device %d is already exists.", - devNo); + cmd.msgtype = GUEST_ADD_VHBA; + cmd.add_vhba.chanptr = dev->chanptr; + cmd.add_vhba.bus_no = bus_no; + cmd.add_vhba.device_no = dev_no; + cmd.add_vhba.instance_uuid = dev->instance_uuid; + cmd.add_vhba.intr = dev->intr; + } else if (uuid_le_cmp(dev->channel_uuid, + spar_vnic_channel_protocol_uuid) == 0) { + wait_for_valid_guid(&((struct channel_header __iomem *) + (dev->chanptr))->chtype); + if (!SPAR_VNIC_CHANNEL_OK_CLIENT(dev->chanptr)) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: VNIC[CLIENT] dev %d chan invalid.", + dev_no); POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, - devNo, busNo, + dev_no, bus_no, POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_ALREADY_DONE; - read_unlock(&bus_list_lock); - goto Away; + result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID; + goto cleanup; } - read_unlock(&bus_list_lock); - /* the msg is bound for virtpci; send - * guest_msgs struct to callback - */ - if (!msg->hdr.flags.server) { - struct guest_msgs cmd; - - if (!uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid)) { - wait_for_valid_guid(&(( - struct channel_header - __iomem *) (dev-> - chanptr))-> - chtype); - if (!SPAR_VHBA_CHANNEL_OK_CLIENT - (dev->chanptr)) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed:[CLIENT]VHBA dev %d chan invalid.", - devNo); - POSTCODE_LINUX_4 - (DEVICE_CREATE_FAILURE_PC, - devNo, busNo, - POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID; - goto Away; - } - cmd.msgtype = GUEST_ADD_VHBA; - cmd.add_vhba.chanptr = dev->chanptr; - cmd.add_vhba.bus_no = busNo; - cmd.add_vhba.device_no = devNo; - cmd.add_vhba.instance_uuid = - dev->instance_uuid; - cmd.add_vhba.intr = dev->intr; - } else - if (!uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid)) { - wait_for_valid_guid(&(( - struct channel_header - __iomem *) (dev-> - chanptr))-> - chtype); - if (!SPAR_VNIC_CHANNEL_OK_CLIENT - (dev->chanptr)) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: VNIC[CLIENT] dev %d chan invalid.", - devNo); - POSTCODE_LINUX_4 - (DEVICE_CREATE_FAILURE_PC, - devNo, busNo, - POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_CHANNEL_INVALID; - goto Away; - } - cmd.msgtype = GUEST_ADD_VNIC; - cmd.add_vnic.chanptr = dev->chanptr; - cmd.add_vnic.bus_no = busNo; - cmd.add_vnic.device_no = devNo; - cmd.add_vnic.instance_uuid = - dev->instance_uuid; - cmd.add_vhba.intr = dev->intr; - } else { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: unknown channelTypeGuid.\n"); - POSTCODE_LINUX_4 - (DEVICE_CREATE_FAILURE_PC, devNo, - busNo, POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN; - goto Away; - } + cmd.msgtype = GUEST_ADD_VNIC; + cmd.add_vnic.chanptr = dev->chanptr; + cmd.add_vnic.bus_no = bus_no; + cmd.add_vnic.device_no = dev_no; + cmd.add_vnic.instance_uuid = dev->instance_uuid; + cmd.add_vhba.intr = dev->intr; + } else { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: unknown channelTypeGuid.\n"); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); + result = CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN; + goto cleanup; + } - if (!virt_control_chan_func) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci callback not registered."); - POSTCODE_LINUX_4 - (DEVICE_CREATE_FAILURE_PC, devNo, - busNo, POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; - goto Away; - } + if (!virt_control_chan_func) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci callback not registered."); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); + result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; + goto cleanup; + } - if (!virt_control_chan_func(&cmd)) { - LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci GUEST_ADD_[VHBA||VNIC] returned error."); - POSTCODE_LINUX_4 - (DEVICE_CREATE_FAILURE_PC, devNo, - busNo, POSTCODE_SEVERITY_ERR); - result = CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; - goto Away; - } - } - bus->device[devNo] = dev; - POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, devNo, busNo, - POSTCODE_SEVERITY_INFO); - return CONTROLVM_RESP_SUCCESS; + if (!virt_control_chan_func(&cmd)) { + LOGERR("CONTROLVM_DEVICE_CREATE Failed: virtpci GUEST_ADD_[VHBA||VNIC] returned error."); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, + bus_no, POSTCODE_SEVERITY_ERR); + result = + CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; + goto cleanup; } + + bus->device[dev_no] = dev; + POSTCODE_LINUX_4(DEVICE_CREATE_SUCCESS_PC, dev_no, + bus_no, POSTCODE_SEVERITY_INFO); + return CONTROLVM_RESP_SUCCESS; } read_unlock(&bus_list_lock); - LOGERR("CONTROLVM_DEVICE_CREATE Failed: failed to find bus %d.", busNo); - POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, devNo, busNo, + LOGERR("CONTROLVM_DEVICE_CREATE Failed: failed to find bus %d.", + bus_no); + POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no, POSTCODE_SEVERITY_ERR); result = CONTROLVM_RESP_ERROR_BUS_INVALID; -Away: +cleanup: if (!msg->hdr.flags.test_message) { uislib_iounmap(dev->chanptr); dev->chanptr = NULL; -- cgit v0.10.2 From 441a29a57e1d88a280308b860d57ac45bd77903a Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:56 -0500 Subject: staging: unisys: refactor pause_device() Fix the function declaration so it is on a single line. Fix CamelCase local variables: busNo => bus_no devNo => dev_no Fix use of uuid_le_cmp() to check for 0 instead of using !uuid_le_cmp(). Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 09a4680..35be4e6 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -526,32 +526,31 @@ cleanup: return result; } -static int -pause_device(struct controlvm_message *msg) +static int pause_device(struct controlvm_message *msg) { - u32 busNo, devNo; + u32 bus_no, dev_no; struct bus_info *bus; struct device_info *dev; struct guest_msgs cmd; int retval = CONTROLVM_RESP_SUCCESS; - busNo = msg->cmd.device_change_state.bus_no; - devNo = msg->cmd.device_change_state.dev_no; + bus_no = msg->cmd.device_change_state.bus_no; + dev_no = msg->cmd.device_change_state.dev_no; read_lock(&bus_list_lock); for (bus = bus_list; bus; bus = bus->next) { - if (bus->bus_no == busNo) { + if (bus->bus_no == bus_no) { /* make sure the device number is valid */ - if (devNo >= bus->device_count) { + if (dev_no >= bus->device_count) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device(%d) >= deviceCount(%d).", - devNo, bus->device_count); + dev_no, bus->device_count); retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID; } else { /* make sure this device exists */ - dev = bus->device[devNo]; + dev = bus->device[dev_no]; if (!dev) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: device %d does not exist.", - devNo); + dev_no); retval = CONTROLVM_RESP_ERROR_ALREADY_DONE; } @@ -561,7 +560,7 @@ pause_device(struct controlvm_message *msg) } if (!bus) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:pause Failed: bus %d does not exist", - busNo); + bus_no); retval = CONTROLVM_RESP_ERROR_BUS_INVALID; } read_unlock(&bus_list_lock); @@ -569,12 +568,12 @@ pause_device(struct controlvm_message *msg) /* the msg is bound for virtpci; send * guest_msgs struct to callback */ - if (!uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid)) { + if (uuid_le_cmp(dev->channel_uuid, + spar_vhba_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_PAUSE_VHBA; cmd.pause_vhba.chanptr = dev->chanptr; - } else if (!uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid)) { + } else if (uuid_le_cmp(dev->channel_uuid, + spar_vnic_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_PAUSE_VNIC; cmd.pause_vnic.chanptr = dev->chanptr; } else { -- cgit v0.10.2 From 027b8c5b8b6cea2adc2db655841c9d24001bc6d4 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:57 -0500 Subject: staging: unisys: refactor resume_device() Fix the function declaration so it is a single line. Fix CamelCase local variable names: busNo => bus_no devNo => dev_no Fix use of uuid_le_cmp() to check for 0 instead of using !uuid_le_cmp(). Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 35be4e6..ca52f47 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -593,32 +593,31 @@ static int pause_device(struct controlvm_message *msg) return retval; } -static int -resume_device(struct controlvm_message *msg) +static int resume_device(struct controlvm_message *msg) { - u32 busNo, devNo; + u32 bus_no, dev_no; struct bus_info *bus; struct device_info *dev; struct guest_msgs cmd; int retval = CONTROLVM_RESP_SUCCESS; - busNo = msg->cmd.device_change_state.bus_no; - devNo = msg->cmd.device_change_state.dev_no; + bus_no = msg->cmd.device_change_state.bus_no; + dev_no = msg->cmd.device_change_state.dev_no; read_lock(&bus_list_lock); for (bus = bus_list; bus; bus = bus->next) { - if (bus->bus_no == busNo) { + if (bus->bus_no == bus_no) { /* make sure the device number is valid */ - if (devNo >= bus->device_count) { + if (dev_no >= bus->device_count) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device(%d) >= deviceCount(%d).", - devNo, bus->device_count); + dev_no, bus->device_count); retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID; } else { /* make sure this device exists */ - dev = bus->device[devNo]; + dev = bus->device[dev_no]; if (!dev) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: device %d does not exist.", - devNo); + dev_no); retval = CONTROLVM_RESP_ERROR_ALREADY_DONE; } @@ -629,7 +628,7 @@ resume_device(struct controlvm_message *msg) if (!bus) { LOGERR("CONTROLVM_DEVICE_CHANGESTATE:resume Failed: bus %d does not exist", - busNo); + bus_no); retval = CONTROLVM_RESP_ERROR_BUS_INVALID; } read_unlock(&bus_list_lock); @@ -637,12 +636,12 @@ resume_device(struct controlvm_message *msg) * guest_msgs struct to callback */ if (retval == CONTROLVM_RESP_SUCCESS) { - if (!uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid)) { + if (uuid_le_cmp(dev->channel_uuid, + spar_vhba_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_RESUME_VHBA; cmd.resume_vhba.chanptr = dev->chanptr; - } else if (!uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid)) { + } else if (uuid_le_cmp(dev->channel_uuid, + spar_vnic_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_RESUME_VNIC; cmd.resume_vnic.chanptr = dev->chanptr; } else { -- cgit v0.10.2 From 5b28f15aa62ac98badad2ed6f2f2aaeab11cb178 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:58 -0500 Subject: staging: unisys: refactor destroy_device() Fix the function declaration so it is a single line. Rename CamelCase local variable names: busNo => bus_no devNo => dev_no Fix use of uuid_le_cmp() to check for 0 instead of using !uuid_le_cmp(). Fix spelling error DESTORY to correctly read DESTROY. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index ca52f47..4f6f2c9 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -661,33 +661,33 @@ static int resume_device(struct controlvm_message *msg) return retval; } -static int -destroy_device(struct controlvm_message *msg, char *buf) +static int destroy_device(struct controlvm_message *msg, char *buf) { - u32 busNo, devNo; + u32 bus_no, dev_no; struct bus_info *bus; struct device_info *dev; struct guest_msgs cmd; int retval = CONTROLVM_RESP_SUCCESS; - busNo = msg->cmd.destroy_device.bus_no; - devNo = msg->cmd.destroy_device.bus_no; + bus_no = msg->cmd.destroy_device.bus_no; + dev_no = msg->cmd.destroy_device.bus_no; read_lock(&bus_list_lock); - LOGINF("destroy_device called for busNo=%u, devNo=%u", busNo, devNo); + LOGINF("destroy_device called for bus_no=%u, dev_no=%u", bus_no, + dev_no); for (bus = bus_list; bus; bus = bus->next) { - if (bus->bus_no == busNo) { + if (bus->bus_no == bus_no) { /* make sure the device number is valid */ - if (devNo >= bus->device_count) { - LOGERR("CONTROLVM_DEVICE_DESTORY Failed: device(%d) >= deviceCount(%d).", - devNo, bus->device_count); + if (dev_no >= bus->device_count) { + LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device(%d) >= device_count(%d).", + dev_no, bus->device_count); retval = CONTROLVM_RESP_ERROR_DEVICE_INVALID; } else { /* make sure this device exists */ - dev = bus->device[devNo]; + dev = bus->device[dev_no]; if (!dev) { LOGERR("CONTROLVM_DEVICE_DESTROY Failed: device %d does not exist.", - devNo); + dev_no); retval = CONTROLVM_RESP_ERROR_ALREADY_DONE; } @@ -698,7 +698,7 @@ destroy_device(struct controlvm_message *msg, char *buf) if (!bus) { LOGERR("CONTROLVM_DEVICE_DESTROY Failed: bus %d does not exist", - busNo); + bus_no); retval = CONTROLVM_RESP_ERROR_BUS_INVALID; } read_unlock(&bus_list_lock); @@ -706,12 +706,12 @@ destroy_device(struct controlvm_message *msg, char *buf) /* the msg is bound for virtpci; send * guest_msgs struct to callback */ - if (!uuid_le_cmp(dev->channel_uuid, - spar_vhba_channel_protocol_uuid)) { + if (uuid_le_cmp(dev->channel_uuid, + spar_vhba_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_DEL_VHBA; cmd.del_vhba.chanptr = dev->chanptr; - } else if (!uuid_le_cmp(dev->channel_uuid, - spar_vnic_channel_protocol_uuid)) { + } else if (uuid_le_cmp(dev->channel_uuid, + spar_vnic_channel_protocol_uuid) == 0) { cmd.msgtype = GUEST_DEL_VNIC; cmd.del_vnic.chanptr = dev->chanptr; } else { @@ -720,7 +720,7 @@ destroy_device(struct controlvm_message *msg, char *buf) CONTROLVM_RESP_ERROR_CHANNEL_TYPE_UNKNOWN; } if (!virt_control_chan_func) { - LOGERR("CONTROLVM_DEVICE_DESTORY Failed: virtpci callback not registered."); + LOGERR("CONTROLVM_DEVICE_DESTROY Failed: virtpci callback not registered."); return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; } @@ -736,7 +736,7 @@ destroy_device(struct controlvm_message *msg, char *buf) */ if (dev->polling) { LOGINF("calling uislib_disable_channel_interrupts"); - uislib_disable_channel_interrupts(busNo, devNo); + uislib_disable_channel_interrupts(bus_no, dev_no); } /* unmap the channel memory for the device. */ if (!msg->hdr.flags.test_message) { @@ -744,7 +744,7 @@ destroy_device(struct controlvm_message *msg, char *buf) uislib_iounmap(dev->chanptr); } kfree(dev); - bus->device[devNo] = NULL; + bus->device[dev_no] = NULL; } return retval; } -- cgit v0.10.2 From 3ee7441ff3b4e8e411940c5d0b27d918b59ab99e Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:08:59 -0500 Subject: staging: unisys: refactor delete_bus_glue() Fix the function declaration to be a single line, and rename the CamelCase parameter: busNo => bus_no Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 4f6f2c9..328f16b 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -774,15 +774,14 @@ init_chipset(struct controlvm_message *msg, char *buf) return CONTROLVM_RESP_SUCCESS; } -static int -delete_bus_glue(u32 busNo) +static int delete_bus_glue(u32 bus_no) { struct controlvm_message msg; init_msg_header(&msg, CONTROLVM_BUS_DESTROY, 0, 0); - msg.cmd.destroy_bus.bus_no = busNo; + msg.cmd.destroy_bus.bus_no = bus_no; if (destroy_bus(&msg, NULL) != CONTROLVM_RESP_SUCCESS) { - LOGERR("destroy_bus failed. busNo=0x%x\n", busNo); + LOGERR("destroy_bus failed. bus_no=0x%x\n", bus_no); return 0; } return 1; -- cgit v0.10.2 From 419113c892db06951046d42c2c2d4e7e5cc4c33f Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:00 -0500 Subject: staging: unisys: refactor delete_device_glue() Fix the function declaration so it is a single line, and fix CamelCase function parameter names: busNo => bus_no devNo => dev_no Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 328f16b..d251822 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -787,17 +787,16 @@ static int delete_bus_glue(u32 bus_no) return 1; } -static int -delete_device_glue(u32 busNo, u32 devNo) +static int delete_device_glue(u32 bus_no, u32 dev_no) { struct controlvm_message msg; init_msg_header(&msg, CONTROLVM_DEVICE_DESTROY, 0, 0); - msg.cmd.destroy_device.bus_no = busNo; - msg.cmd.destroy_device.dev_no = devNo; + msg.cmd.destroy_device.bus_no = bus_no; + msg.cmd.destroy_device.dev_no = dev_no; if (destroy_device(&msg, NULL) != CONTROLVM_RESP_SUCCESS) { - LOGERR("destroy_device failed. busNo=0x%x devNo=0x%x\n", busNo, - devNo); + LOGERR("destroy_device failed. bus_no=0x%x dev_no=0x%x\n", + bus_no, dev_no); return 0; } return 1; -- cgit v0.10.2 From 2b6040c51f7d031d83355df2454d4b80e7779885 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:01 -0500 Subject: staging: unisys: refactor info_debugfs_read() Fix the function declaration so the type is on the same line as the name, and fix the CamelCase local variable name: TotalBytes => total_bytes Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index d251822..614919c8 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -1154,12 +1154,11 @@ err_done: return -1; } -static ssize_t -info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset) +static ssize_t info_debugfs_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) { char *temp; - int totalBytes = 0; + int total_bytes = 0; int remaining_bytes = PROC_READ_BUFFER_SIZE; /* *start = buf; */ @@ -1178,14 +1177,14 @@ info_debugfs_read(struct file *file, char __user *buf, if ((*offset == 0) || (!debug_buf_valid)) { DBGINF("calling info_debugfs_read_helper.\n"); /* if the read fails, then -1 will be returned */ - totalBytes = info_debugfs_read_helper(&temp, &remaining_bytes); + total_bytes = info_debugfs_read_helper(&temp, &remaining_bytes); debug_buf_valid = 1; } else { - totalBytes = strlen(debug_buf); + total_bytes = strlen(debug_buf); } return simple_read_from_buffer(buf, len, offset, - debug_buf, totalBytes); + debug_buf, total_bytes); } static struct device_info * -- cgit v0.10.2 From ab12d8a00abefaa86edba121cc20db86f26ed7d3 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:02 -0500 Subject: staging: unisys: refactor find_dev() Fix the function definition so that it is a single line. Fix CamelCase parameter names: busNo => bus_no devNo => dev_no Get rid of the goto and just break out of the for loop, since that does the exact same thing. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 614919c8..908ec49 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -1187,31 +1187,29 @@ static ssize_t info_debugfs_read(struct file *file, char __user *buf, debug_buf, total_bytes); } -static struct device_info * -find_dev(u32 busNo, u32 devNo) +static struct device_info *find_dev(u32 bus_no, u32 dev_no) { struct bus_info *bus; struct device_info *dev = NULL; read_lock(&bus_list_lock); for (bus = bus_list; bus; bus = bus->next) { - if (bus->bus_no == busNo) { + if (bus->bus_no == bus_no) { /* make sure the device number is valid */ - if (devNo >= bus->device_count) { - LOGERR("%s bad busNo, devNo=%d,%d", + if (dev_no >= bus->device_count) { + LOGERR("%s bad bus_no, dev_no=%d,%d", __func__, - (int)(busNo), (int)(devNo)); - goto Away; + (int)bus_no, (int)dev_no); + break; } - dev = bus->device[devNo]; + dev = bus->device[dev_no]; if (!dev) - LOGERR("%s bad busNo, devNo=%d,%d", + LOGERR("%s bad bus_no, dev_no=%d,%d", __func__, - (int)(busNo), (int)(devNo)); - goto Away; + (int)bus_no, (int)dev_no); + break; } } -Away: read_unlock(&bus_list_lock); return dev; } -- cgit v0.10.2 From 3ec66a4be43f4b1a447385f6dd1d1e2b9fd2b19b Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:03 -0500 Subject: staging: unisys: rename Process_Incoming() Fix the CamelCase function name: Process_Incoming => process_incoming Update all references to use the new name. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 908ec49..3b81bbf 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -1234,8 +1234,7 @@ static struct device_info *find_dev(u32 bus_no, u32 dev_no) * less-busy ones. * */ -static int -Process_Incoming(void *v) +static int process_incoming(void *v) { unsigned long long cur_cycles, old_cycles, idle_cycles, delta_cycles; struct list_head *new_tail = NULL; @@ -1346,7 +1345,7 @@ Initialize_incoming_thread(void) if (incoming_started) return TRUE; if (!uisthread_start(&incoming_ti, - &Process_Incoming, NULL, "dev_incoming")) { + &process_incoming, NULL, "dev_incoming")) { LOGERR("uisthread_start Initialize_incoming_thread ****FAILED"); return FALSE; } @@ -1355,7 +1354,7 @@ Initialize_incoming_thread(void) } /* Add a new device/channel to the list being processed by - * Process_Incoming(). + * process_incoming(). * - indicates the function to call periodically. * - indicates the data to pass to the * function. @@ -1385,7 +1384,7 @@ uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no, EXPORT_SYMBOL_GPL(uislib_enable_channel_interrupts); /* Remove a device/channel from the list being processed by - * Process_Incoming(). + * process_incoming(). */ void uislib_disable_channel_interrupts(u32 bus_no, u32 dev_no) @@ -1418,7 +1417,7 @@ do_wakeup_polling_device_channels(struct work_struct *dummy) static DECLARE_WORK(Work_wakeup_polling_device_channels, do_wakeup_polling_device_channels); -/* Call this function when you want to send a hint to Process_Incoming() that +/* Call this function when you want to send a hint to process_incoming() that * your device might have more requests. */ void @@ -1430,7 +1429,7 @@ uislib_force_channel_interrupt(u32 bus_no, u32 dev_no) return; /* The point of using schedule_work() instead of just doing * the work inline is to force a slight delay before waking up - * the Process_Incoming() thread. + * the process_incoming() thread. */ tot_wakeup_cnt++; schedule_work(&Work_wakeup_polling_device_channels); -- cgit v0.10.2 From 52ebd30e036878d8db95e32a0112ef63a328d5c5 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:04 -0500 Subject: staging: unisys: rename Initialize_incoming_thread() Fix the CamelCase name of this function: Initialize_incoming_thread => initialize_incoming_thread Update all references to use the new name. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 3b81bbf..29c12a3 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -1340,13 +1340,13 @@ static int process_incoming(void *v) } static BOOL -Initialize_incoming_thread(void) +initialize_incoming_thread(void) { if (incoming_started) return TRUE; if (!uisthread_start(&incoming_ti, &process_incoming, NULL, "dev_incoming")) { - LOGERR("uisthread_start Initialize_incoming_thread ****FAILED"); + LOGERR("uisthread_start initialize_incoming_thread ****FAILED"); return FALSE; } incoming_started = TRUE; @@ -1373,7 +1373,7 @@ uislib_enable_channel_interrupts(u32 bus_no, u32 dev_no, return; } down(&poll_dev_lock); - Initialize_incoming_thread(); + initialize_incoming_thread(); dev->interrupt = interrupt; dev->interrupt_context = interrupt_context; dev->polling = TRUE; -- cgit v0.10.2 From 8304ada2e20e18d472a9581ab7258e5cb5b0015f Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:05 -0500 Subject: staging: unisys: fix CamelCase Work queue name in uislib.c Fix CamelCase name: Work_wakeup_polling_device_channels => work_wakeup_polling_device_channels Update references to use the new name. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 29c12a3..a9eedde 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -1414,7 +1414,7 @@ do_wakeup_polling_device_channels(struct work_struct *dummy) } } -static DECLARE_WORK(Work_wakeup_polling_device_channels, +static DECLARE_WORK(work_wakeup_polling_device_channels, do_wakeup_polling_device_channels); /* Call this function when you want to send a hint to process_incoming() that @@ -1432,7 +1432,7 @@ uislib_force_channel_interrupt(u32 bus_no, u32 dev_no) * the process_incoming() thread. */ tot_wakeup_cnt++; - schedule_work(&Work_wakeup_polling_device_channels); + schedule_work(&work_wakeup_polling_device_channels); } EXPORT_SYMBOL_GPL(uislib_force_channel_interrupt); -- cgit v0.10.2 From 120758c0d1b5e2eca3c30d0fa20db55759baee9c Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:06 -0500 Subject: staging: unisys: fix spacing in uisqueue.c Correct alignment for a couple of functions and remove the space between a typecast and its target. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uisqueue.c b/drivers/staging/unisys/uislib/uisqueue.c index 69151e4..9869c9f 100644 --- a/drivers/staging/unisys/uislib/uisqueue.c +++ b/drivers/staging/unisys/uislib/uisqueue.c @@ -226,7 +226,7 @@ EXPORT_SYMBOL_GPL(spar_signalqueue_empty); unsigned long long uisqueue_interlocked_or(unsigned long long __iomem *tgt, - unsigned long long set) + unsigned long long set) { unsigned long long i; unsigned long long j; @@ -244,7 +244,7 @@ EXPORT_SYMBOL_GPL(uisqueue_interlocked_or); unsigned long long uisqueue_interlocked_and(unsigned long long __iomem *tgt, - unsigned long long set) + unsigned long long set) { unsigned long long i; unsigned long long j; @@ -294,7 +294,7 @@ uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo, char oktowait, u8 *channel_id) { while (!do_locked_client_insert(queueinfo, whichqueue, cmdrsp, - (spinlock_t *) insertlock, + (spinlock_t *)insertlock, issue_irq_if_empty, irq_handle, channel_id)) { if (oktowait != OK_TO_WAIT) { -- cgit v0.10.2 From 0b7682ff565f22b0ff31bb77de2e3d61b50996cf Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:07 -0500 Subject: staging: unisys: fix CamelCase names in do_locked_client_insert() Fix CamelCase names: pSignal => signal Remove unused parameters issueInterruptIfEmpty and interruptHandle, and update callers of this function. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uisqueue.c b/drivers/staging/unisys/uislib/uisqueue.c index 9869c9f..71bb7b6 100644 --- a/drivers/staging/unisys/uislib/uisqueue.c +++ b/drivers/staging/unisys/uislib/uisqueue.c @@ -263,22 +263,21 @@ EXPORT_SYMBOL_GPL(uisqueue_interlocked_and); static u8 do_locked_client_insert(struct uisqueue_info *queueinfo, unsigned int whichqueue, - void *pSignal, + void *signal, spinlock_t *lock, - unsigned char issueInterruptIfEmpty, - u64 interruptHandle, u8 *channelId) + u8 *channel_id) { unsigned long flags; u8 rc = 0; spin_lock_irqsave(lock, flags); - if (!spar_channel_client_acquire_os(queueinfo->chan, channelId)) + if (!spar_channel_client_acquire_os(queueinfo->chan, channel_id)) goto unlock; - if (spar_signal_insert(queueinfo->chan, whichqueue, pSignal)) { + if (spar_signal_insert(queueinfo->chan, whichqueue, signal)) { queueinfo->packets_sent++; rc = 1; } - spar_channel_client_release_os(queueinfo->chan, channelId); + spar_channel_client_release_os(queueinfo->chan, channel_id); unlock: spin_unlock_irqrestore((spinlock_t *)lock, flags); return rc; @@ -295,8 +294,7 @@ uisqueue_put_cmdrsp_with_lock_client(struct uisqueue_info *queueinfo, { while (!do_locked_client_insert(queueinfo, whichqueue, cmdrsp, (spinlock_t *)insertlock, - issue_irq_if_empty, - irq_handle, channel_id)) { + channel_id)) { if (oktowait != OK_TO_WAIT) { LOGERR("****FAILED visor_signal_insert failed; cannot wait; insert aborted\n"); return 0; /* failed to queue */ -- cgit v0.10.2 From 3206f853187af95b809a5373bb146700fa8618bc Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:08 -0500 Subject: staging: unisys: fix line spacing in uisthread.c Just remove the one extra blank line. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uisthread.c b/drivers/staging/unisys/uislib/uisthread.c index c0fc812..25adf1a 100644 --- a/drivers/staging/unisys/uislib/uisthread.c +++ b/drivers/staging/unisys/uislib/uisthread.c @@ -53,7 +53,6 @@ uisthread_start(struct uisthread_info *thrinfo, wake_up_process(thrinfo->task); LOGINF("started thread pid:%d\n", thrinfo->id); return 1; - } EXPORT_SYMBOL_GPL(uisthread_start); -- cgit v0.10.2 From 10ae5fad7111ddc26aeaa2480bc0cf6408dd24ad Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:09 -0500 Subject: staging: unisys: fix line spacing in uisutils.c Just remove the couple of extra blank lines. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c index 4a5b867..941f007 100644 --- a/drivers/staging/unisys/uislib/uisutils.c +++ b/drivers/staging/unisys/uislib/uisutils.c @@ -42,7 +42,6 @@ atomic_t uisutils_registered_services = ATOMIC_INIT(0); * uisctrl_register_req_handler() or * uisctrl_register_req_handler_ex() */ - /*****************************************************/ /* Utility functions */ /*****************************************************/ @@ -255,7 +254,6 @@ dolist: if (skb_shinfo(skb)->frag_list) { for (skbinlist = skb_shinfo(skb)->frag_list; skbinlist; skbinlist = skbinlist->next) { - c = uisutil_copy_fragsinfo_from_skb("recursive", skbinlist, skbinlist->len - skbinlist->data_len, -- cgit v0.10.2 From 6791b8c4d2d10ee4747d6ae08f3faa1fd9bc988d Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:10 -0500 Subject: staging: unisys: fix spacing in uisutils.c Fix as many spacing problems as possible by indenting lines properly and getting rid of spaces between typecasts and their targets. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c index 941f007..5865df7 100644 --- a/drivers/staging/unisys/uislib/uisutils.c +++ b/drivers/staging/unisys/uislib/uisutils.c @@ -48,7 +48,7 @@ atomic_t uisutils_registered_services = ATOMIC_INIT(0); int uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining, - char *format, ...) + char *format, ...) { va_list args; int len; @@ -95,7 +95,7 @@ uisctrl_register_req_handler(int type, void *fptr, } if (chipset_driver_info) bus_device_info_init(chipset_driver_info, "chipset", "uislib", - VERSION, NULL); + VERSION, NULL); return 1; } @@ -147,7 +147,7 @@ Away: if (rc) { if (chipset_driver_info) bus_device_info_init(chipset_driver_info, "chipset", - "uislib", VERSION, NULL); + "uislib", VERSION, NULL); } else LOGERR("failed to register type %pUL.\n", &switch_uuid); @@ -163,7 +163,7 @@ uisctrl_unregister_req_handler_ex(uuid_le switch_uuid) LOGINF("type=%pUL.\n", &switch_uuid); if (req_handler_del(switch_uuid) < 0) { LOGERR("failed to remove %pUL from server list\n", - &switch_uuid); + &switch_uuid); goto Away; } atomic_dec(&uisutils_registered_services); @@ -213,10 +213,10 @@ uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx, void *skb_in, frags[count].pi_pfn = page_to_pfn(virt_to_page(skb->data + offset)); frags[count].pi_off = - (unsigned long) (skb->data + offset) & PI_PAGE_MASK; + (unsigned long)(skb->data + offset) & PI_PAGE_MASK; size = min(firstfraglen, - (unsigned int) (PI_PAGE_SIZE - frags[count].pi_off)); + (unsigned int)(PI_PAGE_SIZE - frags[count].pi_off)); /* can take smallest of firstfraglen(what's left) OR * bytes left in the page */ @@ -230,7 +230,7 @@ uisutil_copy_fragsinfo_from_skb(unsigned char *calling_ctx, void *skb_in, if ((count + numfrags) > frags_max) { LOGERR("**** FAILED %s frags array too small: max:%d count+nr_frags:%d\n", - calling_ctx, frags_max, count + numfrags); + calling_ctx, frags_max, count + numfrags); return -1; /* failure */ } -- cgit v0.10.2 From 61f988961f02cf2b11bf475b2ae0ce4d81e4b3fc Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:11 -0500 Subject: staging: unisys: fix brackets in uisctrl_register_req_handler_ex() Add the missing brackets to the last if statement in this function. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c index 5865df7..6d13eb2 100644 --- a/drivers/staging/unisys/uislib/uisutils.c +++ b/drivers/staging/unisys/uislib/uisutils.c @@ -148,9 +148,9 @@ Away: if (chipset_driver_info) bus_device_info_init(chipset_driver_info, "chipset", "uislib", VERSION, NULL); - } else + } else { LOGERR("failed to register type %pUL.\n", &switch_uuid); - + } return rc; } EXPORT_SYMBOL_GPL(uisctrl_register_req_handler_ex); -- cgit v0.10.2 From 717dd09fe75f5e165410caab197b2f7ec74e46e7 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:12 -0500 Subject: staging: unisys: refactor uisctrl_register_req_handler_ex() Fix CamelCase local variable name: pReqHandlerInfo => req_handler Get rid of the useless goto and just return straight away on an error. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c index 6d13eb2..9ca10e9 100644 --- a/drivers/staging/unisys/uislib/uisutils.c +++ b/drivers/staging/unisys/uislib/uisutils.c @@ -112,46 +112,43 @@ uisctrl_register_req_handler_ex(uuid_le switch_uuid, u32 client_str_len, u64 bytes), struct ultra_vbus_deviceinfo *chipset_driver_info) { - struct req_handler_info *pReqHandlerInfo; - int rc = 0; /* assume failure */ + struct req_handler_info *req_handler; LOGINF("type=%pUL, controlfunc=0x%p.\n", &switch_uuid, controlfunc); if (!controlfunc) { LOGERR("%pUL: controlfunc must be supplied\n", &switch_uuid); - goto Away; + return 0; } if (!server_channel_ok) { LOGERR("%pUL: Server_Channel_Ok must be supplied\n", &switch_uuid); - goto Away; + return 0; } if (!server_channel_init) { LOGERR("%pUL: Server_Channel_Init must be supplied\n", &switch_uuid); - goto Away; + return 0; } - pReqHandlerInfo = req_handler_add(switch_uuid, - switch_type_name, - controlfunc, - min_channel_bytes, - server_channel_ok, server_channel_init); - if (!pReqHandlerInfo) { + req_handler = req_handler_add(switch_uuid, + switch_type_name, + controlfunc, + min_channel_bytes, + server_channel_ok, server_channel_init); + if (!req_handler) { LOGERR("failed to add %pUL to server list\n", &switch_uuid); - goto Away; + return 0; } atomic_inc(&uisutils_registered_services); - rc = 1; /* success */ -Away: - if (rc) { - if (chipset_driver_info) - bus_device_info_init(chipset_driver_info, "chipset", - "uislib", VERSION, NULL); - } else { - LOGERR("failed to register type %pUL.\n", &switch_uuid); + if (chipset_driver_info) { + bus_device_info_init(chipset_driver_info, "chipset", + "uislib", VERSION, NULL); + return 1; } - return rc; + + LOGERR("failed to register type %pUL.\n", &switch_uuid); + return 0; } EXPORT_SYMBOL_GPL(uisctrl_register_req_handler_ex); -- cgit v0.10.2 From 94070ed4dd28a451c2ab7c5f90840270ac4cd61a Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:13 -0500 Subject: staging: unisys: refactor uisctrl_unregister_req_handler_ex() Get rid of the unnecessary goto statement and just return directly. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c index 9ca10e9..e8c868e 100644 --- a/drivers/staging/unisys/uislib/uisutils.c +++ b/drivers/staging/unisys/uislib/uisutils.c @@ -155,20 +155,14 @@ EXPORT_SYMBOL_GPL(uisctrl_register_req_handler_ex); int uisctrl_unregister_req_handler_ex(uuid_le switch_uuid) { - int rc = 0; /* assume failure */ - LOGINF("type=%pUL.\n", &switch_uuid); if (req_handler_del(switch_uuid) < 0) { LOGERR("failed to remove %pUL from server list\n", &switch_uuid); - goto Away; + return 0; } atomic_dec(&uisutils_registered_services); - rc = 1; /* success */ -Away: - if (!rc) - LOGERR("failed to unregister type %pUL.\n", &switch_uuid); - return rc; + return 1; } EXPORT_SYMBOL_GPL(uisctrl_unregister_req_handler_ex); -- cgit v0.10.2 From bd7029105e85a6aee014e30351b459504165e13d Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:14 -0500 Subject: staging: unisys: fix CamelCase globals in uisutils.c Rename CamelCase global variable names: ReqHandlerInfo_list => req_handler_info_list ReqHandlerInfo_list_lock => req_handler_info_list_lock Update all references to use the new name. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c index e8c868e..4f89b2c 100644 --- a/drivers/staging/unisys/uislib/uisutils.c +++ b/drivers/staging/unisys/uislib/uisutils.c @@ -261,8 +261,8 @@ dolist: if (skb_shinfo(skb)->frag_list) { } EXPORT_SYMBOL_GPL(uisutil_copy_fragsinfo_from_skb); -static LIST_HEAD(ReqHandlerInfo_list); /* list of struct req_handler_info */ -static DEFINE_SPINLOCK(ReqHandlerInfo_list_lock); +static LIST_HEAD(req_handler_info_list); /* list of struct req_handler_info */ +static DEFINE_SPINLOCK(req_handler_info_list_lock); struct req_handler_info * req_handler_add(uuid_le switch_uuid, @@ -286,9 +286,9 @@ req_handler_add(uuid_le switch_uuid, if (switch_type_name) strncpy(rc->switch_type_name, switch_type_name, sizeof(rc->switch_type_name) - 1); - spin_lock(&ReqHandlerInfo_list_lock); - list_add_tail(&(rc->list_link), &ReqHandlerInfo_list); - spin_unlock(&ReqHandlerInfo_list_lock); + spin_lock(&req_handler_info_list_lock); + list_add_tail(&(rc->list_link), &req_handler_info_list); + spin_unlock(&req_handler_info_list_lock); return rc; } @@ -299,15 +299,15 @@ req_handler_find(uuid_le switch_uuid) struct list_head *lelt, *tmp; struct req_handler_info *entry = NULL; - spin_lock(&ReqHandlerInfo_list_lock); - list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) { + spin_lock(&req_handler_info_list_lock); + list_for_each_safe(lelt, tmp, &req_handler_info_list) { entry = list_entry(lelt, struct req_handler_info, list_link); if (uuid_le_cmp(entry->switch_uuid, switch_uuid) == 0) { - spin_unlock(&ReqHandlerInfo_list_lock); + spin_unlock(&req_handler_info_list_lock); return entry; } } - spin_unlock(&ReqHandlerInfo_list_lock); + spin_unlock(&req_handler_info_list_lock); return NULL; } @@ -318,8 +318,8 @@ req_handler_del(uuid_le switch_uuid) struct req_handler_info *entry = NULL; int rc = -1; - spin_lock(&ReqHandlerInfo_list_lock); - list_for_each_safe(lelt, tmp, &ReqHandlerInfo_list) { + spin_lock(&req_handler_info_list_lock); + list_for_each_safe(lelt, tmp, &req_handler_info_list) { entry = list_entry(lelt, struct req_handler_info, list_link); if (uuid_le_cmp(entry->switch_uuid, switch_uuid) == 0) { list_del(lelt); @@ -327,6 +327,6 @@ req_handler_del(uuid_le switch_uuid) rc++; } } - spin_unlock(&ReqHandlerInfo_list_lock); + spin_unlock(&req_handler_info_list_lock); return rc; } -- cgit v0.10.2 From be080dc1afd4b4aacd3a77f275a10c2b7b14bcd0 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:15 -0500 Subject: staging: unisys: refactor req_handler_add() Fix the CamelCase parameter names: Server_Channel_Ok => server_channel_ok Server_Channel_Init => server_channel_init clientStr => clientstr clientStrLen => clientstr_len And remove the extra parenthesis in the list_add_tail() call at the end. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c index 4f89b2c..d9f527d 100644 --- a/drivers/staging/unisys/uislib/uisutils.c +++ b/drivers/staging/unisys/uislib/uisutils.c @@ -269,9 +269,10 @@ req_handler_add(uuid_le switch_uuid, const char *switch_type_name, int (*controlfunc)(struct io_msgs *), unsigned long min_channel_bytes, - int (*Server_Channel_Ok)(unsigned long channelBytes), - int (*Server_Channel_Init) - (void *x, unsigned char *clientStr, u32 clientStrLen, u64 bytes)) + int (*server_channel_ok)(unsigned long channel_bytes), + int (*server_channel_init) + (void *x, unsigned char *clientstr, u32 clientstr_len, + u64 bytes)) { struct req_handler_info *rc = NULL; @@ -281,13 +282,13 @@ req_handler_add(uuid_le switch_uuid, rc->switch_uuid = switch_uuid; rc->controlfunc = controlfunc; rc->min_channel_bytes = min_channel_bytes; - rc->server_channel_ok = Server_Channel_Ok; - rc->server_channel_init = Server_Channel_Init; + rc->server_channel_ok = server_channel_ok; + rc->server_channel_init = server_channel_init; if (switch_type_name) strncpy(rc->switch_type_name, switch_type_name, sizeof(rc->switch_type_name) - 1); spin_lock(&req_handler_info_list_lock); - list_add_tail(&(rc->list_link), &req_handler_info_list); + list_add_tail(&rc->list_link, &req_handler_info_list); spin_unlock(&req_handler_info_list_lock); return rc; -- cgit v0.10.2 From 7381312852808e88faaecd60eff3eb1d0dd0dcd8 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:16 -0500 Subject: staging: unisys: refactor visorchipset_file_init() Fix the declaration so it is a single line. Fix CamelCase parameter names: MajorDev => major_dev pControlVm_channel => controlvm_channel Remove the unnecessary gotos and just return directly in error cases. Fix the last error condition so it returns the result of cdev_add() instead of always zero. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index 373fa36..cb5bcb9 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -57,13 +57,12 @@ static const struct file_operations visorchipset_fops = { .mmap = visorchipset_mmap, }; -int -visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel) +int visorchipset_file_init(dev_t major_dev, VISORCHANNEL **controlvm_channel) { - int rc = -1; + int rc = 0; - PControlVm_channel = pControlVm_channel; - MajorDev = majorDev; + PControlVm_channel = controlvm_channel; + MajorDev = major_dev; cdev_init(&Cdev, &visorchipset_fops); Cdev.owner = THIS_MODULE; if (MAJOR(MajorDev) == 0) { @@ -71,7 +70,7 @@ visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel) if (alloc_chrdev_region(&MajorDev, 0, 1, MYDRVNAME) < 0) { ERRDRV("Unable to allocate+register char device %s", MYDRVNAME); - goto Away; + return -1; } Registered = TRUE; INFODRV("New major number %d registered\n", MAJOR(MajorDev)); @@ -79,20 +78,19 @@ visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel) /* static major device number registration required */ if (register_chrdev_region(MajorDev, 1, MYDRVNAME) < 0) { ERRDRV("Unable to register char device %s", MYDRVNAME); - goto Away; + return -1; } Registered = TRUE; INFODRV("Static major number %d registered\n", MAJOR(MajorDev)); } - if (cdev_add(&Cdev, MKDEV(MAJOR(MajorDev), 0), 1) < 0) { + rc = cdev_add(&Cdev, MKDEV(MAJOR(MajorDev), 0), 1); + if (rc < 0) { ERRDRV("failed to create char device: (status=%d)\n", rc); - goto Away; + return -1; } INFODRV("Registered char device for %s (major=%d)", MYDRVNAME, MAJOR(MajorDev)); - rc = 0; -Away: - return rc; + return 0; } void diff --git a/drivers/staging/unisys/visorchipset/file.h b/drivers/staging/unisys/visorchipset/file.h index 21bb906..fb434eb 100644 --- a/drivers/staging/unisys/visorchipset/file.h +++ b/drivers/staging/unisys/visorchipset/file.h @@ -20,7 +20,7 @@ #include "globals.h" -int visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel); +int visorchipset_file_init(dev_t major_dev, VISORCHANNEL **controlvm_channel); void visorchipset_file_cleanup(void); #endif -- cgit v0.10.2 From e8fe1ef1e3d2906ba2e49f4623b45154fdba9767 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:17 -0500 Subject: staging: unisys: fix CamelCase global variables in file.c Fix CamelCase names: Cdev => file_cdev PControlVm_channel => file_controlvm_channel MajorDev => majordev Registered => registered Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index cb5bcb9..f4d01ed 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -28,10 +28,10 @@ #define CURRENT_FILE_PC VISOR_CHIPSET_PC_file_c -static struct cdev Cdev; -static VISORCHANNEL **PControlVm_channel; -static dev_t MajorDev = -1; /**< indicates major num for device */ -static BOOL Registered = FALSE; +static struct cdev file_cdev; +static VISORCHANNEL **file_controlvm_channel; +static dev_t majordev = -1; /**< indicates major num for device */ +static BOOL registered = FALSE; static int visorchipset_open(struct inode *inode, struct file *file); static int visorchipset_release(struct inode *inode, struct file *file); @@ -61,50 +61,50 @@ int visorchipset_file_init(dev_t major_dev, VISORCHANNEL **controlvm_channel) { int rc = 0; - PControlVm_channel = controlvm_channel; - MajorDev = major_dev; - cdev_init(&Cdev, &visorchipset_fops); - Cdev.owner = THIS_MODULE; - if (MAJOR(MajorDev) == 0) { + file_controlvm_channel = controlvm_channel; + majordev = major_dev; + cdev_init(&file_cdev, &visorchipset_fops); + file_cdev.owner = THIS_MODULE; + if (MAJOR(majordev) == 0) { /* dynamic major device number registration required */ - if (alloc_chrdev_region(&MajorDev, 0, 1, MYDRVNAME) < 0) { + if (alloc_chrdev_region(&majordev, 0, 1, MYDRVNAME) < 0) { ERRDRV("Unable to allocate+register char device %s", MYDRVNAME); return -1; } - Registered = TRUE; - INFODRV("New major number %d registered\n", MAJOR(MajorDev)); + registered = TRUE; + INFODRV("New major number %d registered\n", MAJOR(majordev)); } else { /* static major device number registration required */ - if (register_chrdev_region(MajorDev, 1, MYDRVNAME) < 0) { + if (register_chrdev_region(majordev, 1, MYDRVNAME) < 0) { ERRDRV("Unable to register char device %s", MYDRVNAME); return -1; } - Registered = TRUE; - INFODRV("Static major number %d registered\n", MAJOR(MajorDev)); + registered = TRUE; + INFODRV("Static major number %d registered\n", MAJOR(majordev)); } - rc = cdev_add(&Cdev, MKDEV(MAJOR(MajorDev), 0), 1); + rc = cdev_add(&file_cdev, MKDEV(MAJOR(majordev), 0), 1); if (rc < 0) { ERRDRV("failed to create char device: (status=%d)\n", rc); return -1; } INFODRV("Registered char device for %s (major=%d)", - MYDRVNAME, MAJOR(MajorDev)); + MYDRVNAME, MAJOR(majordev)); return 0; } void visorchipset_file_cleanup(void) { - if (Cdev.ops != NULL) - cdev_del(&Cdev); - Cdev.ops = NULL; - if (Registered) { - if (MAJOR(MajorDev) >= 0) { - unregister_chrdev_region(MajorDev, 1); - MajorDev = MKDEV(0, 0); + if (file_cdev.ops != NULL) + cdev_del(&file_cdev); + file_cdev.ops = NULL; + if (registered) { + if (MAJOR(majordev) >= 0) { + unregister_chrdev_region(majordev, 1); + majordev = MKDEV(0, 0); } - Registered = FALSE; + registered = FALSE; } } @@ -148,11 +148,11 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) switch (offset) { case VISORCHIPSET_MMAP_CONTROLCHANOFFSET: vma->vm_flags |= VM_IO; - if (*PControlVm_channel == NULL) { + if (*file_controlvm_channel == NULL) { ERRDRV("%s no controlvm channel yet", __func__); return -ENXIO; } - visorchannel_read(*PControlVm_channel, + visorchannel_read(*file_controlvm_channel, offsetof(struct spar_controlvm_channel_protocol, gp_control_channel), &addr, sizeof(addr)); -- cgit v0.10.2 From 9982937a2ae99066699b31b0cd6c230157ebfc49 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:18 -0500 Subject: staging: unisys: get rid of HAVE_UNLOCKED_IOCTL code We definitely have it, so there's no point in keeping the older stuff around. Get rid of the #ifdefs and old code. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index f4d01ed..4b0c158 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -36,23 +36,14 @@ static BOOL registered = FALSE; static int visorchipset_open(struct inode *inode, struct file *file); static int visorchipset_release(struct inode *inode, struct file *file); static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma); -#ifdef HAVE_UNLOCKED_IOCTL long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -#else -int visorchipset_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); -#endif static const struct file_operations visorchipset_fops = { .owner = THIS_MODULE, .open = visorchipset_open, .read = NULL, .write = NULL, -#ifdef HAVE_UNLOCKED_IOCTL .unlocked_ioctl = visorchipset_ioctl, -#else - .ioctl = visorchipset_ioctl, -#endif .release = visorchipset_release, .mmap = visorchipset_mmap, }; @@ -178,14 +169,7 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -#ifdef HAVE_UNLOCKED_IOCTL -long -visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -#else -int -visorchipset_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -#endif +long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int rc = SUCCESS; s64 adjustment; -- cgit v0.10.2 From 11f8ac08e91cca07732feb74dc9d7c6e6b17f3fe Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:19 -0500 Subject: staging: unisys: get rid of goto in visorchipset_open() This goto uses CamelCase and was completely unnecessary. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index 4b0c158..d43c403 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -103,17 +103,12 @@ static int visorchipset_open(struct inode *inode, struct file *file) { unsigned minor_number = iminor(inode); - int rc = -ENODEV; DEBUGDRV("%s", __func__); if (minor_number != 0) - goto Away; + return -ENODEV; file->private_data = NULL; - rc = 0; -Away: - if (rc < 0) - ERRDRV("%s minor=%d failed", __func__, minor_number); - return rc; + return 0; } static int -- cgit v0.10.2 From cc5ff7f5c76ebcbb249696b4bff373bf1898212e Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:20 -0500 Subject: staging: unisys: fix CamelCase in visorchipset_mmap() Fix CamelCase name: physAddr => physaddr Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index d43c403..b82bc4a 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -121,7 +121,7 @@ visorchipset_release(struct inode *inode, struct file *file) static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma) { - ulong physAddr = 0; + ulong physaddr = 0; ulong offset = vma->vm_pgoff << PAGE_SHIFT; GUEST_PHYSICAL_ADDRESS addr = 0; @@ -146,10 +146,10 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) ERRDRV("%s control channel address is 0", __func__); return -ENXIO; } - physAddr = (ulong) (addr); - DEBUGDRV("mapping physical address = 0x%lx", physAddr); + physaddr = (ulong)addr; + DEBUGDRV("mapping physical address = 0x%lx", physaddr); if (remap_pfn_range(vma, vma->vm_start, - physAddr >> PAGE_SHIFT, + physaddr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, /*pgprot_noncached */ (vma->vm_page_prot))) { -- cgit v0.10.2 From 2ce6cbb6b95b0955866ef8db3d3dbb9e7a0d1244 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Fri, 5 Dec 2014 17:09:21 -0500 Subject: staging: unisys: get rid of goto in visorchipset_ioctl() Remove another completely unnecessary goto and just return the values directly. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index b82bc4a..ced3fbe 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -166,7 +166,6 @@ visorchipset_mmap(struct file *file, struct vm_area_struct *vma) long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int rc = SUCCESS; s64 adjustment; s64 vrtc_offset; @@ -177,28 +176,21 @@ long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg) vrtc_offset = issue_vmcall_query_guest_virtual_time_offset(); if (copy_to_user ((void __user *)arg, &vrtc_offset, sizeof(vrtc_offset))) { - rc = -EFAULT; - goto Away; + return -EFAULT; } DBGINF("insde visorchipset_ioctl, cmd=%d, vrtc_offset=%lld", cmd, vrtc_offset); - break; + return SUCCESS; case VMCALL_UPDATE_PHYSICAL_TIME: if (copy_from_user (&adjustment, (void __user *)arg, sizeof(adjustment))) { - rc = -EFAULT; - goto Away; + return -EFAULT; } DBGINF("insde visorchipset_ioctl, cmd=%d, adjustment=%lld", cmd, adjustment); - rc = issue_vmcall_update_physical_time(adjustment); - break; + return issue_vmcall_update_physical_time(adjustment); default: LOGERR("visorchipset_ioctl received invalid command"); - rc = -EFAULT; - break; + return -EFAULT; } -Away: - DBGINF("exiting %d!", rc); - return rc; } -- cgit v0.10.2 From be408256b06ccb15bafc0367f486969328a91e22 Mon Sep 17 00:00:00 2001 From: Bryan Thompson Date: Fri, 5 Dec 2014 17:09:22 -0500 Subject: staging: unisys: visorchannel: Rename CamelCase variable channelBytes Rename channelBytes to channel_bytes in the series of visorchannel_create functions provided by visorchannel. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchannel/visorchannel.h b/drivers/staging/unisys/visorchannel/visorchannel.h index 5061edf..5dbfddb 100644 --- a/drivers/staging/unisys/visorchannel/visorchannel.h +++ b/drivers/staging/unisys/visorchannel/visorchannel.h @@ -35,17 +35,17 @@ typedef struct VISORCHANNEL_Tag VISORCHANNEL; /* Note that for visorchannel_create() and visorchannel_create_overlapped(), - * and arguments may be 0 if we are a channel CLIENT. + * and arguments may be 0 if we are a channel CLIENT. * In this case, the values can simply be read from the channel header. */ VISORCHANNEL *visorchannel_create(HOSTADDRESS physaddr, - ulong channelBytes, uuid_le guid); -VISORCHANNEL *visorchannel_create_overlapped(ulong channelBytes, + ulong channel_bytes, uuid_le guid); +VISORCHANNEL *visorchannel_create_overlapped(ulong channel_bytes, VISORCHANNEL *parent, ulong off, uuid_le guid); VISORCHANNEL *visorchannel_create_with_lock(HOSTADDRESS physaddr, - ulong channelBytes, uuid_le guid); -VISORCHANNEL *visorchannel_create_overlapped_with_lock(ulong channelBytes, + ulong channel_bytes, uuid_le guid); +VISORCHANNEL *visorchannel_create_overlapped_with_lock(ulong channel_bytes, VISORCHANNEL *parent, ulong off, uuid_le guid); void visorchannel_destroy(VISORCHANNEL *channel); diff --git a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c index 36559d5..6601b3e 100644 --- a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c +++ b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c @@ -49,7 +49,7 @@ struct VISORCHANNEL_Tag { * NOT modify this data area. */ static VISORCHANNEL * -visorchannel_create_guts(HOSTADDRESS physaddr, ulong channelBytes, +visorchannel_create_guts(HOSTADDRESS physaddr, ulong channel_bytes, VISORCHANNEL *parent, ulong off, uuid_le guid, BOOL needs_lock) { @@ -87,18 +87,18 @@ visorchannel_create_guts(HOSTADDRESS physaddr, ulong channelBytes, rc = NULL; goto cleanup; } - if (channelBytes == 0) + if (channel_bytes == 0) /* we had better be a CLIENT of this channel */ - channelBytes = (ulong)p->chan_hdr.size; + channel_bytes = (ulong)p->chan_hdr.size; if (uuid_le_cmp(guid, NULL_UUID_LE) == 0) /* we had better be a CLIENT of this channel */ guid = p->chan_hdr.chtype; - if (visor_memregion_resize(p->memregion, channelBytes) < 0) { + if (visor_memregion_resize(p->memregion, channel_bytes) < 0) { ERRDRV("visor_memregion_resize failed: (status=0)\n"); rc = NULL; goto cleanup; } - p->size = channelBytes; + p->size = channel_bytes; p->guid = guid; rc = p; @@ -114,37 +114,37 @@ cleanup: } VISORCHANNEL * -visorchannel_create(HOSTADDRESS physaddr, ulong channelBytes, uuid_le guid) +visorchannel_create(HOSTADDRESS physaddr, ulong channel_bytes, uuid_le guid) { - return visorchannel_create_guts(physaddr, channelBytes, NULL, 0, guid, + return visorchannel_create_guts(physaddr, channel_bytes, NULL, 0, guid, FALSE); } EXPORT_SYMBOL_GPL(visorchannel_create); VISORCHANNEL * -visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channelBytes, +visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channel_bytes, uuid_le guid) { - return visorchannel_create_guts(physaddr, channelBytes, NULL, 0, guid, + return visorchannel_create_guts(physaddr, channel_bytes, NULL, 0, guid, TRUE); } EXPORT_SYMBOL_GPL(visorchannel_create_with_lock); VISORCHANNEL * -visorchannel_create_overlapped(ulong channelBytes, +visorchannel_create_overlapped(ulong channel_bytes, VISORCHANNEL *parent, ulong off, uuid_le guid) { - return visorchannel_create_guts(0, channelBytes, parent, off, guid, + return visorchannel_create_guts(0, channel_bytes, parent, off, guid, FALSE); } EXPORT_SYMBOL_GPL(visorchannel_create_overlapped); VISORCHANNEL * -visorchannel_create_overlapped_with_lock(ulong channelBytes, +visorchannel_create_overlapped_with_lock(ulong channel_bytes, VISORCHANNEL *parent, ulong off, uuid_le guid) { - return visorchannel_create_guts(0, channelBytes, parent, off, guid, + return visorchannel_create_guts(0, channel_bytes, parent, off, guid, TRUE); } EXPORT_SYMBOL_GPL(visorchannel_create_overlapped_with_lock); -- cgit v0.10.2 From 4c67da3083c80d9cdf172d99c942bbddfaeae529 Mon Sep 17 00:00:00 2001 From: Bryan Thompson Date: Fri, 5 Dec 2014 17:09:23 -0500 Subject: staging: unisys: visorchannel: Rename CamelCase variable nQueues Rename the visorchannel_debug parameter nQueues to num_queues. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchannel/visorchannel.h b/drivers/staging/unisys/visorchannel/visorchannel.h index 5dbfddb..3f2184c 100644 --- a/drivers/staging/unisys/visorchannel/visorchannel.h +++ b/drivers/staging/unisys/visorchannel/visorchannel.h @@ -68,7 +68,7 @@ u64 visorchannel_get_clientpartition(VISORCHANNEL *channel); uuid_le visorchannel_get_uuid(VISORCHANNEL *channel); struct memregion *visorchannel_get_memregion(VISORCHANNEL *channel); char *visorchannel_uuid_id(uuid_le *guid, char *s); -void visorchannel_debug(VISORCHANNEL *channel, int nQueues, +void visorchannel_debug(VISORCHANNEL *channel, int num_queues, struct seq_file *seq, u32 off); void visorchannel_dump_section(VISORCHANNEL *chan, char *s, int off, int len, struct seq_file *seq); diff --git a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c index 6601b3e..1568b95 100644 --- a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c +++ b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c @@ -565,7 +565,7 @@ sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq) } void -visorchannel_debug(VISORCHANNEL *channel, int nQueues, +visorchannel_debug(VISORCHANNEL *channel, int num_queues, struct seq_file *seq, u32 off) { HOSTADDRESS addr = 0; @@ -625,7 +625,7 @@ visorchannel_debug(VISORCHANNEL *channel, int nQueues, if ((phdr->ch_space_offset == 0) || (errcode < 0)) ; else - for (i = 0; i < nQueues; i++) { + for (i = 0; i < num_queues; i++) { struct signal_queue_header q; errcode = visorchannel_read(channel, -- cgit v0.10.2 From 9551bfba917a17f850b5887474c56b8772417e70 Mon Sep 17 00:00:00 2001 From: Bryan Thompson Date: Fri, 5 Dec 2014 17:09:24 -0500 Subject: staging: unisys: visorchannel: Describe spinlocks in VISORCHANNEL_Tag struct Add comments indicating the requirements and use of the insert_lock and remove_lock in the VISORCHANNEL_Tag structure. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c index 1568b95..1ce25c2 100644 --- a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c +++ b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c @@ -33,9 +33,10 @@ struct VISORCHANNEL_Tag { struct channel_header chan_hdr; uuid_le guid; ulong size; - BOOL needs_lock; - spinlock_t insert_lock; - spinlock_t remove_lock; + BOOL needs_lock; /* channel creator knows if more than one + * thread will be inserting or removing */ + spinlock_t insert_lock; /* protect head writes in chan_hdr */ + spinlock_t remove_lock; /* protect tail writes in chan_hdr */ struct { struct signal_queue_header req_queue; -- cgit v0.10.2 From 383df64e02029c78875f19d76e7f40483fc9fe10 Mon Sep 17 00:00:00 2001 From: Bryan Thompson Date: Fri, 5 Dec 2014 17:09:25 -0500 Subject: staging: unisys: Remove VISORCHANNEL typedef Remove the VISORCHANNEL typedef and rename the base VISORCHANNEL_Tag structure to visorchannel to follow consistent naming. The longer struct visorchannel type required additional line wrapping to remain less than 81 characters. Signed-off-by: Bryan Thompson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchannel/visorchannel.h b/drivers/staging/unisys/visorchannel/visorchannel.h index 3f2184c..63f1b97 100644 --- a/drivers/staging/unisys/visorchannel/visorchannel.h +++ b/drivers/staging/unisys/visorchannel/visorchannel.h @@ -29,49 +29,48 @@ #define BOOL int #endif -/* VISORCHANNEL is an opaque structure to users. - * Fields are declared only in the implementation .c files. - */ -typedef struct VISORCHANNEL_Tag VISORCHANNEL; - /* Note that for visorchannel_create() and visorchannel_create_overlapped(), * and arguments may be 0 if we are a channel CLIENT. * In this case, the values can simply be read from the channel header. */ -VISORCHANNEL *visorchannel_create(HOSTADDRESS physaddr, - ulong channel_bytes, uuid_le guid); -VISORCHANNEL *visorchannel_create_overlapped(ulong channel_bytes, - VISORCHANNEL *parent, ulong off, - uuid_le guid); -VISORCHANNEL *visorchannel_create_with_lock(HOSTADDRESS physaddr, - ulong channel_bytes, uuid_le guid); -VISORCHANNEL *visorchannel_create_overlapped_with_lock(ulong channel_bytes, - VISORCHANNEL *parent, - ulong off, uuid_le guid); -void visorchannel_destroy(VISORCHANNEL *channel); -int visorchannel_read(VISORCHANNEL *channel, ulong offset, +struct visorchannel *visorchannel_create(HOSTADDRESS physaddr, + ulong channel_bytes, uuid_le guid); +struct visorchannel *visorchannel_create_overlapped(ulong channel_bytes, + struct visorchannel *parent, + ulong off, uuid_le guid); +struct visorchannel *visorchannel_create_with_lock(HOSTADDRESS physaddr, + ulong channel_bytes, + uuid_le guid); +struct visorchannel *visorchannel_create_overlapped_with_lock( + ulong channel_bytes, + struct visorchannel *parent, + ulong off, uuid_le guid); +void visorchannel_destroy(struct visorchannel *channel); +int visorchannel_read(struct visorchannel *channel, ulong offset, void *local, ulong nbytes); -int visorchannel_write(VISORCHANNEL *channel, ulong offset, +int visorchannel_write(struct visorchannel *channel, ulong offset, void *local, ulong nbytes); -int visorchannel_clear(VISORCHANNEL *channel, ulong offset, +int visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch, ulong nbytes); -BOOL visorchannel_signalremove(VISORCHANNEL *channel, u32 queue, void *msg); -BOOL visorchannel_signalinsert(VISORCHANNEL *channel, u32 queue, void *msg); -int visorchannel_signalqueue_slots_avail(VISORCHANNEL *channel, u32 queue); -int visorchannel_signalqueue_max_slots(VISORCHANNEL *channel, u32 queue); - -HOSTADDRESS visorchannel_get_physaddr(VISORCHANNEL *channel); -ulong visorchannel_get_nbytes(VISORCHANNEL *channel); -char *visorchannel_id(VISORCHANNEL *channel, char *s); -char *visorchannel_zoneid(VISORCHANNEL *channel, char *s); -u64 visorchannel_get_clientpartition(VISORCHANNEL *channel); -uuid_le visorchannel_get_uuid(VISORCHANNEL *channel); -struct memregion *visorchannel_get_memregion(VISORCHANNEL *channel); +BOOL visorchannel_signalremove(struct visorchannel *channel, u32 queue, + void *msg); +BOOL visorchannel_signalinsert(struct visorchannel *channel, u32 queue, + void *msg); +int visorchannel_signalqueue_slots_avail(struct visorchannel *channel, + u32 queue); +int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue); +HOSTADDRESS visorchannel_get_physaddr(struct visorchannel *channel); +ulong visorchannel_get_nbytes(struct visorchannel *channel); +char *visorchannel_id(struct visorchannel *channel, char *s); +char *visorchannel_zoneid(struct visorchannel *channel, char *s); +u64 visorchannel_get_clientpartition(struct visorchannel *channel); +uuid_le visorchannel_get_uuid(struct visorchannel *channel); +struct memregion *visorchannel_get_memregion(struct visorchannel *channel); char *visorchannel_uuid_id(uuid_le *guid, char *s); -void visorchannel_debug(VISORCHANNEL *channel, int num_queues, +void visorchannel_debug(struct visorchannel *channel, int num_queues, struct seq_file *seq, u32 off); -void visorchannel_dump_section(VISORCHANNEL *chan, char *s, +void visorchannel_dump_section(struct visorchannel *chan, char *s, int off, int len, struct seq_file *seq); -void __iomem *visorchannel_get_header(VISORCHANNEL *channel); +void __iomem *visorchannel_get_header(struct visorchannel *channel); #endif diff --git a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c index 1ce25c2..6c48ba1 100644 --- a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c +++ b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c @@ -28,7 +28,7 @@ #define MYDRVNAME "visorchannel" -struct VISORCHANNEL_Tag { +struct visorchannel { struct memregion *memregion; /* from visor_memregion_create() */ struct channel_header chan_hdr; uuid_le guid; @@ -46,18 +46,18 @@ struct VISORCHANNEL_Tag { } safe_uis_queue; }; -/* Creates the VISORCHANNEL abstraction for a data area in memory, but does - * NOT modify this data area. +/* Creates the struct visorchannel abstraction for a data area in memory, + * but does NOT modify this data area. */ -static VISORCHANNEL * +static struct visorchannel * visorchannel_create_guts(HOSTADDRESS physaddr, ulong channel_bytes, - VISORCHANNEL *parent, ulong off, uuid_le guid, + struct visorchannel *parent, ulong off, uuid_le guid, BOOL needs_lock) { - VISORCHANNEL *p = NULL; + struct visorchannel *p = NULL; void *rc = NULL; - p = kmalloc(sizeof(VISORCHANNEL), GFP_KERNEL|__GFP_NORETRY); + p = kmalloc(sizeof(*p), GFP_KERNEL|__GFP_NORETRY); if (p == NULL) { ERRDRV("allocation failed: (status=0)\n"); rc = NULL; @@ -114,7 +114,7 @@ cleanup: return rc; } -VISORCHANNEL * +struct visorchannel * visorchannel_create(HOSTADDRESS physaddr, ulong channel_bytes, uuid_le guid) { return visorchannel_create_guts(physaddr, channel_bytes, NULL, 0, guid, @@ -122,7 +122,7 @@ visorchannel_create(HOSTADDRESS physaddr, ulong channel_bytes, uuid_le guid) } EXPORT_SYMBOL_GPL(visorchannel_create); -VISORCHANNEL * +struct visorchannel * visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channel_bytes, uuid_le guid) { @@ -131,18 +131,19 @@ visorchannel_create_with_lock(HOSTADDRESS physaddr, ulong channel_bytes, } EXPORT_SYMBOL_GPL(visorchannel_create_with_lock); -VISORCHANNEL * +struct visorchannel * visorchannel_create_overlapped(ulong channel_bytes, - VISORCHANNEL *parent, ulong off, uuid_le guid) + struct visorchannel *parent, ulong off, + uuid_le guid) { return visorchannel_create_guts(0, channel_bytes, parent, off, guid, FALSE); } EXPORT_SYMBOL_GPL(visorchannel_create_overlapped); -VISORCHANNEL * +struct visorchannel * visorchannel_create_overlapped_with_lock(ulong channel_bytes, - VISORCHANNEL *parent, ulong off, + struct visorchannel *parent, ulong off, uuid_le guid) { return visorchannel_create_guts(0, channel_bytes, parent, off, guid, @@ -151,7 +152,7 @@ visorchannel_create_overlapped_with_lock(ulong channel_bytes, EXPORT_SYMBOL_GPL(visorchannel_create_overlapped_with_lock); void -visorchannel_destroy(VISORCHANNEL *channel) +visorchannel_destroy(struct visorchannel *channel) { if (channel == NULL) return; @@ -164,14 +165,14 @@ visorchannel_destroy(VISORCHANNEL *channel) EXPORT_SYMBOL_GPL(visorchannel_destroy); HOSTADDRESS -visorchannel_get_physaddr(VISORCHANNEL *channel) +visorchannel_get_physaddr(struct visorchannel *channel) { return visor_memregion_get_physaddr(channel->memregion); } EXPORT_SYMBOL_GPL(visorchannel_get_physaddr); ulong -visorchannel_get_nbytes(VISORCHANNEL *channel) +visorchannel_get_nbytes(struct visorchannel *channel) { return channel->size; } @@ -186,42 +187,42 @@ visorchannel_uuid_id(uuid_le *guid, char *s) EXPORT_SYMBOL_GPL(visorchannel_uuid_id); char * -visorchannel_id(VISORCHANNEL *channel, char *s) +visorchannel_id(struct visorchannel *channel, char *s) { return visorchannel_uuid_id(&channel->guid, s); } EXPORT_SYMBOL_GPL(visorchannel_id); char * -visorchannel_zoneid(VISORCHANNEL *channel, char *s) +visorchannel_zoneid(struct visorchannel *channel, char *s) { return visorchannel_uuid_id(&channel->chan_hdr.zone_uuid, s); } EXPORT_SYMBOL_GPL(visorchannel_zoneid); HOSTADDRESS -visorchannel_get_clientpartition(VISORCHANNEL *channel) +visorchannel_get_clientpartition(struct visorchannel *channel) { return channel->chan_hdr.partition_handle; } EXPORT_SYMBOL_GPL(visorchannel_get_clientpartition); uuid_le -visorchannel_get_uuid(VISORCHANNEL *channel) +visorchannel_get_uuid(struct visorchannel *channel) { return channel->guid; } EXPORT_SYMBOL_GPL(visorchannel_get_uuid); struct memregion * -visorchannel_get_memregion(VISORCHANNEL *channel) +visorchannel_get_memregion(struct visorchannel *channel) { return channel->memregion; } EXPORT_SYMBOL_GPL(visorchannel_get_memregion); int -visorchannel_read(VISORCHANNEL *channel, ulong offset, +visorchannel_read(struct visorchannel *channel, ulong offset, void *local, ulong nbytes) { int rc = visor_memregion_read(channel->memregion, offset, @@ -236,7 +237,7 @@ visorchannel_read(VISORCHANNEL *channel, ulong offset, EXPORT_SYMBOL_GPL(visorchannel_read); int -visorchannel_write(VISORCHANNEL *channel, ulong offset, +visorchannel_write(struct visorchannel *channel, ulong offset, void *local, ulong nbytes) { if (offset == 0 && nbytes >= sizeof(struct channel_header)) @@ -247,7 +248,8 @@ visorchannel_write(VISORCHANNEL *channel, ulong offset, EXPORT_SYMBOL_GPL(visorchannel_write); int -visorchannel_clear(VISORCHANNEL *channel, ulong offset, u8 ch, ulong nbytes) +visorchannel_clear(struct visorchannel *channel, ulong offset, u8 ch, + ulong nbytes) { int rc = -1; int bufsize = 65536; @@ -286,7 +288,7 @@ cleanup: EXPORT_SYMBOL_GPL(visorchannel_clear); void __iomem * -visorchannel_get_header(VISORCHANNEL *channel) +visorchannel_get_header(struct visorchannel *channel) { return (void __iomem *)&channel->chan_hdr; } @@ -317,7 +319,7 @@ EXPORT_SYMBOL_GPL(visorchannel_get_header); sizeof((sig_hdr)->FIELD)) >= 0) static BOOL -sig_read_header(VISORCHANNEL *channel, u32 queue, +sig_read_header(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr) { BOOL rc = FALSE; @@ -345,7 +347,7 @@ cleanup: } static BOOL -sig_do_data(VISORCHANNEL *channel, u32 queue, +sig_do_data(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr, u32 slot, void *data, BOOL is_write) { @@ -374,14 +376,14 @@ cleanup: } static inline BOOL -sig_read_data(VISORCHANNEL *channel, u32 queue, +sig_read_data(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr, u32 slot, void *data) { return sig_do_data(channel, queue, sig_hdr, slot, data, FALSE); } static inline BOOL -sig_write_data(VISORCHANNEL *channel, u32 queue, +sig_write_data(struct visorchannel *channel, u32 queue, struct signal_queue_header *sig_hdr, u32 slot, void *data) { return sig_do_data(channel, queue, sig_hdr, slot, data, TRUE); @@ -410,7 +412,7 @@ safe_sig_queue_validate(struct signal_queue_header *psafe_sqh, } /* end safe_sig_queue_validate */ BOOL -visorchannel_signalremove(VISORCHANNEL *channel, u32 queue, void *msg) +visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) { BOOL rc = FALSE; struct signal_queue_header sig_hdr; @@ -457,7 +459,7 @@ cleanup: EXPORT_SYMBOL_GPL(visorchannel_signalremove); BOOL -visorchannel_signalinsert(VISORCHANNEL *channel, u32 queue, void *msg) +visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) { BOOL rc = FALSE; struct signal_queue_header sig_hdr; @@ -512,7 +514,7 @@ cleanup: EXPORT_SYMBOL_GPL(visorchannel_signalinsert); int -visorchannel_signalqueue_slots_avail(VISORCHANNEL *channel, u32 queue) +visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue) { struct signal_queue_header sig_hdr; u32 slots_avail, slots_used; @@ -531,7 +533,7 @@ visorchannel_signalqueue_slots_avail(VISORCHANNEL *channel, u32 queue) EXPORT_SYMBOL_GPL(visorchannel_signalqueue_slots_avail); int -visorchannel_signalqueue_max_slots(VISORCHANNEL *channel, u32 queue) +visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue) { struct signal_queue_header sig_hdr; @@ -566,7 +568,7 @@ sigqueue_debug(struct signal_queue_header *q, int which, struct seq_file *seq) } void -visorchannel_debug(VISORCHANNEL *channel, int num_queues, +visorchannel_debug(struct visorchannel *channel, int num_queues, struct seq_file *seq, u32 off) { HOSTADDRESS addr = 0; @@ -648,7 +650,7 @@ visorchannel_debug(VISORCHANNEL *channel, int num_queues, EXPORT_SYMBOL_GPL(visorchannel_debug); void -visorchannel_dump_section(VISORCHANNEL *chan, char *s, +visorchannel_dump_section(struct visorchannel *chan, char *s, int off, int len, struct seq_file *seq) { char *buf, *tbuf, *fmtbuf; diff --git a/drivers/staging/unisys/visorchipset/file.c b/drivers/staging/unisys/visorchipset/file.c index ced3fbe..e51fd4e 100644 --- a/drivers/staging/unisys/visorchipset/file.c +++ b/drivers/staging/unisys/visorchipset/file.c @@ -29,7 +29,7 @@ #define CURRENT_FILE_PC VISOR_CHIPSET_PC_file_c static struct cdev file_cdev; -static VISORCHANNEL **file_controlvm_channel; +static struct visorchannel **file_controlvm_channel; static dev_t majordev = -1; /**< indicates major num for device */ static BOOL registered = FALSE; @@ -48,7 +48,8 @@ static const struct file_operations visorchipset_fops = { .mmap = visorchipset_mmap, }; -int visorchipset_file_init(dev_t major_dev, VISORCHANNEL **controlvm_channel) +int +visorchipset_file_init(dev_t major_dev, struct visorchannel **controlvm_channel) { int rc = 0; diff --git a/drivers/staging/unisys/visorchipset/file.h b/drivers/staging/unisys/visorchipset/file.h index fb434eb..dc7a195 100644 --- a/drivers/staging/unisys/visorchipset/file.h +++ b/drivers/staging/unisys/visorchipset/file.h @@ -20,7 +20,8 @@ #include "globals.h" -int visorchipset_file_init(dev_t major_dev, VISORCHANNEL **controlvm_channel); +int visorchipset_file_init(dev_t majorDev, + struct visorchannel **pControlVm_channel); void visorchipset_file_cleanup(void); #endif diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 2651f89..82e259d 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -101,7 +101,7 @@ static struct controlvm_message_packet g_DeviceChangeStatePacket; static LIST_HEAD(BusInfoList); static LIST_HEAD(DevInfoList); -static VISORCHANNEL *ControlVm_channel; +static struct visorchannel *ControlVm_channel; typedef struct { u8 __iomem *ptr; /* pointer to base address of payload pool */ -- cgit v0.10.2 From d7462ca0e86be313db332395b9efff41c083309c Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Fri, 12 Dec 2014 11:51:27 +0100 Subject: staging: unisys: remove leftover __DATE__ Commit 836bee9eee6d ("Staging: unisys: remove references to __DATE__ and __TIME__") removed most; this seems to be an accidental leftover. VERSIONDATE is not used anywhere. Signed-off-by: Rasmus Villemoes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/common-spar/include/version.h b/drivers/staging/unisys/common-spar/include/version.h index f25208f..83d1da7 100644 --- a/drivers/staging/unisys/common-spar/include/version.h +++ b/drivers/staging/unisys/common-spar/include/version.h @@ -30,7 +30,6 @@ #define SPARVER4 "0" #define VERSION SPARVER1 "." SPARVER2 "." SPARVER3 "." SPARVER4 -#define VERSIONDATE __DATE__ /* Here are various version forms needed in Windows environments. */ -- cgit v0.10.2 From e5f4a331c914a91383b93fd437119c8b24d0183c Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Mon, 15 Dec 2014 00:08:37 +0100 Subject: staging: unisys: virtpci: virtpci.c: Removes unnecessary NULL check It is impossible for dprivate to ever be NULL, no check required. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virtpci/virtpci.c b/drivers/staging/unisys/virtpci/virtpci.c index 39b828d..bc6e237 100644 --- a/drivers/staging/unisys/virtpci/virtpci.c +++ b/drivers/staging/unisys/virtpci/virtpci.c @@ -1338,18 +1338,13 @@ static ssize_t virtpci_driver_attr_show(struct kobject *kobj, ssize_t ret = 0; struct driver_private *dprivate = to_driver(kobj); - struct device_driver *driver; + struct device_driver *driver = dprivate->driver; - if (dprivate != NULL) - driver = dprivate->driver; - else - driver = NULL; + DBGINF("In virtpci_driver_attr_show driver->name:%s\n", driver->name); + + if (dattr->show) + ret = dattr->show(driver, buf); - DBGINF("In virtpci_driver_attr_show driver->name:%s\n", driver->name); - if (driver) { - if (dattr->show) - ret = dattr->show(driver, buf); - } return ret; } @@ -1361,19 +1356,13 @@ static ssize_t virtpci_driver_attr_store(struct kobject *kobj, ssize_t ret = 0; struct driver_private *dprivate = to_driver(kobj); - struct device_driver *driver; - - if (dprivate != NULL) - driver = dprivate->driver; - else - driver = NULL; + struct device_driver *driver = dprivate->driver; DBGINF("In virtpci_driver_attr_store driver->name:%s\n", driver->name); - if (driver) { - if (dattr->store) - ret = dattr->store(driver, buf, count); - } + if (dattr->store) + ret = dattr->store(driver, buf, count); + return ret; } -- cgit v0.10.2 From 66875c5d6495da7af0116d39bf7e8fbc257f3b01 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sat, 27 Dec 2014 23:04:14 +0100 Subject: staging: unisys: uislib: uisutils.c: Fix a missing va_end A missing va_end in connection with vsnprintf Was found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/uislib/uisutils.c b/drivers/staging/unisys/uislib/uisutils.c index d9f527d..31318d2 100644 --- a/drivers/staging/unisys/uislib/uisutils.c +++ b/drivers/staging/unisys/uislib/uisutils.c @@ -56,6 +56,7 @@ uisutil_add_proc_line_ex(int *total, char **buffer, int *buffer_remaining, DBGINF("buffer = 0x%p : *buffer = 0x%p.\n", buffer, *buffer); va_start(args, format); len = vsnprintf(*buffer, *buffer_remaining, format, args); + va_end(args); if (len >= *buffer_remaining) { *buffer += *buffer_remaining; *total += *buffer_remaining; -- cgit v0.10.2 From 29d586247d2194304a54ecb04a4cbfb86a8d87a3 Mon Sep 17 00:00:00 2001 From: Syed Amer Gilani Date: Sat, 27 Dec 2014 21:57:43 +0100 Subject: staging: unisys: fix checkpatch space prohibited before comma errors Fixes checkpatch Error: ERROR: space prohibited before that ',' (ctx:WxW) Signed-off-by: Syed Amer Gilani Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index d7a629b..82fcb3b 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -1438,7 +1438,7 @@ static ssize_t enable_ints_write(struct file *file, return -EFAULT; } - i = kstrtoint(buf, 10 , &new_value); + i = kstrtoint(buf, 10, &new_value); if (i != 0) { LOGERR("Failed to scan value for enable_ints, buf<<%.*s>>", diff --git a/drivers/staging/unisys/virtpci/virtpci.c b/drivers/staging/unisys/virtpci/virtpci.c index bc6e237..729affc 100644 --- a/drivers/staging/unisys/virtpci/virtpci.c +++ b/drivers/staging/unisys/virtpci/virtpci.c @@ -279,9 +279,9 @@ static int add_vbus(struct add_vbus_guestpart *addparams) POSTCODE_LINUX_2(VPCI_CREATE_FAILURE_PC, POSTCODE_SEVERITY_ERR); return 0; } - write_vbus_chp_info(vbus->platform_data /* chanptr */ , + write_vbus_chp_info(vbus->platform_data /* chanptr */, &chipset_driver_info); - write_vbus_bus_info(vbus->platform_data /* chanptr */ , + write_vbus_bus_info(vbus->platform_data /* chanptr */, &bus_driver_info); LOGINF("Added vbus %d; device %s created successfully\n", addparams->bus_no, BUS_ID(vbus)); @@ -466,7 +466,7 @@ static int pause_vhba(struct pause_virt_guestpart *pauseparams) GET_SCSIADAPINFO_FROM_CHANPTR(pauseparams->chanptr); LOGINF("Pausing vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2); - i = virtpci_device_serverdown(NULL /*no parent bus */ , VIRTHBA_TYPE, + i = virtpci_device_serverdown(NULL /*no parent bus */, VIRTHBA_TYPE, &scsi.wwnn, NULL); if (i) LOGINF("Paused vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, @@ -487,7 +487,7 @@ static int pause_vnic(struct pause_virt_guestpart *pauseparams) LOGINF("Pausing vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", net.mac_addr[0], net.mac_addr[1], net.mac_addr[2], net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]); - i = virtpci_device_serverdown(NULL /*no parent bus */ , VIRTNIC_TYPE, + i = virtpci_device_serverdown(NULL /*no parent bus */, VIRTNIC_TYPE, NULL, net.mac_addr); if (i) { LOGINF(" Paused vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", @@ -508,7 +508,7 @@ static int resume_vhba(struct resume_virt_guestpart *resumeparams) GET_SCSIADAPINFO_FROM_CHANPTR(resumeparams->chanptr); LOGINF("Resuming vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2); - i = virtpci_device_serverup(NULL /*no parent bus */ , VIRTHBA_TYPE, + i = virtpci_device_serverup(NULL /*no parent bus */, VIRTHBA_TYPE, &scsi.wwnn, NULL); if (i) LOGINF("Resumed vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, @@ -530,7 +530,7 @@ resume_vnic(struct resume_virt_guestpart *resumeparams) LOGINF("Resuming vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", net.mac_addr[0], net.mac_addr[1], net.mac_addr[2], net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]); - i = virtpci_device_serverup(NULL /*no parent bus */ , VIRTNIC_TYPE, + i = virtpci_device_serverup(NULL /*no parent bus */, VIRTNIC_TYPE, NULL, net.mac_addr); if (i) { LOGINF(" Resumed vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", @@ -551,7 +551,7 @@ static int delete_vhba(struct del_virt_guestpart *delparams) GET_SCSIADAPINFO_FROM_CHANPTR(delparams->chanptr); LOGINF("Deleting vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, scsi.wwnn.wwnn2); - i = virtpci_device_del(NULL /*no parent bus */ , VIRTHBA_TYPE, + i = virtpci_device_del(NULL /*no parent bus */, VIRTHBA_TYPE, &scsi.wwnn, NULL); if (i) { LOGINF("Deleted vhba wwnn:%x:%x\n", scsi.wwnn.wwnn1, @@ -574,7 +574,7 @@ static int delete_vnic(struct del_virt_guestpart *delparams) LOGINF("Deleting vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", net.mac_addr[0], net.mac_addr[1], net.mac_addr[2], net.mac_addr[3], net.mac_addr[4], net.mac_addr[5]); - i = virtpci_device_del(NULL /*no parent bus */ , VIRTNIC_TYPE, NULL, + i = virtpci_device_del(NULL /*no parent bus */, VIRTNIC_TYPE, NULL, net.mac_addr); if (i) { LOGINF("Deleted vnic macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n", -- cgit v0.10.2 From 1216ed713bfc53f1d43e220fa7b1713cad466498 Mon Sep 17 00:00:00 2001 From: Mariusz Gorski Date: Wed, 3 Dec 2014 19:53:47 +0100 Subject: staging: panel: Remove unused variable Remove lcd.left_shift because it is only written to at some places but never read from. Signed-off-by: Mariusz Gorski Acked-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 98325b7..b68a9c3 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -228,9 +228,6 @@ static struct { bool initialized; bool must_clear; - /* TODO: use bool here? */ - char left_shift; - int height; int width; int bwidth; @@ -1135,12 +1132,10 @@ static inline int handle_lcd_special_code(void) processed = 1; break; case 'L': /* shift display left */ - lcd.left_shift++; lcd_write_cmd(0x18); processed = 1; break; case 'R': /* shift display right */ - lcd.left_shift--; lcd_write_cmd(0x1C); processed = 1; break; @@ -1157,7 +1152,6 @@ static inline int handle_lcd_special_code(void) } case 'I': /* reinitialize display */ lcd_init_display(); - lcd.left_shift = 0; processed = 1; break; case 'G': { -- cgit v0.10.2 From 2114924a9e94b741bf5dd53fb66970de5dcf7e46 Mon Sep 17 00:00:00 2001 From: Mariusz Gorski Date: Fri, 5 Dec 2014 22:28:19 +0100 Subject: staging: panel: Remove magic numbers in LCD commands Get rid of magic numbers in LCD commands and replace them with defined values, so that it's more obvious that the commands are doing. Signed-off-by: Mariusz Gorski Acked-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index b68a9c3..9c68ccf 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -130,6 +130,30 @@ #define LCD_FLAG_N 0x0040 /* 2-rows mode */ #define LCD_FLAG_L 0x0080 /* backlight enabled */ +/* LCD commands */ +#define LCD_CMD_DISPLAY_CLEAR 0x01 /* Clear entire display */ + +#define LCD_CMD_ENTRY_MODE 0x04 /* Set entry mode */ +#define LCD_CMD_CURSOR_INC 0x02 /* Increment cursor */ + +#define LCD_CMD_DISPLAY_CTRL 0x08 /* Display control */ +#define LCD_CMD_DISPLAY_ON 0x04 /* Set display on */ +#define LCD_CMD_CURSOR_ON 0x02 /* Set cursor on */ +#define LCD_CMD_BLINK_ON 0x01 /* Set blink on */ + +#define LCD_CMD_SHIFT 0x10 /* Shift cursor/display */ +#define LCD_CMD_DISPLAY_SHIFT 0x08 /* Shift display instead of cursor */ +#define LCD_CMD_SHIFT_RIGHT 0x04 /* Shift display/cursor to the right */ + +#define LCD_CMD_FUNCTION_SET 0x20 /* Set function */ +#define LCD_CMD_DATA_LEN_8BITS 0x10 /* Set data length to 8 bits */ +#define LCD_CMD_TWO_LINES 0x08 /* Set to two display lines */ +#define LCD_CMD_FONT_5X10_DOTS 0x04 /* Set char font to 5x10 dots */ + +#define LCD_CMD_SET_CGRAM_ADDR 0x40 /* Set char generator RAM address */ + +#define LCD_CMD_SET_DDRAM_ADDR 0x80 /* Set display data RAM address */ + #define LCD_ESCAPE_LEN 24 /* max chars for LCD escape command */ #define LCD_ESCAPE_CHAR 27 /* use char 27 for escape command */ @@ -883,7 +907,7 @@ static void lcd_write_data_tilcd(int data) static void lcd_gotoxy(void) { - lcd_write_cmd(0x80 /* set DDRAM address */ + lcd_write_cmd(LCD_CMD_SET_DDRAM_ADDR | (lcd.addr.y ? lcd.hwidth : 0) /* we force the cursor to stay at the end of the line if it wants to go farther */ @@ -991,7 +1015,7 @@ static void lcd_clear_fast_tilcd(void) /* clears the display and resets X/Y */ static void lcd_clear_display(void) { - lcd_write_cmd(0x01); /* clear display */ + lcd_write_cmd(LCD_CMD_DISPLAY_CLEAR); lcd.addr.x = 0; lcd.addr.y = 0; /* we must wait a few milliseconds (15) */ @@ -1005,26 +1029,29 @@ static void lcd_init_display(void) long_sleep(20); /* wait 20 ms after power-up for the paranoid */ - lcd_write_cmd(0x30); /* 8bits, 1 line, small fonts */ + /* 8bits, 1 line, small fonts; let's do it 3 times */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); long_sleep(10); - lcd_write_cmd(0x30); /* 8bits, 1 line, small fonts */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); long_sleep(10); - lcd_write_cmd(0x30); /* 8bits, 1 line, small fonts */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); long_sleep(10); - lcd_write_cmd(0x30 /* set font height and lines number */ - | ((lcd.flags & LCD_FLAG_F) ? 4 : 0) - | ((lcd.flags & LCD_FLAG_N) ? 8 : 0) + /* set font height and lines number */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS + | ((lcd.flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) + | ((lcd.flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0) ); long_sleep(10); - lcd_write_cmd(0x08); /* display off, cursor off, blink off */ + /* display off, cursor off, blink off */ + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL); long_sleep(10); - lcd_write_cmd(0x08 /* set display mode */ - | ((lcd.flags & LCD_FLAG_D) ? 4 : 0) - | ((lcd.flags & LCD_FLAG_C) ? 2 : 0) - | ((lcd.flags & LCD_FLAG_B) ? 1 : 0) + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL /* set display mode */ + | ((lcd.flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) + | ((lcd.flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) + | ((lcd.flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0) ); lcd_backlight((lcd.flags & LCD_FLAG_L) ? 1 : 0); @@ -1032,7 +1059,7 @@ static void lcd_init_display(void) long_sleep(10); /* entry mode set : increment, cursor shifting */ - lcd_write_cmd(0x06); + lcd_write_cmd(LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC); lcd_clear_display(); } @@ -1116,7 +1143,7 @@ static inline int handle_lcd_special_code(void) if (lcd.addr.x > 0) { /* back one char if not at end of line */ if (lcd.addr.x < lcd.bwidth) - lcd_write_cmd(0x10); + lcd_write_cmd(LCD_CMD_SHIFT); lcd.addr.x--; } processed = 1; @@ -1124,19 +1151,20 @@ static inline int handle_lcd_special_code(void) case 'r': /* shift cursor right */ if (lcd.addr.x < lcd.width) { /* allow the cursor to pass the end of the line */ - if (lcd.addr.x < - (lcd.bwidth - 1)) - lcd_write_cmd(0x14); + if (lcd.addr.x < (lcd.bwidth - 1)) + lcd_write_cmd(LCD_CMD_SHIFT | + LCD_CMD_SHIFT_RIGHT); lcd.addr.x++; } processed = 1; break; case 'L': /* shift display left */ - lcd_write_cmd(0x18); + lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT); processed = 1; break; case 'R': /* shift display right */ - lcd_write_cmd(0x1C); + lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT | + LCD_CMD_SHIFT_RIGHT); processed = 1; break; case 'k': { /* kill end of line */ @@ -1205,7 +1233,7 @@ static inline int handle_lcd_special_code(void) esc++; } - lcd_write_cmd(0x40 | (cgaddr * 8)); + lcd_write_cmd(LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8)); for (addr = 0; addr < cgoffset; addr++) lcd_write_data(cgbytes[addr]); @@ -1238,21 +1266,29 @@ static inline int handle_lcd_special_code(void) break; } + /* TODO: This indent party here got ugly, clean it! */ /* Check whether one flag was changed */ if (oldflags != lcd.flags) { /* check whether one of B,C,D flags were changed */ if ((oldflags ^ lcd.flags) & (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D)) /* set display mode */ - lcd_write_cmd(0x08 - | ((lcd.flags & LCD_FLAG_D) ? 4 : 0) - | ((lcd.flags & LCD_FLAG_C) ? 2 : 0) - | ((lcd.flags & LCD_FLAG_B) ? 1 : 0)); + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL + | ((lcd.flags & LCD_FLAG_D) + ? LCD_CMD_DISPLAY_ON : 0) + | ((lcd.flags & LCD_FLAG_C) + ? LCD_CMD_CURSOR_ON : 0) + | ((lcd.flags & LCD_FLAG_B) + ? LCD_CMD_BLINK_ON : 0)); /* check whether one of F,N flags was changed */ else if ((oldflags ^ lcd.flags) & (LCD_FLAG_F | LCD_FLAG_N)) - lcd_write_cmd(0x30 - | ((lcd.flags & LCD_FLAG_F) ? 4 : 0) - | ((lcd.flags & LCD_FLAG_N) ? 8 : 0)); + lcd_write_cmd(LCD_CMD_FUNCTION_SET + | LCD_CMD_DATA_LEN_8BITS + | ((lcd.flags & LCD_FLAG_F) + ? LCD_CMD_TWO_LINES : 0) + | ((lcd.flags & LCD_FLAG_N) + ? LCD_CMD_FONT_5X10_DOTS + : 0)); /* check whether L flag was changed */ else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L)) { if (lcd.flags & (LCD_FLAG_L)) @@ -1291,13 +1327,13 @@ static void lcd_write_char(char c) end of the line */ if (lcd.addr.x < lcd.bwidth) /* back one char */ - lcd_write_cmd(0x10); + lcd_write_cmd(LCD_CMD_SHIFT); lcd.addr.x--; } /* replace with a space */ lcd_write_data(' '); /* back one char again */ - lcd_write_cmd(0x10); + lcd_write_cmd(LCD_CMD_SHIFT); break; case '\014': /* quickly clear the display */ -- cgit v0.10.2 From b7c9cd450baed139ed07c997071ec5b3164ee1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Brinkmann?= Date: Thu, 4 Dec 2014 20:33:41 -0800 Subject: staging: vt6655: Declare vnt_init() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix sparse warning: drivers/staging/vt6655/device_main.c:1672:5: warning: symbol 'vnt_init' was not declared. Should it be static? Signed-off-by: Sören Brinkmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 83e4162..a3f5cd8 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1669,7 +1669,7 @@ static const struct ieee80211_ops vnt_mac_ops = { .reset_tsf = vnt_reset_tsf, }; -int vnt_init(struct vnt_private *priv) +static int vnt_init(struct vnt_private *priv) { SET_IEEE80211_PERM_ADDR(priv->hw, priv->abyCurrentNetAddr); -- cgit v0.10.2 From ccc103f564d992bb3260a9195980b26098384943 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Mon, 8 Dec 2014 12:13:41 +0100 Subject: staging: vt6656: Use ether_addr_copy() in vnt_fill_ieee80211_rts. Both struct ieee80211_rts and struct ieee80211_hdr defined in linux/ieee80211.h are declared as __aligned(2) so it is safe to use ether_addr_copy() instead of memcpy(). Signed-off-by: Krzysztof Adamski Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index ea5140a..280c923 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -36,6 +36,7 @@ * */ +#include #include "device.h" #include "rxtx.h" #include "card.h" @@ -392,8 +393,8 @@ static int vnt_fill_ieee80211_rts(struct vnt_usb_send_context *tx_context, rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); - memcpy(rts->ra, hdr->addr1, ETH_ALEN); - memcpy(rts->ta, hdr->addr2, ETH_ALEN); + ether_addr_copy(rts->ra, hdr->addr1); + ether_addr_copy(rts->ta, hdr->addr2); return 0; } -- cgit v0.10.2 From e2382233ad0251698ff7a1124cd330e5f6ecab8a Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Tue, 9 Dec 2014 12:01:38 +0100 Subject: staging: vt6656: Use ether_addr_copy() on vnt_private members. This patch fixes checkpatch.pl warning: WARNING: Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2) current_net_addr and permanent_net_addr members of vnt_private alignment is changed to at last 16 bits so that ether_addr_copy can be safely used on them. buf->data is of type ieee80211_cts which is already properly aligned. Signed-off-by: Krzysztof Adamski Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 5a7ca52..4dcc67d 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -307,8 +307,8 @@ struct vnt_private { struct vnt_cmd_card_init init_command; struct vnt_rsp_card_init init_response; - u8 current_net_addr[ETH_ALEN]; - u8 permanent_net_addr[ETH_ALEN]; + u8 current_net_addr[ETH_ALEN] __aligned(2); + u8 permanent_net_addr[ETH_ALEN] __aligned(2); u8 exist_sw_net_addr; diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index b95d5b1..71adc1f 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -34,6 +34,7 @@ */ #undef __NO_VERSION__ +#include #include #include "device.h" #include "card.h" @@ -319,7 +320,7 @@ static int vnt_init_registers(struct vnt_private *priv) /* get permanent network address */ memcpy(priv->permanent_net_addr, init_rsp->net_addr, 6); - memcpy(priv->current_net_addr, priv->permanent_net_addr, ETH_ALEN); + ether_addr_copy(priv->current_net_addr, priv->permanent_net_addr); /* if exist SW network address, use it */ dev_dbg(&priv->usb->dev, "Network address = %pM\n", diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 280c923..75d2c5e 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -553,7 +553,7 @@ static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, buf->data.frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); - memcpy(buf->data.ra, priv->current_net_addr, ETH_ALEN); + ether_addr_copy(buf->data.ra, priv->current_net_addr); return vnt_rxtx_datahead_g_fb(tx_context, &buf->data_head); } else { @@ -571,7 +571,7 @@ static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, buf->data.frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); - memcpy(buf->data.ra, priv->current_net_addr, ETH_ALEN); + ether_addr_copy(buf->data.ra, priv->current_net_addr); return vnt_rxtx_datahead_g(tx_context, &buf->data_head); } -- cgit v0.10.2 From 99ae87e7554e9bb0e34930eaebef6a5e775314bd Mon Sep 17 00:00:00 2001 From: Fred Chou Date: Wed, 10 Dec 2014 13:50:16 +0800 Subject: staging: vt6655: remove unused function in mac.c Removed the unused function MACvGetShortRetryLimit, which also fixed the following sparse warning: drivers/staging/vt6655/mac.c:162:6: warning: symbol 'MACvGetShortRetryLimit' was not declared. Should it be static? Signed-off-by: Fred Chou Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 8f0d652..09a91d1 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -30,7 +30,6 @@ * MACbIsRegBitsOff - Test if All test Bits Off * MACbIsIntDisable - Test if MAC interrupt disable * MACvSetShortRetryLimit - Set 802.11 Short Retry limit - * MACvGetShortRetryLimit - Get 802.11 Short Retry limit * MACvSetLongRetryLimit - Set 802.11 Long Retry limit * MACvSetLoopbackMode - Set MAC Loopback Mode * MACvSaveContext - Save Context of MAC Registers @@ -146,24 +145,6 @@ void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit) VNSvOutPortB(dwIoBase + MAC_REG_SRT, byRetryLimit); } -/* - * Description: - * Get 802.11 Short Retry Limit - * - * Parameters: - * In: - * dwIoBase - Base Address for MAC - * Out: - * pbyRetryLimit - Retry Limit Get - * - * Return Value: none - * - */ -void MACvGetShortRetryLimit(void __iomem *dwIoBase, unsigned char *pbyRetryLimit) -{ - // get SRT - VNSvInPortB(dwIoBase + MAC_REG_SRT, pbyRetryLimit); -} /* * Description: -- cgit v0.10.2 From 73c4c6eee1e2daec2ab2934be13717a82543c9b8 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Wed, 10 Dec 2014 18:05:31 +0100 Subject: staging: vt6656: whitespace checkpatch warning fix. This fixes following checkpatch.pl error: ERROR: space prohibited before that ',' (ctx:WxW) Signed-off-by: Krzysztof Adamski Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 75d2c5e..95d82eb 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -56,7 +56,7 @@ static const u16 vnt_fb_opt0[2][5] = { static const u16 vnt_fb_opt1[2][5] = { {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, /* fallback_rate0 */ - {RATE_6M , RATE_6M, RATE_12M, RATE_12M, RATE_18M}, /* fallback_rate1 */ + {RATE_6M, RATE_6M, RATE_12M, RATE_12M, RATE_18M}, /* fallback_rate1 */ }; #define RTSDUR_BB 0 -- cgit v0.10.2 From c3dd5a08d736c590603a514e423f76fb4153ae56 Mon Sep 17 00:00:00 2001 From: Nicholas Parkanyi Date: Tue, 30 Dec 2014 04:57:44 -0500 Subject: staging: vt6655: Replace C99 comments in power.c and upc.h. This patch fixes the following checkpatch.pl warnings: ERROR: do not use C99 // comments +// ERROR: do not use C99 // comments +// For memory mapped IO ERROR: do not use C99 // comments +// ERROR: do not use C99 // comments +#endif // __UPC_H__ ERROR: do not use C99 // comments + // set period of power up before TBTT ERROR: do not use C99 // comments + // set AID ERROR: do not use C99 // comments + // set ATIM Window ERROR: do not use C99 // comments + // Set AutoSleep ERROR: do not use C99 // comments + // Set HWUTSF ERROR: do not use C99 // comments + // clear always listen beacon ERROR: do not use C99 // comments + // first time set listen next beacon ERROR: do not use C99 // comments + // always listen beacon ERROR: do not use C99 // comments + // enable power saving hw function ERROR: do not use C99 // comments + // disable power saving hw function ERROR: do not use C99 // comments + //clear AutoSleep ERROR: do not use C99 // comments + //clear HWUTSF ERROR: do not use C99 // comments + // set always listen beacon Signed-off-by: Nicholas Parkanyi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index e826f07..be3c4e9 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -71,33 +71,33 @@ PSvEnablePowerSaving( struct vnt_private *pDevice = hDeviceContext; u16 wAID = pDevice->current_aid | BIT(14) | BIT(15); - // set period of power up before TBTT + /* set period of power up before TBTT */ VNSvOutPortW(pDevice->PortOffset + MAC_REG_PWBT, C_PWBT); if (pDevice->op_mode != NL80211_IFTYPE_ADHOC) { - // set AID + /* set AID */ VNSvOutPortW(pDevice->PortOffset + MAC_REG_AIDATIM, wAID); } else { - // set ATIM Window + /* set ATIM Window */ #if 0 /* TODO atim window */ MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow); #endif } - // Set AutoSleep + /* Set AutoSleep */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); - // Set HWUTSF + /* Set HWUTSF */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); if (wListenInterval >= 2) { - // clear always listen beacon + /* clear always listen beacon */ MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); - // first time set listen next beacon + /* first time set listen next beacon */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); } else { - // always listen beacon + /* always listen beacon */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); } - // enable power saving hw function + /* enable power saving hw function */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN); pDevice->bEnablePSMode = true; @@ -122,13 +122,13 @@ PSvDisablePowerSaving( { struct vnt_private *pDevice = hDeviceContext; - // disable power saving hw function + /* disable power saving hw function */ MACbPSWakeup(pDevice->PortOffset); - //clear AutoSleep + /* clear AutoSleep */ MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); - //clear HWUTSF + /* clear HWUTSF */ MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); - // set always listen beacon + /* set always listen beacon */ MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); pDevice->bEnablePSMode = false; diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h index c53703a..cc63dc8 100644 --- a/drivers/staging/vt6655/upc.h +++ b/drivers/staging/vt6655/upc.h @@ -33,9 +33,9 @@ /*--------------------- Export Definitions -------------------------*/ -// -// For memory mapped IO -// + +/* For memory mapped IO */ + #define VNSvInPortB(dwIOAddress, pbyData) \ do { \ @@ -86,4 +86,4 @@ do { \ /*--------------------- Export Functions --------------------------*/ -#endif // __UPC_H__ +#endif /* __UPC_H__ */ -- cgit v0.10.2 From 527ef70d1a45c31264edfabbcb49135a6adaca98 Mon Sep 17 00:00:00 2001 From: Sakshi Bansal Date: Thu, 8 Jan 2015 22:07:41 +0530 Subject: Staging: vt6655: baseband.c: fixed line over 80 characters Signed-off-by: Sakshi Bansal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index 86c72ba..c138f9b 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -27,7 +27,8 @@ * * Functions: * BBuGetFrameTime - Calculate data frame transmitting time - * BBvCaculateParameter - Caculate PhyLength, PhyService and Phy Signal parameter for baseband Tx + * BBvCaculateParameter - Caculate PhyLength, PhyService and Phy Signal + * parameter for baseband Tx * BBbReadEmbedded - Embedded read baseband register via MAC * BBbWriteEmbedded - Embedded write baseband register via MAC * BBbVT3253Init - VIA VT3253 baseband chip init code -- cgit v0.10.2 From bc22b4978d06e270372dc243f9341d921346f35a Mon Sep 17 00:00:00 2001 From: Piotr Kubus Date: Sat, 10 Jan 2015 15:35:45 +0100 Subject: Staging: vt6655: fix a space coding style issue Fixed a space coding style issue found by checkpatch.pl in rxtx.c. Signed-off-by: Piotr Kubus Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 61c39dd..8047838 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -205,7 +205,7 @@ s_uGetRTSCTSRsvTime( unsigned short wCurrentRate ) { - unsigned int uRrvTime , uRTSTime, uCTSTime, uAckTime, uDataTime; + unsigned int uRrvTime, uRTSTime, uCTSTime, uAckTime, uDataTime; uRrvTime = uRTSTime = uCTSTime = uAckTime = uDataTime = 0; -- cgit v0.10.2 From 95775d12219285d6e0116acb6267864582cd01ef Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 11 Jan 2015 10:26:12 +0000 Subject: staging: vt6655: [BUG] Protect MACvSelectPage1 with lock. The device must not flip to page 1 while in interrupt lock causing loss of connection or dead lock. Protect from changes to page by adding lock where user can change the page in CARDvSetRSPINF, vnt_configure and set_channel Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index a079640..47801ca 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -670,6 +670,9 @@ void CARDvSetRSPINF(struct vnt_private *pDevice, u8 bb_type) { union vnt_phy_field_swap phy; unsigned char byTxRate, byRsvTime; /* For OFDM */ + unsigned long flags; + + spin_lock_irqsave(&pDevice->lock, flags); /* Set to Page1 */ MACvSelectPage1(pDevice->PortOffset); @@ -767,6 +770,8 @@ void CARDvSetRSPINF(struct vnt_private *pDevice, u8 bb_type) VNSvOutPortW(pDevice->PortOffset + MAC_REG_RSPINF_A_72, MAKEWORD(byTxRate, byRsvTime)); /* Set to Page0 */ MACvSelectPage0(pDevice->PortOffset); + + spin_unlock_irqrestore(&pDevice->lock, flags); } void CARDvUpdateBasicTopRate(struct vnt_private *pDevice) diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index c8f739d..983d9cb 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -202,6 +202,10 @@ bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel) BBvSoftwareReset(pDevice); if (pDevice->byLocalID > REV_ID_VT3253_B1) { + unsigned long flags; + + spin_lock_irqsave(&pDevice->lock, flags); + /* set HW default power register */ MACvSelectPage1(pDevice->PortOffset); RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh); @@ -209,6 +213,8 @@ bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel) RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh); VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWROFDM, pDevice->byCurPwr); MACvSelectPage0(pDevice->PortOffset); + + spin_unlock_irqrestore(&pDevice->lock, flags); } if (pDevice->byBBType == BB_TYPE_11B) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index a3f5cd8..f5cc78e 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1565,6 +1565,10 @@ static void vnt_configure(struct ieee80211_hw *hw, if (changed_flags & FIF_ALLMULTI) { if (*total_flags & FIF_ALLMULTI) { + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + if (priv->mc_list_count > 2) { MACvSelectPage1(priv->PortOffset); @@ -1586,6 +1590,8 @@ static void vnt_configure(struct ieee80211_hw *hw, MACvSelectPage0(priv->PortOffset); } + spin_unlock_irqrestore(&priv->lock, flags); + rx_mode |= RCR_MULTICAST | RCR_BROADCAST; } else { rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST); -- cgit v0.10.2 From b1797dfda6ed418a519e5460b8bf111651307656 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 11 Jan 2015 16:18:00 -0600 Subject: Staging: vt6655: Fixed a typo Fixed a typo in mac.c file. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 09a91d1..63c9c7e 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -337,7 +337,7 @@ bool MACbSafeSoftwareReset(void __iomem *dwIoBase) /* * Description: - * Trun Off MAC Rx + * Turn Off MAC Rx * * Parameters: * In: @@ -398,7 +398,7 @@ bool MACbSafeRxOff(void __iomem *dwIoBase) /* * Description: - * Trun Off MAC Tx + * Turn Off MAC Tx * * Parameters: * In: -- cgit v0.10.2 From 733b3b07943418f020acf3ff69b65bce010806d3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 11 Jan 2015 16:35:54 -0600 Subject: Staging: vt6656: Fixed typo in a macro name Fixed typo in a macro name in card.c and device.h files. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index 9340f15..67ff13f 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c @@ -78,7 +78,7 @@ void vnt_set_channel(struct vnt_private *priv, u32 connection_channel) /* Set Channel[7] = 0 to tell H/W channel is changing now. */ vnt_mac_reg_bits_off(priv, MAC_REG_CHANNEL, 0xb0); - vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNLE, + vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNEL, connection_channel, 0, 0, NULL); vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL, diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 4dcc67d..f71d59f 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -160,7 +160,7 @@ #define MESSAGE_TYPE_CLRKEYENTRY 0x9 #define MESSAGE_TYPE_WRITE_MISCFF 0xa #define MESSAGE_TYPE_SET_ANTMD 0xb -#define MESSAGE_TYPE_SELECT_CHANNLE 0xc +#define MESSAGE_TYPE_SELECT_CHANNEL 0xc #define MESSAGE_TYPE_SET_TSFTBTT 0xd #define MESSAGE_TYPE_SET_SSTIFS 0xe #define MESSAGE_TYPE_CHANGE_BBTYPE 0xf -- cgit v0.10.2 From ffad440b73ddc9e8636209e84be7e97558ce29e8 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 11 Jan 2015 16:46:45 -0600 Subject: Staging: vt6656: Fixed typo in a variable name Fixed typo in a variable name in dpc.h file. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/dpc.h b/drivers/staging/vt6656/dpc.h index fab195f..95e0e83 100644 --- a/drivers/staging/vt6656/dpc.h +++ b/drivers/staging/vt6656/dpc.h @@ -32,6 +32,6 @@ #include "device.h" int vnt_rx_data(struct vnt_private *, struct vnt_rcb *, - unsigned long bytes_recieved); + unsigned long bytes_received); #endif /* __RXTX_H__ */ -- cgit v0.10.2 From 09a7a6b5d8b026dd25b1e047e4920e4baa150105 Mon Sep 17 00:00:00 2001 From: Emrys Bayliss Date: Tue, 13 Jan 2015 03:51:36 +1100 Subject: Staging: vt6656: Checkpatch fix: else after break or return This patch fixes the following checkpatch.pl error: rxtx.c:588: WARNING: else is not generally useful after a break or return Signed-off-by: Emrys Bayliss Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 95d82eb..bb6a4d4 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -575,8 +575,6 @@ static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, return vnt_rxtx_datahead_g(tx_context, &buf->data_head); } - - return 0; } static u16 vnt_rxtx_rts(struct vnt_usb_send_context *tx_context, -- cgit v0.10.2 From 3002b1a60181ae628bce068733c873fe6575ee99 Mon Sep 17 00:00:00 2001 From: Paul Hedman Date: Tue, 2 Dec 2014 20:34:13 -0600 Subject: Staging: rtl8712: Fixes brace coding style in rtl871x_sta_mgt.c This patch fixes a brace warning in rtl871x_sta_mgt.c found by the checkpatch.pl tool. Signed-off-by: Paul Hedman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c index 4c9b98e..de8acc1 100644 --- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c +++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c @@ -83,9 +83,8 @@ static void mfree_all_stainfo(struct sta_priv *pstapriv) spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL); phead = &pstapriv->free_sta_queue.queue; plist = phead->next; - while ((end_of_queue_search(phead, plist)) == false) { + while ((end_of_queue_search(phead, plist)) == false) plist = plist->next; - } spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL); } -- cgit v0.10.2 From ef4c65351a3daf572fb3c0bad3dd4baba51e817d Mon Sep 17 00:00:00 2001 From: Anjana Sasindran Date: Wed, 3 Dec 2014 21:42:09 +0530 Subject: staging: rtl8723au: hal: Removed spaces before semicolon This patch fix the checkpatch.pl warning: WARNING: space prohibited before semicolon Signed-off-by: Anjana Sasindran Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/odm_HWConfig.c b/drivers/staging/rtl8723au/hal/odm_HWConfig.c index fb3cc87..33aafa0 100644 --- a/drivers/staging/rtl8723au/hal/odm_HWConfig.c +++ b/drivers/staging/rtl8723au/hal/odm_HWConfig.c @@ -113,7 +113,7 @@ static void odm_RxPhyStatus92CSeries_Parsing(struct dm_odm_t *pDM_Odm, cck_highpwr = pDM_Odm->bCckHighPower; - cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a ; + cck_agc_rpt = pPhyStaRpt->cck_agc_rpt_ofdm_cfosho_a; /* The RSSI formula should be modified according to the gain table */ if (!cck_highpwr) { @@ -138,16 +138,16 @@ static void odm_RxPhyStatus92CSeries_Parsing(struct dm_odm_t *pDM_Odm, report = (cck_agc_rpt & 0x60)>>5; switch (report) { case 0x3: - rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f)<<1) ; + rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f)<<1); break; case 0x2: rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f)<<1); break; case 0x1: - rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f)<<1) ; + rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f)<<1); break; case 0x0: - rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f)<<1) ; + rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f)<<1); break; } } -- cgit v0.10.2 From 069b000ce432667ec6754572dda920b729d0a73c Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:43 -0500 Subject: staging: rtl8723au: usb_dvobj_init(): A NULL pointer check for usb_host_endpoints makes no sense struct usb_host_interface points to an array of struct usb_host_endpoints - it makes no sense to do a NULL pointer check for each pointer. Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/os_dep/usb_intf.c b/drivers/staging/rtl8723au/os_dep/usb_intf.c index 373a617..5007349 100644 --- a/drivers/staging/rtl8723au/os_dep/usb_intf.c +++ b/drivers/staging/rtl8723au/os_dep/usb_intf.c @@ -80,11 +80,9 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) struct usb_config_descriptor *pconf_desc; struct usb_host_interface *phost_iface; struct usb_interface_descriptor *piface_desc; - struct usb_host_endpoint *phost_endp; struct usb_endpoint_descriptor *pendp_desc; - struct usb_device *pusbd; - int i; - int status = _FAIL; + struct usb_device *pusbd; + int i, status = _FAIL; pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL); if (!pdvobjpriv) @@ -114,42 +112,38 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf) pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints; for (i = 0; i < pdvobjpriv->nr_endpoint; i++) { - phost_endp = phost_iface->endpoint + i; - if (phost_endp) { - pendp_desc = &phost_endp->desc; - - DBG_8723A("\nusb_endpoint_descriptor(%d):\n", i); - DBG_8723A("bLength =%x\n", pendp_desc->bLength); - DBG_8723A("bDescriptorType =%x\n", - pendp_desc->bDescriptorType); - DBG_8723A("bEndpointAddress =%x\n", - pendp_desc->bEndpointAddress); - DBG_8723A("wMaxPacketSize =%d\n", - le16_to_cpu(pendp_desc->wMaxPacketSize)); - DBG_8723A("bInterval =%x\n", pendp_desc->bInterval); - - if (usb_endpoint_is_bulk_in(pendp_desc)) { - DBG_8723A("usb_endpoint_is_bulk_in = %x\n", - usb_endpoint_num(pendp_desc)); - pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumInPipes++; - } else if (usb_endpoint_is_int_in(pendp_desc)) { - DBG_8723A("usb_endpoint_is_int_in = %x, Interval = %x\n", - usb_endpoint_num(pendp_desc), - pendp_desc->bInterval); - pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumInPipes++; - } else if (usb_endpoint_is_bulk_out(pendp_desc)) { - DBG_8723A("usb_endpoint_is_bulk_out = %x\n", - usb_endpoint_num(pendp_desc)); - pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] = - usb_endpoint_num(pendp_desc); - pdvobjpriv->RtNumOutPipes++; - } - pdvobjpriv->ep_num[i] = usb_endpoint_num(pendp_desc); + pendp_desc = &phost_iface->endpoint[i].desc; + + DBG_8723A("\nusb_endpoint_descriptor(%d):\n", i); + DBG_8723A("bLength =%x\n", pendp_desc->bLength); + DBG_8723A("bDescriptorType =%x\n", pendp_desc->bDescriptorType); + DBG_8723A("bEndpointAddress =%x\n", + pendp_desc->bEndpointAddress); + DBG_8723A("wMaxPacketSize =%d\n", + le16_to_cpu(pendp_desc->wMaxPacketSize)); + DBG_8723A("bInterval =%x\n", pendp_desc->bInterval); + + if (usb_endpoint_is_bulk_in(pendp_desc)) { + DBG_8723A("usb_endpoint_is_bulk_in = %x\n", + usb_endpoint_num(pendp_desc)); + pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = + usb_endpoint_num(pendp_desc); + pdvobjpriv->RtNumInPipes++; + } else if (usb_endpoint_is_int_in(pendp_desc)) { + DBG_8723A("usb_endpoint_is_int_in = %x, Interval = " + "%x\n", usb_endpoint_num(pendp_desc), + pendp_desc->bInterval); + pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] = + usb_endpoint_num(pendp_desc); + pdvobjpriv->RtNumInPipes++; + } else if (usb_endpoint_is_bulk_out(pendp_desc)) { + DBG_8723A("usb_endpoint_is_bulk_out = %x\n", + usb_endpoint_num(pendp_desc)); + pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] = + usb_endpoint_num(pendp_desc); + pdvobjpriv->RtNumOutPipes++; } + pdvobjpriv->ep_num[i] = usb_endpoint_num(pendp_desc); } DBG_8723A("nr_endpoint =%d, in_num =%d, out_num =%d\n\n", pdvobjpriv->nr_endpoint, pdvobjpriv->RtNumInPipes, -- cgit v0.10.2 From 6e946f0e3b4a6214cad74a0484006d332d0d3e6f Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:44 -0500 Subject: staging: rtl8723au: Use correct register names to set parameters to reduce 80M spur Use the correct register names when setting parameters to reduce 80M spur. In addition apply updated 80M spur reduction parameters. Original patch supplied by Andrew Chang Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/usb_halinit.c b/drivers/staging/rtl8723au/hal/usb_halinit.c index febe5ce..ee17b2c 100644 --- a/drivers/staging/rtl8723au/hal/usb_halinit.c +++ b/drivers/staging/rtl8723au/hal/usb_halinit.c @@ -625,10 +625,10 @@ int rtl8723au_hal_init(struct rtw_adapter *Adapter) } /* reducing 80M spur */ - PHY_SetBBReg(Adapter, RF_T_METER, bMaskDWord, 0x0381808d); - PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff83); - PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff82); - PHY_SetBBReg(Adapter, RF_SYN_G4, bMaskDWord, 0xf2ffff83); + PHY_SetBBReg(Adapter, REG_AFE_XTAL_CTRL, bMaskDWord, 0x0381808d); + PHY_SetBBReg(Adapter, REG_AFE_PLL_CTRL, bMaskDWord, 0xf0ffff83); + PHY_SetBBReg(Adapter, REG_AFE_PLL_CTRL, bMaskDWord, 0xf0ffff82); + PHY_SetBBReg(Adapter, REG_AFE_PLL_CTRL, bMaskDWord, 0xf0ffff83); /* RFSW Control */ PHY_SetBBReg(Adapter, rFPGA0_TxInfo, bMaskDWord, 0x00000003); /* 0x804[14]= 0 */ -- cgit v0.10.2 From bb583c54bc6ddc476fe2454d4f7054403fd46071 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:45 -0500 Subject: staging: rtl8723au: Use proper enum defines Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/usb_halinit.c b/drivers/staging/rtl8723au/hal/usb_halinit.c index ee17b2c..adbf1c2 100644 --- a/drivers/staging/rtl8723au/hal/usb_halinit.c +++ b/drivers/staging/rtl8723au/hal/usb_halinit.c @@ -640,8 +640,10 @@ int rtl8723au_hal_init(struct rtw_adapter *Adapter) /* */ /* Joseph Note: Keep RfRegChnlVal for later use. */ /* */ - pHalData->RfRegChnlVal[0] = PHY_QueryRFReg(Adapter, (enum RF_RADIO_PATH)0, RF_CHNLBW, bRFRegOffsetMask); - pHalData->RfRegChnlVal[1] = PHY_QueryRFReg(Adapter, (enum RF_RADIO_PATH)1, RF_CHNLBW, bRFRegOffsetMask); + pHalData->RfRegChnlVal[0] = PHY_QueryRFReg(Adapter, RF_PATH_A, + RF_CHNLBW, bRFRegOffsetMask); + pHalData->RfRegChnlVal[1] = PHY_QueryRFReg(Adapter, RF_PATH_B, + RF_CHNLBW, bRFRegOffsetMask); if (!mac_on) { _InitQueueReservedPage(Adapter); -- cgit v0.10.2 From 65c1b6b8291bca4ecb206fc356114cd84d7e0aeb Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:46 -0500 Subject: staging: rtl8723au: Use enum for counter and avoid ugly typecast Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c index 88e91cd..e0fff53 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c @@ -1074,7 +1074,7 @@ PHY_SetBWMode23a8723A(struct rtw_adapter *Adapter, static void _PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel) { - u8 eRFPath; + enum RF_RADIO_PATH eRFPath; u32 param1, param2; struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter); @@ -1088,7 +1088,7 @@ static void _PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel) for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) { pHalData->RfRegChnlVal[eRFPath] = (pHalData->RfRegChnlVal[eRFPath] & 0xfffffc00) | param2; - PHY_SetRFReg(Adapter, (enum RF_RADIO_PATH)eRFPath, param1, + PHY_SetRFReg(Adapter, eRFPath, param1, bRFRegOffsetMask, pHalData->RfRegChnlVal[eRFPath]); } -- cgit v0.10.2 From 924a87152fa61765ebef0af3710dff6d0507f311 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:47 -0500 Subject: staging: rtl8723au: Hal8723APhyCfg.h: Remove some undefined structs and enums Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h index 688f204..66e2756 100644 --- a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h +++ b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h @@ -30,33 +30,6 @@ /*------------------------------Define structure----------------------------*/ -enum swchnlcmdid { - CmdID_End, - CmdID_SetTxPowerLevel, - CmdID_BBRegWrite10, - CmdID_WritePortUlong, - CmdID_WritePortUshort, - CmdID_WritePortUchar, - CmdID_RF_WriteReg, -}; - - -/* 1. Switch channel related */ -struct swchnlcmd { - enum swchnlcmdid CmdID; - u32 Para1; - u32 Para2; - u32 msDelay; -}; - -enum HW90_BLOCK { - HW90_BLOCK_MAC = 0, - HW90_BLOCK_PHY0 = 1, - HW90_BLOCK_PHY1 = 2, - HW90_BLOCK_RF = 3, - HW90_BLOCK_MAXIMUM = 4, /* Never use this */ -}; - enum RF_RADIO_PATH { RF_PATH_A = 0, /* Radio Path A */ RF_PATH_B = 1, /* Radio Path B */ @@ -64,7 +37,6 @@ enum RF_RADIO_PATH { }; #define CHANNEL_MAX_NUMBER 14 /* 14 is the max channel number */ -#define CHANNEL_GROUP_MAX 3 /* ch1~3, ch4~9, ch10~14 total three groups */ enum WIRELESS_MODE { WIRELESS_MODE_UNKNOWN = 0x00, @@ -82,17 +54,6 @@ enum baseband_config_type { BaseBand_Config_AGC_TAB = 1, /* Radio Path B */ }; -enum ra_offset_area { - RA_OFFSET_LEGACY_OFDM1, - RA_OFFSET_LEGACY_OFDM2, - RA_OFFSET_HT_OFDM1, - RA_OFFSET_HT_OFDM2, - RA_OFFSET_HT_OFDM3, - RA_OFFSET_HT_OFDM4, - RA_OFFSET_HT_CCK, -}; - - /* BB/RF related */ enum rf_type_8190p { RF_TYPE_MIN, /* 0 */ -- cgit v0.10.2 From b74431d518510f503056abd4b573db8b1ff23d78 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:48 -0500 Subject: staging: rtl8723au: Baseband is always configured through PHY regs Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c index e0fff53..1692c49 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c @@ -698,7 +698,7 @@ storePwrIndexDiffRateOffset(struct rtw_adapter *Adapter, u32 RegAddr, * 11/10/2008 tynli Modify to mew files. *---------------------------------------------------------------------------*/ static int -phy_ConfigBBWithPgHeaderFile(struct rtw_adapter *Adapter, u8 ConfigType) +phy_ConfigBBWithPgHeaderFile(struct rtw_adapter *Adapter) { int i; u32 *Rtl819XPHY_REGArray_Table_PG; @@ -707,17 +707,15 @@ phy_ConfigBBWithPgHeaderFile(struct rtw_adapter *Adapter, u8 ConfigType) PHY_REGArrayPGLen = Rtl8723_PHY_REG_Array_PGLength; Rtl819XPHY_REGArray_Table_PG = (u32 *)Rtl8723_PHY_REG_Array_PG; - if (ConfigType == BaseBand_Config_PHY_REG) { - for (i = 0; i < PHY_REGArrayPGLen; i = i + 3) { - storePwrIndexDiffRateOffset(Adapter, - Rtl819XPHY_REGArray_Table_PG[i], - Rtl819XPHY_REGArray_Table_PG[i+1], - Rtl819XPHY_REGArray_Table_PG[i+2]); - } + for (i = 0; i < PHY_REGArrayPGLen; i = i + 3) { + storePwrIndexDiffRateOffset(Adapter, + Rtl819XPHY_REGArray_Table_PG[i], + Rtl819XPHY_REGArray_Table_PG[i+1], + Rtl819XPHY_REGArray_Table_PG[i+2]); } return _SUCCESS; -} /* phy_ConfigBBWithPgHeaderFile */ +} static void phy_BB8192C_Config_1T(struct rtw_adapter *Adapter) @@ -768,8 +766,7 @@ phy_BB8723a_Config_ParaFile(struct rtw_adapter *Adapter) if (pEEPROM->bautoload_fail_flag == false) { pHalData->pwrGroupCnt = 0; - rtStatus = phy_ConfigBBWithPgHeaderFile(Adapter, - BaseBand_Config_PHY_REG); + rtStatus = phy_ConfigBBWithPgHeaderFile(Adapter); } if (rtStatus != _SUCCESS) diff --git a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h index 66e2756..c1b7d08 100644 --- a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h +++ b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h @@ -49,11 +49,6 @@ enum WIRELESS_MODE { WIRELESS_MODE_AC = BIT(6) }; -enum baseband_config_type { - BaseBand_Config_PHY_REG = 0, /* Radio Path A */ - BaseBand_Config_AGC_TAB = 1, /* Radio Path B */ -}; - /* BB/RF related */ enum rf_type_8190p { RF_TYPE_MIN, /* 0 */ -- cgit v0.10.2 From e855a643ed123b75a01639e2378d88816fe60b1d Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:49 -0500 Subject: staging: rtl8723au: There is no 11N pseudo PHY here Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c index 1692c49..19dc5e3 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_phycfg.c @@ -920,9 +920,6 @@ _PHY_SetBWMode23a92C(struct rtw_adapter *Adapter) u8 regBwOpMode; u8 regRRSR_RSC; - if (pHalData->rf_chip == RF_PSEUDO_11N) - return; - /* There is no 40MHz mode in RF_8225. */ if (pHalData->rf_chip == RF_8225) return; @@ -1018,10 +1015,6 @@ _PHY_SetBWMode23a92C(struct rtw_adapter *Adapter) /* PHY_SetRF8258Bandwidth(); */ break; - case RF_PSEUDO_11N: - /* Do Nothing */ - break; - case RF_6052: rtl8723a_phy_rf6052set_bw(Adapter, pHalData->CurrentChannelBW); break; @@ -1098,11 +1091,6 @@ void PHY_SwChnl8723A(struct rtw_adapter *Adapter, u8 channel) u8 tmpchannel = pHalData->CurrentChannel; bool result = true; - if (pHalData->rf_chip == RF_PSEUDO_11N) { - /* return immediately if it is peudo-phy */ - return; - } - if (channel == 0) channel = 1; diff --git a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h index c1b7d08..fa6f4ae 100644 --- a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h +++ b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h @@ -56,7 +56,6 @@ enum rf_type_8190p { RF_8256 = 2, /* 2 11b/g/n */ RF_8258 = 3, /* 3 11a/b/g/n RF */ RF_6052 = 4, /* 4 11b/g/n RF */ - RF_PSEUDO_11N = 5, /* 5, It is a temporality RF. */ }; struct bb_reg_define { -- cgit v0.10.2 From ebf0235b4c21802b10cdce6efb1296baaac2a786 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:50 -0500 Subject: staging: rtl8723au: Hal8723APhyCfg.h: Remove more unused #defines Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h index fa6f4ae..2247d98 100644 --- a/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h +++ b/drivers/staging/rtl8723au/include/Hal8723APhyCfg.h @@ -17,18 +17,8 @@ #define __INC_HAL8723PHYCFG_H__ /*--------------------------Define Parameters-------------------------------*/ -#define LOOP_LIMIT 5 -#define MAX_STALL_TIME 50 /* us */ -#define AntennaDiversityValue 0x80 -#define MAX_TXPWR_IDX_NMODE_92S 63 -#define Reset_Cnt_Limit 3 - - #define MAX_AGGR_NUM 0x0909 -/*--------------------------Define Parameters-------------------------------*/ - - /*------------------------------Define structure----------------------------*/ enum RF_RADIO_PATH { RF_PATH_A = 0, /* Radio Path A */ -- cgit v0.10.2 From 1c69cb939610f2b80d133ee24d5dd0a3c9ede7b9 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:51 -0500 Subject: staging: rtl8723au: HalPwrSeqCmdParsing23a(): Avoid unnecessary variable inits Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c b/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c index 1da4eec..33777d2 100644 --- a/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c +++ b/drivers/staging/rtl8723au/hal/HalPwrSeqCmd.c @@ -47,11 +47,11 @@ u8 HalPwrSeqCmdParsing23a(struct rtw_adapter *padapter, u8 CutVersion, u8 FabVersion, u8 InterfaceType, struct wlan_pwr_cfg PwrSeqCmd[]) { - struct wlan_pwr_cfg PwrCfgCmd = { 0 }; - u8 bPollingBit = false; + struct wlan_pwr_cfg PwrCfgCmd; + u8 bPollingBit; u32 AryIdx = 0; - u8 value = 0; - u32 offset = 0; + u8 value; + u32 offset; u32 pollingCount = 0; /* polling autoload done. */ u32 maxPollingCnt = 5000; -- cgit v0.10.2 From fc318321762615d84868a29b62c945b6deac4459 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:52 -0500 Subject: staging: rtl8723au: Hal8723PwrSeq.h: Remove PCI specific entries from the power sequence tables Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h index 4a1f58f..d2c1ff2 100644 --- a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h +++ b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h @@ -62,11 +62,9 @@ #define RTL8723A_TRANS_CARDEMU_TO_SUS \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4)|BIT(3), (BIT(4)|BIT(3))}, /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07[7:0] = 0x20 SDIO SOP option to disable BG/MB/ACK/SWR*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)|BIT(4)}, /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*Set SDIO suspend local register*/ \ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/ @@ -80,7 +78,6 @@ #define RTL8723A_TRANS_CARDEMU_TO_CARDDIS \ {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07 = 0x20 , SOP option to disable BG/MB*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), BIT(2)}, /*0x04[10] = 1, enable SW LPS*/ \ {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 1}, /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ \ {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*Set SDIO suspend local register*/ \ @@ -92,8 +89,7 @@ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, /*wait power state to suspend*/\ {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/\ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0},/*PCIe DMA start*/ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x23[4] = 1b'0 12H LDO enter normal mode*/ #define RTL8723A_TRANS_CARDEMU_TO_PDN \ @@ -106,7 +102,6 @@ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/* 0x04[15] = 0*/ #define RTL8723A_TRANS_ACT_TO_LPS \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},/*PCIe DMA stop*/ \ {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF},/*Tx Pause*/ \ {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0},/*Should be zero if no packet is transmitting*/ \ @@ -123,7 +118,6 @@ #define RTL8723A_TRANS_LPS_TO_ACT \ {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/\ {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/\ - {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*PCIe RPWM*/\ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/\ {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*. 0x08[4] = 0 switch TSF to 40M*/\ {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, /*Polling 0x109[7]= 0 TSF in 40M*/\ -- cgit v0.10.2 From 66e702ac311e26bbdf1b23e5948d48fbd8e7d236 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:53 -0500 Subject: staging: rtl8723au: Hal8723PwrSeq.h: Remove SDIO specific entries Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h index d2c1ff2..fe76221 100644 --- a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h +++ b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h @@ -39,10 +39,10 @@ * { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, comments here */ #define RTL8723A_TRANS_CARDEMU_TO_ACT \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/ \ - {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x67[0] = 0 to disable BT_GPS_SEL pins*/ \ - {0x0001, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 1, PWRSEQ_DELAY_MS},/*Delay 1ms*/ \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), 0}, /*0x00[5] = 1b'0 release analog Ips to digital , 1:isolation*/ \ + {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/ \ + {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x67[0] = 0 to disable BT_GPS_SEL pins*/ \ + {0x0001, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 1, PWRSEQ_DELAY_MS},/*Delay 1ms*/ \ + {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), 0}, /*0x00[5] = 1b'0 release analog Ips to digital , 1:isolation*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), 0},/* disable SW LPS 0x04[10]= 0*/ \ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)},/* wait till 0x04[17] = 1 power ready*/ \ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},/* release WLON reset 0x04[16]= 1*/ \ @@ -57,44 +57,28 @@ {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},/*0x4C[23] = 0x4E[7] = 0, switch DPDT_SEL_P output from register 0x65[2] */\ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, /*0x04[9] = 1 turn off MAC by HW state machine*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, /*0x00[5] = 1b'1 analog Ips to digital , 1:isolation*/ \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, /*0x20[0] = 1b'0 disable LDOA12 MACRO block*/ \ + {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, /*0x00[5] = 1b'1 analog Ips to digital , 1:isolation*/ \ + {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, /*0x20[0] = 1b'0 disable LDOA12 MACRO block*/ \ #define RTL8723A_TRANS_CARDEMU_TO_SUS \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07[7:0] = 0x20 SDIO SOP option to disable BG/MB/ACK/SWR*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ #define RTL8723A_TRANS_SUS_TO_CARDEMU \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, /*clear suspend enable and power down enable*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, /*wait power state to suspend*/\ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/ #define RTL8723A_TRANS_CARDEMU_TO_CARDDIS \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07 = 0x20 , SOP option to disable BG/MB*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 1}, /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, /*wait power state to suspend*/ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ + {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 1}, /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ #define RTL8723A_TRANS_CARDDIS_TO_CARDEMU \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, /*clear suspend enable and power down enable*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, /*wait power state to suspend*/\ {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/\ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*0x23[4] = 1b'0 12H LDO enter normal mode*/ - + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, /*0x04[12:11] = 2b'01enable WL suspend*/ #define RTL8723A_TRANS_CARDEMU_TO_PDN \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK|PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07[7:0] = 0x20 SOP option to disable BG/MB/ACK/SWR*/ \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, /*0x07[7:0] = 0x20 SOP option to disable BG/MB/ACK/SWR*/ \ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0},/* 0x04[16] = 0*/\ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)},/* 0x04[15] = 1*/ @@ -112,11 +96,9 @@ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},/*Whole BB is reset*/ \ {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x03},/*Reset MAC TRX*/ \ {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0},/*check if removed later*/ \ - {0x0093, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00},/*When driver enter Sus/ Disable, enable LOP for BT*/ \ {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)},/*Respond TxOK to scheduler*/ #define RTL8723A_TRANS_LPS_TO_ACT \ - {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/\ {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/\ {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/\ {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, /*. 0x08[4] = 0 switch TSF to 40M*/\ -- cgit v0.10.2 From 6b284c830531638e05f1bb9f03b04e6ae0316aa8 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Thu, 4 Dec 2014 16:15:54 -0500 Subject: staging: rtl8723au: Hal8723PwrSeq.h: Use BIT() define to match mask value This is a no-op change, but it improves consistency. Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h index fe76221..3771d6b 100644 --- a/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h +++ b/drivers/staging/rtl8723au/include/Hal8723PwrSeq.h @@ -70,7 +70,7 @@ #define RTL8723A_TRANS_CARDEMU_TO_CARDDIS \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 1}, /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ + {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ #define RTL8723A_TRANS_CARDDIS_TO_CARDEMU \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, /*clear suspend enable and power down enable*/ \ -- cgit v0.10.2 From 3cd87c122d3e412626d6cff973ed3e9bc14e3f72 Mon Sep 17 00:00:00 2001 From: Greg Donald Date: Wed, 3 Dec 2014 20:19:59 -0600 Subject: drivers: staging: rtl8723au: Fix "'foo * bar' should be 'foo *bar'" errors Fix checkpatch.pl "'foo * bar' should be 'foo *bar'" errors Signed-off-by: Greg Donald Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h b/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h index 0506965..7add5df 100644 --- a/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h +++ b/drivers/staging/rtl8723au/include/rtl8723a_bt-coexist.h @@ -31,8 +31,8 @@ enum rt_media_status { void BT_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt); -void BT_HaltProcess(struct rtw_adapter * padapter); -void BT_LpsLeave(struct rtw_adapter * padapter); +void BT_HaltProcess(struct rtw_adapter *padapter); +void BT_LpsLeave(struct rtw_adapter *padapter); #define BT_HsConnectionEstablished(Adapter) false @@ -1092,17 +1092,20 @@ enum hci_ext_bp_operation { BTHCI_StateMachine(_Adapter, _StateToEnter, _StateCmd, _EntryNum);\ } -void BTHCI_EventParse(struct rtw_adapter * padapter, void *pEvntData, u32 dataLen); +void BTHCI_EventParse(struct rtw_adapter *padapter, void *pEvntData, + u32 dataLen); #define BT_EventParse BTHCI_EventParse -u8 BTHCI_HsConnectionEstablished(struct rtw_adapter * padapter); -void BTHCI_UpdateBTProfileRTKToMoto(struct rtw_adapter * padapter); -void BTHCI_WifiScanNotify(struct rtw_adapter * padapter, u8 scanType); -void BTHCI_StateMachine(struct rtw_adapter * padapter, u8 StateToEnter, enum hci_state_with_cmd StateCmd, u8 EntryNum); -void BTHCI_DisconnectPeer(struct rtw_adapter * padapter, u8 EntryNum); -void BTHCI_EventNumOfCompletedDataBlocks(struct rtw_adapter * padapter); -void BTHCI_EventAMPStatusChange(struct rtw_adapter * padapter, u8 AMP_Status); -void BTHCI_DisconnectAll(struct rtw_adapter * padapter); -enum hci_status BTHCI_HandleHCICMD(struct rtw_adapter * padapter, struct packet_irp_hcicmd_data *pHciCmd); +u8 BTHCI_HsConnectionEstablished(struct rtw_adapter *padapter); +void BTHCI_UpdateBTProfileRTKToMoto(struct rtw_adapter *padapter); +void BTHCI_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType); +void BTHCI_StateMachine(struct rtw_adapter *padapter, u8 StateToEnter, + enum hci_state_with_cmd StateCmd, u8 EntryNum); +void BTHCI_DisconnectPeer(struct rtw_adapter *padapter, u8 EntryNum); +void BTHCI_EventNumOfCompletedDataBlocks(struct rtw_adapter *padapter); +void BTHCI_EventAMPStatusChange(struct rtw_adapter *padapter, u8 AMP_Status); +void BTHCI_DisconnectAll(struct rtw_adapter *padapter); +enum hci_status BTHCI_HandleHCICMD(struct rtw_adapter *padapter, + struct packet_irp_hcicmd_data *pHciCmd); /* ===== End of sync from SD7 driver COMMON/bt_hci.h ===== */ @@ -1157,9 +1160,10 @@ struct btdm_8723a_1ant { u8 bRAChanged; }; -void BTDM_1AntSignalCompensation(struct rtw_adapter * padapter, u8 *rssi_wifi, u8 *rssi_bt); -void BTDM_1AntForDhcp(struct rtw_adapter * padapter); -void BTDM_1AntBtCoexist8723A(struct rtw_adapter * padapter); +void BTDM_1AntSignalCompensation(struct rtw_adapter *padapter, + u8 *rssi_wifi, u8 *rssi_bt); +void BTDM_1AntForDhcp(struct rtw_adapter *padapter); +void BTDM_1AntBtCoexist8723A(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.h ===== */ @@ -1241,7 +1245,7 @@ struct btdm_8723a_2ant { u8 btStatus; }; -void BTDM_2AntBtCoexist8723A(struct rtw_adapter * padapter); +void BTDM_2AntBtCoexist8723A(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.h ===== */ /* ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc8723.h ===== */ @@ -1310,15 +1314,17 @@ struct bt_coexist_8723a { struct btdm_8723a_1ant btdm1Ant; }; -void BTDM_SetFwChnlInfo(struct rtw_adapter * padapter, enum rt_media_status mstatus); -u8 BTDM_IsWifiConnectionExist(struct rtw_adapter * padapter); -void BTDM_SetFw3a(struct rtw_adapter * padapter, u8 byte1, u8 byte2, u8 byte3, u8 byte4, u8 byte5); -void BTDM_QueryBtInformation(struct rtw_adapter * padapter); -void BTDM_SetSwRfRxLpfCorner(struct rtw_adapter * padapter, u8 type); -void BTDM_SetSwPenaltyTxRateAdaptive(struct rtw_adapter * padapter, u8 raType); -void BTDM_SetFwDecBtPwr(struct rtw_adapter * padapter, u8 bDecBtPwr); -u8 BTDM_BtProfileSupport(struct rtw_adapter * padapter); -void BTDM_LpsLeave(struct rtw_adapter * padapter); +void BTDM_SetFwChnlInfo(struct rtw_adapter *padapter, + enum rt_media_status mstatus); +u8 BTDM_IsWifiConnectionExist(struct rtw_adapter *padapter); +void BTDM_SetFw3a(struct rtw_adapter *padapter, u8 byte1, u8 byte2, u8 byte3, + u8 byte4, u8 byte5); +void BTDM_QueryBtInformation(struct rtw_adapter *padapter); +void BTDM_SetSwRfRxLpfCorner(struct rtw_adapter *padapter, u8 type); +void BTDM_SetSwPenaltyTxRateAdaptive(struct rtw_adapter *padapter, u8 raType); +void BTDM_SetFwDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr); +u8 BTDM_BtProfileSupport(struct rtw_adapter *padapter); +void BTDM_LpsLeave(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc8723.h ===== */ @@ -1340,8 +1346,9 @@ enum BT_A2DP_INDEX{ #define BTDM_ANT_BT 2 -void BTDM_SingleAnt(struct rtw_adapter * padapter, u8 bSingleAntOn, u8 bInterruptOn, u8 bMultiNAVOn); -void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter * padapter); +void BTDM_SingleAnt(struct rtw_adapter *padapter, u8 bSingleAntOn, + u8 bInterruptOn, u8 bMultiNAVOn); +void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.h ===== */ @@ -1361,7 +1368,8 @@ void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter * padapter); #define BT_DACSWING_M7 2 #define BT_DACSWING_M10 3 -void BTDM_DiminishWiFi(struct rtw_adapter * Adapter, u8 bDACOn, u8 bInterruptOn, u8 DACSwingLevel, u8 bNAVOn); +void BTDM_DiminishWiFi(struct rtw_adapter *Adapter, u8 bDACOn, u8 bInterruptOn, + u8 DACSwingLevel, u8 bNAVOn); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.h ===== */ @@ -1534,58 +1542,63 @@ struct bt_coexist_str { u8 fw3aVal[5]; }; -void BTDM_CheckAntSelMode(struct rtw_adapter * padapter); -void BTDM_FwC2hBtRssi(struct rtw_adapter * padapter, u8 *tmpBuf); +void BTDM_CheckAntSelMode(struct rtw_adapter *padapter); +void BTDM_FwC2hBtRssi(struct rtw_adapter *padapter, u8 *tmpBuf); #define BT_FwC2hBtRssi BTDM_FwC2hBtRssi -void BTDM_DisplayBtCoexInfo(struct rtw_adapter * padapter); +void BTDM_DisplayBtCoexInfo(struct rtw_adapter *padapter); #define BT_DisplayBtCoexInfo BTDM_DisplayBtCoexInfo -void BTDM_RejectAPAggregatedPacket(struct rtw_adapter * padapter, u8 bReject); -u8 BTDM_IsHT40(struct rtw_adapter * padapter); -u8 BTDM_Legacy(struct rtw_adapter * padapter); -void BTDM_CheckWiFiState(struct rtw_adapter * padapter); -s32 BTDM_GetRxSS(struct rtw_adapter * padapter); -u8 BTDM_CheckCoexBcnRssiState(struct rtw_adapter * padapter, u8 levelNum, u8 RssiThresh, u8 RssiThresh1); -u8 BTDM_CheckCoexRSSIState1(struct rtw_adapter * padapter, u8 levelNum, u8 RssiThresh, u8 RssiThresh1); -u8 BTDM_CheckCoexRSSIState(struct rtw_adapter * padapter, u8 levelNum, u8 RssiThresh, u8 RssiThresh1); -void BTDM_Balance(struct rtw_adapter * padapter, u8 bBalanceOn, u8 ms0, u8 ms1); -void BTDM_AGCTable(struct rtw_adapter * padapter, u8 type); -void BTDM_BBBackOffLevel(struct rtw_adapter * padapter, u8 type); -void BTDM_FWCoexAllOff(struct rtw_adapter * padapter); -void BTDM_SWCoexAllOff(struct rtw_adapter * padapter); -void BTDM_HWCoexAllOff(struct rtw_adapter * padapter); -void BTDM_CoexAllOff(struct rtw_adapter * padapter); -void BTDM_TurnOffBtCoexistBeforeEnterIPS(struct rtw_adapter * padapter); -void BTDM_SignalCompensation(struct rtw_adapter * padapter, u8 *rssi_wifi, u8 *rssi_bt); -void BTDM_UpdateCoexState(struct rtw_adapter * padapter); -u8 BTDM_IsSameCoexistState(struct rtw_adapter * padapter); -void BTDM_PWDBMonitor(struct rtw_adapter * padapter); -u8 BTDM_IsBTBusy(struct rtw_adapter * padapter); +void BTDM_RejectAPAggregatedPacket(struct rtw_adapter *padapter, u8 bReject); +u8 BTDM_IsHT40(struct rtw_adapter *padapter); +u8 BTDM_Legacy(struct rtw_adapter *padapter); +void BTDM_CheckWiFiState(struct rtw_adapter *padapter); +s32 BTDM_GetRxSS(struct rtw_adapter *padapter); +u8 BTDM_CheckCoexBcnRssiState(struct rtw_adapter *padapter, u8 levelNum, + u8 RssiThresh, u8 RssiThresh1); +u8 BTDM_CheckCoexRSSIState1(struct rtw_adapter *padapter, u8 levelNum, + u8 RssiThresh, u8 RssiThresh1); +u8 BTDM_CheckCoexRSSIState(struct rtw_adapter *padapter, u8 levelNum, + u8 RssiThresh, u8 RssiThresh1); +void BTDM_Balance(struct rtw_adapter *padapter, u8 bBalanceOn, u8 ms0, u8 ms1); +void BTDM_AGCTable(struct rtw_adapter *padapter, u8 type); +void BTDM_BBBackOffLevel(struct rtw_adapter *padapter, u8 type); +void BTDM_FWCoexAllOff(struct rtw_adapter *padapter); +void BTDM_SWCoexAllOff(struct rtw_adapter *padapter); +void BTDM_HWCoexAllOff(struct rtw_adapter *padapter); +void BTDM_CoexAllOff(struct rtw_adapter *padapter); +void BTDM_TurnOffBtCoexistBeforeEnterIPS(struct rtw_adapter *padapter); +void BTDM_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, + u8 *rssi_bt); +void BTDM_UpdateCoexState(struct rtw_adapter *padapter); +u8 BTDM_IsSameCoexistState(struct rtw_adapter *padapter); +void BTDM_PWDBMonitor(struct rtw_adapter *padapter); +u8 BTDM_IsBTBusy(struct rtw_adapter *padapter); #define BT_IsBtBusy BTDM_IsBTBusy -u8 BTDM_IsWifiBusy(struct rtw_adapter * padapter); -u8 BTDM_IsCoexistStateChanged(struct rtw_adapter * padapter); -u8 BTDM_IsWifiUplink(struct rtw_adapter * padapter); -u8 BTDM_IsWifiDownlink(struct rtw_adapter * padapter); -u8 BTDM_IsBTHSMode(struct rtw_adapter * padapter); -u8 BTDM_IsBTUplink(struct rtw_adapter * padapter); -u8 BTDM_IsBTDownlink(struct rtw_adapter * padapter); -void BTDM_AdjustForBtOperation(struct rtw_adapter * padapter); -void BTDM_ForHalt(struct rtw_adapter * padapter); -void BTDM_WifiScanNotify(struct rtw_adapter * padapter, u8 scanType); -void BTDM_WifiAssociateNotify(struct rtw_adapter * padapter, u8 action); -void BTDM_MediaStatusNotify(struct rtw_adapter * padapter, enum rt_media_status mstatus); -void BTDM_ForDhcp(struct rtw_adapter * padapter); -void BTDM_ResetActionProfileState(struct rtw_adapter * padapter); -void BTDM_SetBtCoexCurrAntNum(struct rtw_adapter * padapter, u8 antNum); +u8 BTDM_IsWifiBusy(struct rtw_adapter *padapter); +u8 BTDM_IsCoexistStateChanged(struct rtw_adapter *padapter); +u8 BTDM_IsWifiUplink(struct rtw_adapter *padapter); +u8 BTDM_IsWifiDownlink(struct rtw_adapter *padapter); +u8 BTDM_IsBTHSMode(struct rtw_adapter *padapter); +u8 BTDM_IsBTUplink(struct rtw_adapter *padapter); +u8 BTDM_IsBTDownlink(struct rtw_adapter *padapter); +void BTDM_AdjustForBtOperation(struct rtw_adapter *padapter); +void BTDM_ForHalt(struct rtw_adapter *padapter); +void BTDM_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType); +void BTDM_WifiAssociateNotify(struct rtw_adapter *padapter, u8 action); +void BTDM_MediaStatusNotify(struct rtw_adapter *padapter, + enum rt_media_status mstatus); +void BTDM_ForDhcp(struct rtw_adapter *padapter); +void BTDM_ResetActionProfileState(struct rtw_adapter *padapter); +void BTDM_SetBtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum); #define BT_SetBtCoexCurrAntNum BTDM_SetBtCoexCurrAntNum -u8 BTDM_IsActionSCO(struct rtw_adapter * padapter); -u8 BTDM_IsActionHID(struct rtw_adapter * padapter); -u8 BTDM_IsActionA2DP(struct rtw_adapter * padapter); -u8 BTDM_IsActionPAN(struct rtw_adapter * padapter); -u8 BTDM_IsActionHIDA2DP(struct rtw_adapter * padapter); -u8 BTDM_IsActionHIDPAN(struct rtw_adapter * padapter); -u8 BTDM_IsActionPANA2DP(struct rtw_adapter * padapter); -u32 BTDM_BtTxRxCounterH(struct rtw_adapter * padapter); -u32 BTDM_BtTxRxCounterL(struct rtw_adapter * padapter); +u8 BTDM_IsActionSCO(struct rtw_adapter *padapter); +u8 BTDM_IsActionHID(struct rtw_adapter *padapter); +u8 BTDM_IsActionA2DP(struct rtw_adapter *padapter); +u8 BTDM_IsActionPAN(struct rtw_adapter *padapter); +u8 BTDM_IsActionHIDA2DP(struct rtw_adapter *padapter); +u8 BTDM_IsActionHIDPAN(struct rtw_adapter *padapter); +u8 BTDM_IsActionPANA2DP(struct rtw_adapter *padapter); +u32 BTDM_BtTxRxCounterH(struct rtw_adapter *padapter); +u32 BTDM_BtTxRxCounterL(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/BTCoexist/HalBtCoexist.h ===== */ @@ -1593,14 +1606,14 @@ u32 BTDM_BtTxRxCounterL(struct rtw_adapter * padapter); #define RTS_CTS_NO_LEN_LIMIT 0 -u8 HALBT_GetPGAntNum(struct rtw_adapter * padapter); +u8 HALBT_GetPGAntNum(struct rtw_adapter *padapter); #define BT_GetPGAntNum HALBT_GetPGAntNum -void HALBT_SetKey(struct rtw_adapter * padapter, u8 EntryNum); -void HALBT_RemoveKey(struct rtw_adapter * padapter, u8 EntryNum); -u8 HALBT_IsBTExist(struct rtw_adapter * padapter); +void HALBT_SetKey(struct rtw_adapter *padapter, u8 EntryNum); +void HALBT_RemoveKey(struct rtw_adapter *padapter, u8 EntryNum); +u8 HALBT_IsBTExist(struct rtw_adapter *padapter); #define BT_IsBtExist HALBT_IsBTExist -u8 HALBT_BTChipType(struct rtw_adapter * padapter); -void HALBT_SetRtsCtsNoLenLimit(struct rtw_adapter * padapter); +u8 HALBT_BTChipType(struct rtw_adapter *padapter); +void HALBT_SetRtsCtsNoLenLimit(struct rtw_adapter *padapter); /* ===== End of sync from SD7 driver HAL/HalBT.c ===== */ diff --git a/drivers/staging/rtl8723au/include/rtl8723a_recv.h b/drivers/staging/rtl8723au/include/rtl8723a_recv.h index 0177bbc..875d37b 100644 --- a/drivers/staging/rtl8723au/include/rtl8723a_recv.h +++ b/drivers/staging/rtl8723au/include/rtl8723a_recv.h @@ -56,8 +56,8 @@ struct interrupt_msg_format { unsigned int MSG_EX; }; -int rtl8723au_init_recv_priv(struct rtw_adapter * padapter); -void rtl8723au_free_recv_priv(struct rtw_adapter * padapter); +int rtl8723au_init_recv_priv(struct rtw_adapter *padapter); +void rtl8723au_free_recv_priv(struct rtw_adapter *padapter); void rtl8723a_process_phy_info(struct rtw_adapter *padapter, void *prframe); void update_recvframe_attrib(struct recv_frame *precvframe, struct recv_stat *prxstat); void update_recvframe_phyinfo(struct recv_frame *precvframe, struct phy_stat *pphy_info); diff --git a/drivers/staging/rtl8723au/include/rtw_cmd.h b/drivers/staging/rtl8723au/include/rtw_cmd.h index 7104410..92c8ec4 100644 --- a/drivers/staging/rtl8723au/include/rtw_cmd.h +++ b/drivers/staging/rtl8723au/include/rtw_cmd.h @@ -689,10 +689,10 @@ int rtw_disassoc_cmd23a(struct rtw_adapter *padapter, u32 deauth_timeout_ms, boo int rtw_setopmode_cmd23a(struct rtw_adapter *padapter, enum nl80211_iftype ifmode); int rtw_setdatarate_cmd(struct rtw_adapter *padapter, u8 *rateset); int rtw_setbasicrate_cmd(struct rtw_adapter *padapter, u8 *rateset); -int rtw_setbbreg_cmd(struct rtw_adapter * padapter, u8 offset, u8 val); -int rtw_setrfreg_cmd(struct rtw_adapter * padapter, u8 offset, u32 val); -int rtw_getbbreg_cmd(struct rtw_adapter * padapter, u8 offset, u8 * pval); -int rtw_getrfreg_cmd(struct rtw_adapter * padapter, u8 offset, u8 * pval); +int rtw_setbbreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 val); +int rtw_setrfreg_cmd(struct rtw_adapter *padapter, u8 offset, u32 val); +int rtw_getbbreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 *pval); +int rtw_getrfreg_cmd(struct rtw_adapter *padapter, u8 offset, u8 *pval); int rtw_setrfintfs_cmd(struct rtw_adapter *padapter, u8 mode); int rtw_setrttbl_cmd(struct rtw_adapter *padapter, struct setratable_parm *prate_table); int rtw_getrttbl_cmd(struct rtw_adapter *padapter, struct getratable_rsp *pval); diff --git a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h index 51dba1f..ffb37b2 100644 --- a/drivers/staging/rtl8723au/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723au/include/rtw_mlme_ext.h @@ -509,7 +509,7 @@ int rtw_check_bcn_info23a(struct rtw_adapter *Adapter, struct ieee80211_mgmt *mgmt, u32 packet_len); void update_IOT_info23a(struct rtw_adapter *padapter); void update_capinfo23a(struct rtw_adapter *Adapter, u16 updateCap); -void update_wireless_mode23a(struct rtw_adapter * padapter); +void update_wireless_mode23a(struct rtw_adapter *padapter); void update_tx_basic_rate23a(struct rtw_adapter *padapter, u8 modulation); void update_bmc_sta_support_rate23a(struct rtw_adapter *padapter, u32 mac_id); int update_sta_support_rate23a(struct rtw_adapter *padapter, u8 *pvar_ie, -- cgit v0.10.2 From 0dc4872308dc3c19ff0173188293248419d2895d Mon Sep 17 00:00:00 2001 From: Anjana Sasindran Date: Thu, 4 Dec 2014 18:11:13 +0530 Subject: staging: rtl8723au: hal: Added blank line after declaration This patch fix the checkpatch.pl warning: WARNING: Missing blank line after declaration Signed-off-by: Anjana Sasindran Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/odm.c b/drivers/staging/rtl8723au/hal/odm.c index 1c0f106d..cabe33a 100644 --- a/drivers/staging/rtl8723au/hal/odm.c +++ b/drivers/staging/rtl8723au/hal/odm.c @@ -1435,6 +1435,7 @@ static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm) { struct rtw_adapter *Adapter = pDM_Odm->Adapter; + pDM_Odm->DM_EDCA_Table.bCurrentTurboEDCA = false; pDM_Odm->DM_EDCA_Table.bIsCurRDLState = false; Adapter->recvpriv.bIsAnyNonBEPkts = false; @@ -1591,6 +1592,7 @@ ConvertTo_dB23a( void ODM_SingleDualAntennaDefaultSetting(struct dm_odm_t *pDM_Odm) { struct sw_ant_sw *pDM_SWAT_Table = &pDM_Odm->DM_SWAT_Table; + pDM_SWAT_Table->ANTA_ON = true; pDM_SWAT_Table->ANTB_ON = true; } -- cgit v0.10.2 From 9d55c8140f510b3068edd4b47e03b230e501e9a5 Mon Sep 17 00:00:00 2001 From: Anjana Sasindran Date: Thu, 4 Dec 2014 19:20:30 +0530 Subject: staging: rtl8723au: hal: Removed space before semicolon This patch fix the checkpatch.pl warning: WARNING: spaces prohibited before semicolon Signed-off-by: Anjana Sasindran Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/odm.c b/drivers/staging/rtl8723au/hal/odm.c index cabe33a..216930a 100644 --- a/drivers/staging/rtl8723au/hal/odm.c +++ b/drivers/staging/rtl8723au/hal/odm.c @@ -983,10 +983,10 @@ void odm_1R_CCA23a(struct dm_odm_t *pDM_Odm) void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal) { struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable; - u8 Rssi_Up_bound = 30 ; + u8 Rssi_Up_bound = 30; u8 Rssi_Low_bound = 25; if (pDM_Odm->PatchID == 40) { /* RT_CID_819x_FUNAI_TV */ - Rssi_Up_bound = 50 ; + Rssi_Up_bound = 50; Rssi_Low_bound = 45; } if (pDM_PSTable->initialize == 0) { -- cgit v0.10.2 From de77b4ceae336d97a272eedbfd0047045074dca9 Mon Sep 17 00:00:00 2001 From: Anjana Sasindran Date: Fri, 5 Dec 2014 21:17:02 +0530 Subject: staging: rtl8723au: hal: Removed a space before semicolon This patch fix the checkpatch.pl warning: WARNING: space before semicolon prohibited Signed-off-by: Anjana Sasindran Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c index 86a8397..412d8cf 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c @@ -9145,7 +9145,7 @@ u32 BTDM_BtTxRxCounterL(struct rtw_adapter *padapter) u32 counters = 0; counters = pHalData->bt_coexist.halCoex8723.lowPriorityTx+ - pHalData->bt_coexist.halCoex8723.lowPriorityRx ; + pHalData->bt_coexist.halCoex8723.lowPriorityRx; return counters; } -- cgit v0.10.2 From 3895ed0b9ee9e0d731930e1fa4cdd8109b9c8ebe Mon Sep 17 00:00:00 2001 From: Dean Michael Ancajas Date: Mon, 8 Dec 2014 13:55:21 -0700 Subject: Staging: rtl8723au: os_dep: Fixed a coding style issue. Fixed a coding style issue for braces. Signed-off-by: Dean Michael Ancajas Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c index 82a8c06..9e1304f 100644 --- a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c @@ -1468,9 +1468,8 @@ static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, return 0; } - if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) { + if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK; - } /* if (wpa_version & NL80211_WPA_VERSION_2) -- cgit v0.10.2 From 4ae888b64e9512dc77b8d875c9b860447328e802 Mon Sep 17 00:00:00 2001 From: Krzysztof Konopko Date: Mon, 15 Dec 2014 16:02:14 +0100 Subject: staging: rtl8723au: Fix sparse warnings Some struct fields in wifi.h are meant to be __le16 but were declared as unsigned short. This was reported by sparse: rtw_wlan_util.c:538:24: warning: cast to restricted __le16 rtw_wlan_util.c:1544:29: warning: cast to restricted __le16 rtw_wlan_util.c:1546:25: warning: cast to restricted __le16 This patch updates the types of the fields in `AC_param` and `ADDBA_request` structs to be consistent with relevant structs in include/linux/ieee80211.h. Signed-off-by: Krzysztof Konopko Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/include/wifi.h b/drivers/staging/rtl8723au/include/wifi.h index fd3da3b..25d573c 100644 --- a/drivers/staging/rtl8723au/include/wifi.h +++ b/drivers/staging/rtl8723au/include/wifi.h @@ -26,9 +26,9 @@ ------------------------------------------------------------------------------*/ struct AC_param { - unsigned char ACI_AIFSN; - unsigned char CW; - unsigned short TXOP_limit; + u8 ACI_AIFSN; + u8 CW; + __le16 TXOP_limit; } __packed; struct WMM_para_element { @@ -38,10 +38,10 @@ struct WMM_para_element { } __packed; struct ADDBA_request { - unsigned char dialog_token; - unsigned short BA_para_set; - unsigned short BA_timeout_value; - unsigned short BA_starting_seqctrl; + u8 dialog_token; + __le16 BA_para_set; + __le16 BA_timeout_value; + __le16 BA_starting_seqctrl; } __packed; -- cgit v0.10.2 From ca439e90055743ba26dea20755217436863cb991 Mon Sep 17 00:00:00 2001 From: Asaf Vertz Date: Tue, 16 Dec 2014 15:57:58 +0200 Subject: staging: rtl8723au: core: fixing "foo * bar" should be "foo *bar" Fixed a coding style error, "foo * bar" should be "foo *bar" Signed-off-by: Asaf Vertz Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/core/rtw_efuse.c b/drivers/staging/rtl8723au/core/rtw_efuse.c index 81960e7..a6deddc 100644 --- a/drivers/staging/rtl8723au/core/rtw_efuse.c +++ b/drivers/staging/rtl8723au/core/rtw_efuse.c @@ -327,15 +327,9 @@ EFUSE_Read1Byte23a(struct rtw_adapter *Adapter, u16 Address) *---------------------------------------------------------------------------*/ void -EFUSE_Write1Byte( - struct rtw_adapter * Adapter, - u16 Address, - u8 Value); +EFUSE_Write1Byte(struct rtw_adapter *Adapter, u16 Address, u8 Value); void -EFUSE_Write1Byte( - struct rtw_adapter * Adapter, - u16 Address, - u8 Value) +EFUSE_Write1Byte(struct rtw_adapter *Adapter, u16 Address, u8 Value) { u8 Bytetemp = {0x00}; u8 temp = {0x00}; @@ -635,10 +629,7 @@ Efuse_ReadAllMap(struct rtw_adapter *pAdapter, u8 efuseType, u8 *Efuse) * *---------------------------------------------------------------------------*/ static void -efuse_ShadowRead1Byte( - struct rtw_adapter * pAdapter, - u16 Offset, - u8 *Value) +efuse_ShadowRead1Byte(struct rtw_adapter *pAdapter, u16 Offset, u8 *Value) { struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); @@ -647,10 +638,7 @@ efuse_ShadowRead1Byte( /* Read Two Bytes */ static void -efuse_ShadowRead2Byte( - struct rtw_adapter * pAdapter, - u16 Offset, - u16 *Value) +efuse_ShadowRead2Byte(struct rtw_adapter *pAdapter, u16 Offset, u16 *Value) { struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); @@ -660,10 +648,7 @@ efuse_ShadowRead2Byte( /* Read Four Bytes */ static void -efuse_ShadowRead4Byte( - struct rtw_adapter * pAdapter, - u16 Offset, - u32 *Value) +efuse_ShadowRead4Byte(struct rtw_adapter *pAdapter, u16 Offset, u32 *Value) { struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(pAdapter); @@ -722,11 +707,8 @@ void EFUSE_ShadowMapUpdate23a(struct rtw_adapter *pAdapter, u8 efuseType) * *---------------------------------------------------------------------------*/ void -EFUSE_ShadowRead23a( - struct rtw_adapter * pAdapter, - u8 Type, - u16 Offset, - u32 *Value) +EFUSE_ShadowRead23a(struct rtw_adapter *pAdapter, + u8 Type, u16 Offset, u32 *Value) { if (Type == 1) efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value); -- cgit v0.10.2 From 936601e5f4473a36cbe85acea362c2552d78f5dd Mon Sep 17 00:00:00 2001 From: Yannis Damigos Date: Sat, 20 Dec 2014 18:47:27 +0200 Subject: staging: rtl8723au: Fix sparse invalid assignment warnings This is a patch to the hal/rtl8723au_xmit.c file that fixes the following warnings found by sparse tool: drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:88:22: warning: invalid assignment: |= drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:88:22: left side has type unsigned int drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:88:22: right side has type restricted __le32 drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:91:22: warning: invalid assignment: |= drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:91:22: left side has type unsigned int drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:91:22: right side has type restricted __le32 drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:99:22: warning: invalid assignment: |= drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:99:22: left side has type unsigned int drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:99:22: right side has type restricted __le32 drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:103:30: warning: invalid assignment: |= drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:103:30: left side has type unsigned int drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:103:30: right side has type restricted __le32 drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:106:38: warning: invalid assignment: |= drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:106:38: left side has type unsigned int drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:106:38: right side has type restricted __le32 drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:108:38: warning: invalid assignment: |= drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:108:38: left side has type unsigned int drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:108:38: right side has type restricted __le32 drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:112:38: warning: invalid assignment: |= drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:112:38: left side has type unsigned int drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:112:38: right side has type restricted __le32 drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:120:22: warning: invalid assignment: |= drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:120:22: left side has type unsigned int drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:120:22: right side has type restricted __le32 drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:123:30: warning: invalid assignment: |= drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:123:30: left side has type unsigned int drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:123:30: right side has type restricted __le32 drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:125:30: warning: invalid assignment: |= drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:125:30: left side has type unsigned int drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:125:30: right side has type restricted __le32 drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:129:30: warning: invalid assignment: |= drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:129:30: left side has type unsigned int drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:129:30: right side has type restricted __le32 drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:184:51: warning: incorrect type in argument 2 (different base types) drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:184:51: expected unsigned int [usertype] *pdw drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:184:51: got restricted __le32 * drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:185:51: warning: incorrect type in argument 2 (different base types) drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:185:51: expected unsigned int [usertype] *pdw drivers/staging/rtl8723au//hal/rtl8723au_xmit.c:185:51: got restricted __le32 * Signed-off-by: Yannis Damigos Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c b/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c index 6070510..1759487 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c +++ b/drivers/staging/rtl8723au/hal/rtl8723au_xmit.c @@ -79,7 +79,7 @@ static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxd } } -static void fill_txdesc_vcs(struct pkt_attrib *pattrib, u32 *pdw) +static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw) { /* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */ @@ -114,7 +114,7 @@ static void fill_txdesc_vcs(struct pkt_attrib *pattrib, u32 *pdw) } } -static void fill_txdesc_phy(struct pkt_attrib *pattrib, u32 *pdw) +static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw) { if (pattrib->ht_en) { *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0; -- cgit v0.10.2 From 22faca217fbd50c95b117fa40670768afcf6973f Mon Sep 17 00:00:00 2001 From: Joe Borg Date: Tue, 16 Dec 2014 02:54:32 -0500 Subject: Staging: rtl8723au: core: rtw_ap: checkpatch.pl fixes Fixing styling errors found with checkpatch.pl. These include: "(foo*)" should be "(foo *)" space required after that ';' ...totalling 5 styling errors. Signed-off-by: Joe Borg Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/core/rtw_ap.c b/drivers/staging/rtl8723au/core/rtw_ap.c index e394d12..c6327c0 100644 --- a/drivers/staging/rtl8723au/core/rtw_ap.c +++ b/drivers/staging/rtl8723au/core/rtw_ap.c @@ -456,8 +456,8 @@ static void update_bmc_sta(struct rtw_adapter *padapter) sizeof(struct stainfo_stats)); /* prepare for add_RATid23a */ - supportRateNum = rtw_get_rateset_len23a((u8*)&pcur_network->SupportedRates); - network_type = rtw_check_network_type23a((u8*)&pcur_network->SupportedRates, supportRateNum, 1); + supportRateNum = rtw_get_rateset_len23a((u8 *)&pcur_network->SupportedRates); + network_type = rtw_check_network_type23a((u8 *)&pcur_network->SupportedRates, supportRateNum, 1); memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum); psta->bssratelen = supportRateNum; @@ -897,7 +897,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, pairwise_cipher = 0; psecuritypriv->wpa_group_cipher = 0; psecuritypriv->wpa_pairwise_cipher = 0; - for (p = ie; ;p += (ie_len + 2)) { + for (p = ie; ; p += (ie_len + 2)) { p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, pbss_network->IELength - (ie_len + 2)); if ((p) && (!memcmp(p+2, RTW_WPA_OUI23A_TYPE, 4))) { @@ -924,7 +924,7 @@ int rtw_check_beacon_data23a(struct rtw_adapter *padapter, ie_len = 0; pmlmepriv->qos_option = 0; if (pregistrypriv->wmm_enable) { - for (p = ie; ;p += (ie_len + 2)) { + for (p = ie; ; p += (ie_len + 2)) { p = rtw_get_ie23a(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, (pbss_network->IELength - (ie_len + 2))); @@ -1204,7 +1204,7 @@ static void update_bcn_p2p_ie(struct rtw_adapter *padapter) { } -static void update_bcn_vendor_spec_ie(struct rtw_adapter *padapter, u8*oui) +static void update_bcn_vendor_spec_ie(struct rtw_adapter *padapter, u8 *oui) { DBG_8723A("%s\n", __func__); -- cgit v0.10.2 From 539b5e0bb084fb5f54aad0de97bea55b6a2a833b Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sat, 20 Dec 2014 17:44:10 +0100 Subject: staging: rtl8723au: hal: odm.c: Remove some unused functions Removes some functions that are not used anywhere: odm_1R_CCA23a() odm_TXPowerTrackingCheckAP() odm_TXPowerTrackingCheckMP() odm_RSSIMonitorCheck23aAP() odm_RSSIMonitorCheck23aMP() odm_RSSIMonitorInit() odm_RefreshRateAdaptiveMask23aAPADSL23a() odm_RefreshRateAdaptiveMask23aMP23a() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/odm.c b/drivers/staging/rtl8723au/hal/odm.c index 216930a..5269b46 100644 --- a/drivers/staging/rtl8723au/hal/odm.c +++ b/drivers/staging/rtl8723au/hal/odm.c @@ -187,24 +187,13 @@ void odm23a_DynBBPSInit(struct dm_odm_t *pDM_Odm); void odm_DynamicBBPowerSaving23a(struct dm_odm_t *pDM_Odm); -void odm_1R_CCA23a(struct dm_odm_t *pDM_Odm); /* END---------BB POWER SAVE----------------------- */ -void odm_RefreshRateAdaptiveMask23aMP23a(struct dm_odm_t *pDM_Odm); - void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm); -void odm_RefreshRateAdaptiveMask23aAPADSL23a(struct dm_odm_t *pDM_Odm); - void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm); -void odm_RSSIMonitorInit(struct dm_odm_t *pDM_Odm); - -void odm_RSSIMonitorCheck23aMP(struct dm_odm_t *pDM_Odm); - void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm); -void odm_RSSIMonitorCheck23aAP(struct dm_odm_t *pDM_Odm); - void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm); void odm_DynamicTxPower23a(struct dm_odm_t *pDM_Odm); @@ -212,16 +201,12 @@ void odm_RefreshRateAdaptiveMask23a(struct dm_odm_t *pDM_Odm); void ODM_TXPowerTrackingCheck23a(struct dm_odm_t *pDM_Odm); -void odm_TXPowerTrackingCheckAP(struct dm_odm_t *pDM_Odm); - void odm_RateAdaptiveMaskInit23a(struct dm_odm_t *pDM_Odm); void odm_TXPowerTrackingThermalMeterInit23a(struct dm_odm_t *pDM_Odm); void odm_TXPowerTrackingInit23a(struct dm_odm_t *pDM_Odm); -void odm_TXPowerTrackingCheckMP(struct dm_odm_t *pDM_Odm); - void odm_TXPowerTrackingCheckCE23a(struct dm_odm_t *pDM_Odm); static void odm_EdcaTurboCheck23a(struct dm_odm_t *pDM_Odm); @@ -946,40 +931,6 @@ void odm_DynamicBBPowerSaving23a(struct dm_odm_t *pDM_Odm) return; } -void odm_1R_CCA23a(struct dm_odm_t *pDM_Odm) -{ - struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable; - - if (pDM_Odm->RSSI_Min != 0xFF) { - if (pDM_PSTable->PreCCAState == CCA_2R) { - if (pDM_Odm->RSSI_Min >= 35) - pDM_PSTable->CurCCAState = CCA_1R; - else - pDM_PSTable->CurCCAState = CCA_2R; - } else { - if (pDM_Odm->RSSI_Min <= 30) - pDM_PSTable->CurCCAState = CCA_2R; - else - pDM_PSTable->CurCCAState = CCA_1R; - } - } else { - pDM_PSTable->CurCCAState = CCA_MAX; - } - - if (pDM_PSTable->PreCCAState != pDM_PSTable->CurCCAState) { - if (pDM_PSTable->CurCCAState == CCA_1R) { - if (pDM_Odm->RFType == ODM_2T2R) - ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x13); - else - ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x23); - } else { - ODM_SetBBReg(pDM_Odm, 0xc04, bMaskByte0, 0x33); - /* PHY_SetBBReg(pAdapter, 0xe70, bMaskByte3, 0x63); */ - } - pDM_PSTable->PreCCAState = pDM_PSTable->CurCCAState; - } -} - void ODM_RF_Saving23a(struct dm_odm_t *pDM_Odm, u8 bForceInNormal) { struct dynamic_pwr_sav *pDM_PSTable = &pDM_Odm->DM_PSTable; @@ -1177,10 +1128,6 @@ void odm_RefreshRateAdaptiveMask23a(struct dm_odm_t *pDM_Odm) odm_RefreshRateAdaptiveMask23aCE23a(pDM_Odm); } -void odm_RefreshRateAdaptiveMask23aMP23a(struct dm_odm_t *pDM_Odm) -{ -} - void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm) { u8 i; @@ -1216,10 +1163,6 @@ void odm_RefreshRateAdaptiveMask23aCE23a(struct dm_odm_t *pDM_Odm) } -void odm_RefreshRateAdaptiveMask23aAPADSL23a(struct dm_odm_t *pDM_Odm) -{ -} - /* Return Value: bool */ /* - true: RATRState is changed. */ bool ODM_RAStateCheck23a(struct dm_odm_t *pDM_Odm, s32 RSSI, bool bForceUpdate, @@ -1284,14 +1227,6 @@ void odm_DynamicTxPower23aInit(struct dm_odm_t *pDM_Odm) pdmpriv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal; } -/* 3 ============================================================ */ -/* 3 RSSI Monitor */ -/* 3 ============================================================ */ - -void odm_RSSIMonitorInit(struct dm_odm_t *pDM_Odm) -{ -} - void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm) { /* For AP/ADSL use struct rtl8723a_priv * */ @@ -1306,10 +1241,6 @@ void odm_RSSIMonitorCheck23a(struct dm_odm_t *pDM_Odm) odm_RSSIMonitorCheck23aCE(pDM_Odm); } /* odm_RSSIMonitorCheck23a */ -void odm_RSSIMonitorCheck23aMP(struct dm_odm_t *pDM_Odm) -{ -} - static void FindMinimumRSSI( struct rtw_adapter *pAdapter @@ -1378,10 +1309,6 @@ void odm_RSSIMonitorCheck23aCE(struct dm_odm_t *pDM_Odm) ODM_CmnInfoUpdate23a(&pHalData->odmpriv, ODM_CMNINFO_RSSI_MIN, pdmpriv->MinUndecoratedPWDBForDM); } -void odm_RSSIMonitorCheck23aAP(struct dm_odm_t *pDM_Odm) -{ -} - /* endif */ /* 3 ============================================================ */ /* 3 Tx Power Tracking */ @@ -1422,14 +1349,6 @@ void odm_TXPowerTrackingCheckCE23a(struct dm_odm_t *pDM_Odm) { } -void odm_TXPowerTrackingCheckMP(struct dm_odm_t *pDM_Odm) -{ -} - -void odm_TXPowerTrackingCheckAP(struct dm_odm_t *pDM_Odm) -{ -} - /* EDCA Turbo */ static void ODM_EdcaTurboInit23a(struct dm_odm_t *pDM_Odm) { -- cgit v0.10.2 From 252949d1e1a305ea9429a93f365cb6879e3e0156 Mon Sep 17 00:00:00 2001 From: Alexey Tulia Date: Wed, 24 Dec 2014 09:15:09 +0300 Subject: staging: rtl8723au: fix sparse warning drivers/staging/rtl8723au/core/rtw_xmit.c:2375 warning: symbol 'rtw_ack_tx_done23a' was not declared. Should it be static? Function 'rtw_ack_tx_done23a' seems to be unused in current staging code. Signed-off-by: Alexey Tulia Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/core/rtw_xmit.c b/drivers/staging/rtl8723au/core/rtw_xmit.c index 7a5e6bf..1c82dff 100644 --- a/drivers/staging/rtl8723au/core/rtw_xmit.c +++ b/drivers/staging/rtl8723au/core/rtw_xmit.c @@ -2372,12 +2372,3 @@ int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms) return rtw_sctx_wait23a(pack_tx_ops); } -void rtw_ack_tx_done23a(struct xmit_priv *pxmitpriv, int status) -{ - struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops; - - if (pxmitpriv->ack_tx) - rtw23a_sctx_done_err(&pack_tx_ops, status); - else - DBG_8723A("%s ack_tx not set\n", __func__); -} -- cgit v0.10.2 From 74df1cd75966e1456274cdcf51d7e64df7aa2a58 Mon Sep 17 00:00:00 2001 From: Abel Moyo Date: Thu, 4 Dec 2014 14:13:21 +0100 Subject: Staging: rtl8188eu: {core, hal, include}: Removed inline function Removed inline function get_my_bssid and open coded all its references Signed-off-by: Abel Moyo Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index e4b7ee4c..901ede9 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -577,13 +577,14 @@ unsigned int OnBeacon(struct adapter *padapter, struct recv_frame *precv_frame) uint len = precv_frame->len; struct wlan_bssid_ex *pbss; int ret = _SUCCESS; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { report_survey_event(padapter, precv_frame); return _SUCCESS; } - if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) { + if (!memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) { if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { /* we should update current network before auth, or some IE is wrong */ pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex)); @@ -1445,10 +1446,10 @@ unsigned int OnDeAuth(struct adapter *padapter, struct recv_frame *precv_frame) struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); u8 *pframe = precv_frame->rx_data; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); /* check A3 */ - if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), - ETH_ALEN)) + if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) return _SUCCESS; reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); @@ -1499,10 +1500,10 @@ unsigned int OnDisassoc(struct adapter *padapter, struct recv_frame *precv_frame struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); u8 *pframe = precv_frame->rx_data; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); /* check A3 */ - if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), - ETH_ALEN)) + if (memcmp(GetAddr3Ptr(pframe), pnetwork->MacAddress, ETH_ALEN)) return _SUCCESS; reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); @@ -2018,7 +2019,7 @@ void issue_beacon(struct adapter *padapter, int timeout_ms) memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); + memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); /* pmlmeext->mgnt_seq++; */ @@ -2422,6 +2423,7 @@ void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (pmgntframe == NULL) @@ -2487,9 +2489,9 @@ void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short } else { __le32 le_tmp32; __le16 le_tmp16; - memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); + memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); /* setting auth algo number */ val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */ @@ -2582,7 +2584,7 @@ void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_i memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN); memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy((void *)GetAddr3Ptr(pwlanhdr), pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); @@ -2687,6 +2689,7 @@ void issue_assocreq(struct adapter *padapter) struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); int bssrate_len = 0, sta_bssrate_len = 0; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (pmgntframe == NULL) @@ -2702,9 +2705,9 @@ void issue_assocreq(struct adapter *padapter) fctrl = &(pwlanhdr->frame_ctl); *(fctrl) = 0; - memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -2879,6 +2882,7 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned struct xmit_priv *pxmitpriv; struct mlme_ext_priv *pmlmeext; struct mlme_ext_info *pmlmeinfo; + struct wlan_bssid_ex *pnetwork; if (!padapter) goto exit; @@ -2886,6 +2890,7 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned pxmitpriv = &(padapter->xmitpriv); pmlmeext = &(padapter->mlmeextpriv); pmlmeinfo = &(pmlmeext->mlmext_info); + pnetwork = &(pmlmeinfo->network); pmgntframe = alloc_mgtxmitframe(pxmitpriv); if (pmgntframe == NULL) @@ -2914,7 +2919,7 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned memcpy(pwlanhdr->addr1, da, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -2946,10 +2951,11 @@ int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int pow u32 start = jiffies; struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); /* da == NULL, assume it's null data for sta to ap*/ if (da == NULL) - da = get_my_bssid(&(pmlmeinfo->network)); + da = pnetwork->MacAddress; do { ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0 ? true : false); @@ -2995,6 +3001,7 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); DBG_88E("%s\n", __func__); @@ -3038,7 +3045,7 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 memcpy(pwlanhdr->addr1, da, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -3069,10 +3076,11 @@ int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int u32 start = jiffies; struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); /* da == NULL, assume it's null data for sta to ap*/ if (da == NULL) - da = get_my_bssid(&(pmlmeinfo->network)); + da = pnetwork->MacAddress; do { ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0 ? true : false); @@ -3115,6 +3123,7 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned s struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); int ret = _FAIL; __le16 le_tmp; @@ -3137,7 +3146,7 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned s memcpy(pwlanhdr->addr1, da, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -3288,6 +3297,7 @@ void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned ch struct sta_info *psta; struct sta_priv *pstapriv = &padapter->stapriv; struct registry_priv *pregpriv = &padapter->registrypriv; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); DBG_88E("%s, category=%d, action=%d, status=%d\n", __func__, category, action, status); @@ -3310,7 +3320,7 @@ void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned ch /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -3420,6 +3430,8 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) struct __queue *queue = &(pmlmepriv->scanned_queue); u8 InfoContent[16] = {0}; u8 ICS[8][15]; + struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); + if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0)) return; @@ -3449,9 +3461,9 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter) fctrl = &(pwlanhdr->frame_ctl); *(fctrl) = 0; - memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr1, cur_network->MacAddress, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); pmlmeext->mgnt_seq++; @@ -4042,9 +4054,10 @@ unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr { struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); /* check A3 */ - if (memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) + if (memcmp(MacAddr, pnetwork->MacAddress, ETH_ALEN)) return _SUCCESS; DBG_88E("%s\n", __func__); diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 324c1a7..3e9b6e9 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -405,11 +405,6 @@ int get_bsstype(unsigned short capability) return 0; } -__inline u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork) -{ - return pnetwork->MacAddress; -} - u16 get_beacon_interval(struct wlan_bssid_ex *bss) { __le16 val; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 7f30dea..0d513e3 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -276,7 +276,7 @@ static void ConstructBeacon(struct adapter *adapt, u8 *pframe, u32 *pLength) memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); + memcpy(pwlanhdr->addr3, cur_network->MacAddress, ETH_ALEN); SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); SetFrameSubType(pframe, WIFI_BEACON); @@ -350,6 +350,7 @@ static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength) struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); __le16 *fctrl; + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; @@ -363,7 +364,7 @@ static void ConstructPSPoll(struct adapter *adapt, u8 *pframe, u32 *pLength) SetDuration(pframe, (pmlmeinfo->aid | 0xc000)); /* BSSID. */ - memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); /* TA. */ memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); @@ -386,6 +387,7 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, struct wlan_network *cur_network = &pmlmepriv->cur_network; struct mlme_ext_priv *pmlmeext = &(adapt->mlmeextpriv); struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; @@ -397,21 +399,21 @@ static void ConstructNullFunctionData(struct adapter *adapt, u8 *pframe, switch (cur_network->network.InfrastructureMode) { case Ndis802_11Infrastructure: SetToDs(fctrl); - memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr1, pnetwork->MacAddress, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN); break; case Ndis802_11APMode: SetFrDs(fctrl); memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr2, pnetwork->MacAddress, ETH_ALEN); memcpy(pwlanhdr->addr3, myid(&(adapt->eeprompriv)), ETH_ALEN); break; case Ndis802_11IBSS: default: memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(adapt->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); break; } @@ -498,6 +500,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) u16 BufIndex; u32 TotalPacketLen; struct rsvdpage_loc RsvdPageLoc; + struct wlan_bssid_ex *pnetwork; DBG_88E("%s\n", __func__); ReservedPagePacket = kzalloc(1000, GFP_KERNEL); @@ -510,6 +513,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) pxmitpriv = &adapt->xmitpriv; pmlmeext = &adapt->mlmeextpriv; pmlmeinfo = &pmlmeext->mlmext_info; + pnetwork = &(pmlmeinfo->network); TxDescLen = TXDESC_SIZE; PageNum = 0; @@ -541,7 +545,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) /* 3 (3) null data * 1 page */ RsvdPageLoc.LocNullData = PageNum; - ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], &NullDataLength, get_my_bssid(&pmlmeinfo->network), false, 0, 0, false); + ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], &NullDataLength, pnetwork->MacAddress, false, 0, 0, false); rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], NullDataLength, false, false); PageNeed = (u8)PageNum_128(TxDescLen + NullDataLength); @@ -551,7 +555,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) /* 3 (4) probe response * 1page */ RsvdPageLoc.LocProbeRsp = PageNum; - ConstructProbeRsp(adapt, &ReservedPagePacket[BufIndex], &ProbeRspLength, get_my_bssid(&pmlmeinfo->network), false); + ConstructProbeRsp(adapt, &ReservedPagePacket[BufIndex], &ProbeRspLength, pnetwork->MacAddress, false); rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], ProbeRspLength, false, false); PageNeed = (u8)PageNum_128(TxDescLen + ProbeRspLength); @@ -562,7 +566,7 @@ static void SetFwRsvdPagePkt(struct adapter *adapt, bool bDLFinished) /* 3 (5) Qos null data */ RsvdPageLoc.LocQosNull = PageNum; ConstructNullFunctionData(adapt, &ReservedPagePacket[BufIndex], - &QosNullLength, get_my_bssid(&pmlmeinfo->network), true, 0, 0, false); + &QosNullLength, pnetwork->MacAddress, true, 0, 0, false); rtl8188e_fill_fake_txdesc(adapt, &ReservedPagePacket[BufIndex-TxDescLen], QosNullLength, false, false); PageNeed = (u8)PageNum_128(TxDescLen + QosNullLength); diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 8d72ccf..1920b1c 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -496,7 +496,6 @@ void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src, struct adapter *adapter, bool update_ie); int get_bsstype(unsigned short capability); -u8 *get_my_bssid(struct wlan_bssid_ex *pnetwork); u16 get_beacon_interval(struct wlan_bssid_ex *bss); int is_client_associated_to_ap(struct adapter *padapter); @@ -516,7 +515,7 @@ void ERP_IE_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE); void VCS_update(struct adapter *padapter, struct sta_info *psta); void update_beacon_info(struct adapter *padapter, u8 *pframe, uint len, - struct sta_info *psta); + struct sta_info *psta); int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len); void update_IOT_info(struct adapter *padapter); void update_capinfo(struct adapter *adapter, u16 updatecap); -- cgit v0.10.2 From 7aa36b4bc2e1a7bc9c014b5d171dc5d2264abc41 Mon Sep 17 00:00:00 2001 From: Gangadhar Vukkesala Date: Sat, 20 Dec 2014 21:29:47 +0530 Subject: staging: rtl8188eu: Fixed a space coding style issue. Fixed a space coding style issue which was found when running checkpatch.pl script on rtw_ap.c. Signed-off-by: Gangadhar Vukkesala Reviewed-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index d61842e..da19145 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -509,7 +509,7 @@ void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level) tx_ra_bitmap |= ((raid<<28)&0xf0000000); DBG_88E("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = 0x%x\n", - __func__ , psta->mac_id, raid , tx_ra_bitmap, arg); + __func__, psta->mac_id, raid, tx_ra_bitmap, arg); /* bitmap[0:27] = tx_rate_bitmap */ /* bitmap[28:31]= Rate Adaptive id */ -- cgit v0.10.2 From 6d6163c3bc35fc5ca4aa4e919c347df06d47372f Mon Sep 17 00:00:00 2001 From: Jonathan Jin Date: Mon, 15 Dec 2014 21:28:23 -0600 Subject: staging: rtl8192e: rejoin split quoted strings Fix a checkpatch.pl warning regarding quoted string splits across lines. While each join of these quoted strings results in a new checkpatch.pl "lines over 80 characters" warning, the regained ability to grep for these log strings in the codebase is, I would argue, well worth the trade-off. Signed-off-by: Jonathan Jin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index cf11b04..fdc349e 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -70,8 +70,7 @@ rtllib_frag_cache_find(struct rtllib_device *ieee, unsigned int seq, if (entry->skb != NULL && time_after(jiffies, entry->first_frag_time + 2 * HZ)) { RTLLIB_DEBUG_FRAG( - "expiring fragment cache entry " - "seq=%u last_frag=%u\n", + "expiring fragment cache entry seq=%u last_frag=%u\n", entry->seq, entry->last_frag); dev_kfree_skb_any(entry->skb); entry->skb = NULL; @@ -188,8 +187,7 @@ static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee, if (entry == NULL) { RTLLIB_DEBUG_FRAG( - "could not invalidate fragment cache " - "entry (seq=%u)\n", seq); + "could not invalidate fragment cache entry (seq=%u)\n", seq); return -1; } @@ -305,11 +303,9 @@ rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, atomic_dec(&crypt->refcnt); if (res < 0) { RTLLIB_DEBUG_DROP( - "decryption failed (SA= %pM" - ") res=%d\n", hdr->addr2, res); + "decryption failed (SA= %pM) res=%d\n", hdr->addr2, res); if (res == -2) - RTLLIB_DEBUG_DROP("Decryption failed ICV " - "mismatch (key %d)\n", + RTLLIB_DEBUG_DROP("Decryption failed ICV mismatch (key %d)\n", skb->data[hdrlen + 3] >> 6); ieee->ieee_stats.rx_discards_undecryptable++; return -1; @@ -345,8 +341,7 @@ rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb, res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv); atomic_dec(&crypt->refcnt); if (res < 0) { - printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed" - " (SA= %pM keyidx=%d)\n", + printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed (SA= %pM keyidx=%d)\n", ieee->dev->name, hdr->addr2, keyidx); return -1; } @@ -559,8 +554,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, bool bMatchWinStart = false, bPktInBuf = false; unsigned long flags; - RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Seq is %d, pTS->RxIndicateSeq" - " is %d, WinSize is %d\n", __func__, SeqNum, + RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Seq is %d, pTS->RxIndicateSeq is %d, WinSize is %d\n", __func__, SeqNum, pTS->RxIndicateSeq, WinSize); spin_lock_irqsave(&(ieee->reorder_spinlock), flags); @@ -600,8 +594,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, pTS->RxIndicateSeq = SeqNum + 1 - WinSize; else pTS->RxIndicateSeq = 4095 - (WinSize - (SeqNum + 1)) + 1; - RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Window Shift! IndicateSeq: %d," - " NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum); + RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum); } /* @@ -617,8 +610,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, */ if (bMatchWinStart) { /* Current packet is going to be indicated.*/ - RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packets indication!! " - "IndicateSeq: %d, NewSeq: %d\n", + RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum); ieee->prxbIndicateArray[0] = prxb; index = 1; @@ -636,9 +628,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, if (!AddReorderEntry(pTS, pReorderEntry)) { RTLLIB_DEBUG(RTLLIB_DL_REORDER, - "%s(): Duplicate packet is " - "dropped!! IndicateSeq: %d, " - "NewSeq: %d\n", + "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", __func__, pTS->RxIndicateSeq, SeqNum); list_add_tail(&pReorderEntry->List, @@ -652,8 +642,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, } } else { RTLLIB_DEBUG(RTLLIB_DL_REORDER, - "Pkt insert into struct buffer!! " - "IndicateSeq: %d, NewSeq: %d\n", + "Pkt insert into struct buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum); } } else { @@ -663,9 +652,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, * indicate all the packets in struct buffer and get * reorder entries. */ - RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket():" - " There is no reorder entry!! Packet is " - "dropped!!\n"); + RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n"); { int i; @@ -687,8 +674,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq)) { /* This protect struct buffer from overflow. */ if (index >= REORDER_WIN_SIZE) { - RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicate" - "Packet(): Buffer overflow!!\n"); + RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!!\n"); bPktInBuf = true; break; } @@ -699,8 +685,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096; ieee->prxbIndicateArray[index] = pReorderEntry->prxb; - RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate SeqNum" - " %d!\n", __func__, pReorderEntry->SeqNum); + RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate SeqNum %d!\n", __func__, pReorderEntry->SeqNum); index++; list_add_tail(&pReorderEntry->List, @@ -719,8 +704,7 @@ static void RxReorderIndicatePacket(struct rtllib_device *ieee, pTS->RxTimeoutIndicateSeq = 0xffff; if (index > REORDER_WIN_SIZE) { - RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket():" - " Rx Reorder struct buffer full!!\n"); + RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder struct buffer full!!\n"); spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); return; @@ -809,14 +793,11 @@ static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb, (nSubframe_Length << 8); if (skb->len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) { - printk(KERN_INFO "%s: A-MSDU parse error!! " - "pRfd->nTotalSubframe : %d\n",\ + printk(KERN_INFO "%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\ __func__, rxb->nr_subframes); - printk(KERN_INFO "%s: A-MSDU parse error!! " - "Subframe Length: %d\n", __func__, + printk(KERN_INFO "%s: A-MSDU parse error!! Subframe Length: %d\n", __func__, nSubframe_Length); - printk(KERN_INFO "nRemain_Length is %d and " - "nSubframe_Length is : %d\n", skb->len, + printk(KERN_INFO "nRemain_Length is %d and nSubframe_Length is : %d\n", skb->len, nSubframe_Length); printk(KERN_INFO "The Packet SeqNum is %d\n", SeqNum); return 0; @@ -844,8 +825,7 @@ static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb, sub_skb->dev = ieee->dev; rxb->subframes[rxb->nr_subframes++] = sub_skb; if (rxb->nr_subframes >= MAX_SUBFRAME_COUNT) { - RTLLIB_DEBUG_RX("ParseSubframe(): Too many " - "Subframes! Packets dropped!\n"); + RTLLIB_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n"); break; } skb_pull(skb, nSubframe_Length); @@ -922,8 +902,7 @@ static int rtllib_rx_check_duplicate(struct rtllib_device *ieee, pRxTS->RxLastFragNum = frag; pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc); } else { - RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!%s(): No TS!! Skip" - " the check!!\n", __func__); + RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!%s(): No TS!! Skip the check!!\n", __func__); return -1; } } @@ -996,9 +975,7 @@ static int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc, stype != RTLLIB_STYPE_QOS_DATA) { if (stype != RTLLIB_STYPE_NULLFUNC) RTLLIB_DEBUG_DROP( - "RX: dropped data frame " - "with no data (type=0x%02x, " - "subtype=0x%02x)\n", + "RX: dropped data frame with no data (type=0x%02x, subtype=0x%02x)\n", type, stype); return -1; } @@ -1041,8 +1018,7 @@ static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb, * frames from other than current BSS, so just drop the * frames silently instead of filling system log with * these reports. */ - RTLLIB_DEBUG_DROP("Decryption failed (not set)" - " (SA= %pM)\n", + RTLLIB_DEBUG_DROP("Decryption failed (not set) (SA= %pM)\n", hdr->addr2); ieee->ieee_stats.rx_discards_undecryptable++; return -1; @@ -1086,8 +1062,7 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, if (!frag_skb) { RTLLIB_DEBUG(RTLLIB_DL_RX | RTLLIB_DL_FRAG, - "Rx cannot get skb from fragment " - "cache (morefrag=%d seq=%u frag=%u)\n", + "Rx cannot get skb from fragment cache (morefrag=%d seq=%u frag=%u)\n", (fc & RTLLIB_FCTL_MOREFRAGS) != 0, WLAN_GET_SEQ_SEQ(sc), frag); return -1; @@ -1097,8 +1072,7 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, flen -= hdrlen; if (frag_skb->tail + flen > frag_skb->end) { - printk(KERN_WARNING "%s: host decrypted and " - "reassembled frame did not fit skb\n", + printk(KERN_WARNING "%s: host decrypted and reassembled frame did not fit skb\n", __func__); rtllib_frag_cache_invalidate(ieee, hdr); return -1; @@ -1152,8 +1126,7 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, eap_get_type(eap->type)); } else { RTLLIB_DEBUG_DROP( - "encryption configured, but RX " - "frame not encrypted (SA= %pM)\n", + "encryption configured, but RX frame not encrypted (SA= %pM)\n", hdr->addr2); return -1; } @@ -1170,9 +1143,7 @@ static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb, if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep && !rtllib_is_eapol_frame(ieee, skb, hdrlen)) { RTLLIB_DEBUG_DROP( - "dropped unencrypted RX data " - "frame from %pM" - " (drop_unencrypted=1)\n", + "dropped unencrypted RX data frame from %pM (drop_unencrypted=1)\n", hdr->addr2); return -1; } @@ -1762,9 +1733,7 @@ int rtllib_parse_info_param(struct rtllib_device *ieee, while (length >= sizeof(*info_element)) { if (sizeof(*info_element) + info_element->len > length) { - RTLLIB_DEBUG_MGMT("Info elem: parse failed: " - "info_element->len + 2 > left : " - "info_element->len+2=%zd left=%d, id=%d.\n", + RTLLIB_DEBUG_MGMT("Info elem: parse failed: info_element->len + 2 > left : info_element->len+2=%zd left=%d, id=%d.\n", info_element->len + sizeof(*info_element), length, info_element->id); @@ -2321,8 +2290,7 @@ static inline int rtllib_network_init( } if (network->mode == 0) { - RTLLIB_DEBUG_SCAN("Filtered out '%s (%pM)' " - "network.\n", + RTLLIB_DEBUG_SCAN("Filtered out '%s (%pM)' network.\n", escape_essid(network->ssid, network->ssid_len), network->bssid); @@ -2568,8 +2536,7 @@ static inline void rtllib_process_probe_response( if (WLAN_FC_GET_STYPE(le16_to_cpu(beacon->header.frame_ctl)) == RTLLIB_STYPE_PROBE_RESP) { if (IsPassiveChannel(ieee, network->channel)) { - printk(KERN_INFO "GetScanInfo(): For Global Domain, " - "filter probe response at channel(%d).\n", + printk(KERN_INFO "GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network->channel); goto free_network; } @@ -2618,8 +2585,7 @@ static inline void rtllib_process_probe_response( /* If there are no more slots, expire the oldest */ list_del(&oldest->list); target = oldest; - RTLLIB_DEBUG_SCAN("Expired '%s' ( %pM) from " - "network list.\n", + RTLLIB_DEBUG_SCAN("Expired '%s' ( %pM) from network list.\n", escape_essid(target->ssid, target->ssid_len), target->bssid); -- cgit v0.10.2 From 683a6868a1a0f05a35737bf18872df95342f4361 Mon Sep 17 00:00:00 2001 From: Mohammad Jamal Date: Tue, 16 Dec 2014 21:57:44 +0530 Subject: Staging: rtl8192u : fix space before , coding style issue in r8190_rtl8256.c This is a patch to r8190_rtl8256.c file that fixes space before , warning found by checkpatch.pl tool Signed-off-by: Mohammad Jamal Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.c b/drivers/staging/rtl8192u/r8190_rtl8256.c index 45514aa..1868352 100644 --- a/drivers/staging/rtl8192u/r8190_rtl8256.c +++ b/drivers/staging/rtl8192u/r8190_rtl8256.c @@ -23,7 +23,7 @@ * Return: NONE * Note: 8226 support both 20M and 40 MHz *---------------------------------------------------------------------------*/ -void PHY_SetRF8256Bandwidth(struct net_device *dev , HT_CHANNEL_WIDTH Bandwidth) +void PHY_SetRF8256Bandwidth(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth) { u8 eRFPath; struct r8192_priv *priv = ieee80211_priv(dev); -- cgit v0.10.2 From 55b3bba0b8cc5cd68ed269a539043ef971fb95a9 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 18:33:06 +0100 Subject: staging: rtl8188eu: hal: rtl8188e_cmd.c: Remove unused function Remove the function rtl8188e_set_rssi_cmd() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c index 0d513e3..86347f2 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c @@ -127,22 +127,6 @@ exit: return ret; } -u8 rtl8188e_set_rssi_cmd(struct adapter *adapt, u8 *param) -{ - u8 res = _SUCCESS; - struct hal_data_8188e *haldata = GET_HAL_DATA(adapt); - - if (haldata->fw_ractrl) { - ; - } else { - DBG_88E("==>%s fw dont support RA\n", __func__); - res = _FAIL; - } - - - return res; -} - u8 rtl8188e_set_raid_cmd(struct adapter *adapt, u32 mask) { u8 buf[3]; diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h index 0e78e2a..42b1f22 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h @@ -107,7 +107,6 @@ struct P2P_PS_CTWPeriod_t { /* host message to firmware cmd */ void rtl8188e_set_FwPwrMode_cmd(struct adapter *padapter, u8 Mode); void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *padapter, u8 mstatus); -u8 rtl8188e_set_rssi_cmd(struct adapter *padapter, u8 *param); u8 rtl8188e_set_raid_cmd(struct adapter *padapter, u32 mask); void rtl8188e_Add_RateATid(struct adapter *padapter, u32 bitmap, u8 arg, u8 rssi_level); -- cgit v0.10.2 From f225d04e4e3702a56d90724d1332920a4236f442 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 19:16:15 +0100 Subject: staging: rtl8188eu: hal: rtl8188e_hal_init.c: Remove unused function Remove the function GetEEPROMSize8188E() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 7d460ea..3222d8d 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -242,20 +242,6 @@ void rtl8188e_set_hal_ops(struct hal_ops *pHalFunc) pHalFunc->hal_notch_filter = &hal_notch_filter_8188e; } -u8 GetEEPROMSize8188E(struct adapter *padapter) -{ - u8 size = 0; - u32 cr; - - cr = usb_read16(padapter, REG_9346CR); - /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */ - size = (cr & BOOT_FROM_EEPROM) ? 6 : 4; - - MSG_88E("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46"); - - return size; -} - /* */ /* */ /* LLT R/W/Init function */ diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index 42ab1d2..b8c42ee 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -391,7 +391,6 @@ void rtl8188e_InitializeFirmwareVars(struct adapter *padapter); s32 InitLLTTable(struct adapter *padapter, u8 txpktbuf_bndy); /* EFuse */ -u8 GetEEPROMSize8188E(struct adapter *padapter); void Hal_InitPGData88E(struct adapter *padapter); void Hal_EfuseParseIDCode88E(struct adapter *padapter, u8 *hwinfo); void Hal_ReadTxPowerInfo88E(struct adapter *padapter, u8 *hwinfo, -- cgit v0.10.2 From 17ad975c5aa631919131b4c572fc878be29e3d7e Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 22:59:07 +0100 Subject: staging: rtl8188eu: os_dep: usb_ops_linux.c: Remove unused function Remove the function usb_writeN() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/include/usb_ops_linux.h b/drivers/staging/rtl8188eu/include/usb_ops_linux.h index 01b3810..4fdc536 100644 --- a/drivers/staging/rtl8188eu/include/usb_ops_linux.h +++ b/drivers/staging/rtl8188eu/include/usb_ops_linux.h @@ -79,7 +79,6 @@ void usb_read_port_cancel(struct adapter *adapter); int usb_write8(struct adapter *adapter, u32 addr, u8 val); int usb_write16(struct adapter *adapter, u32 addr, u16 val); int usb_write32(struct adapter *adapter, u32 addr, u32 val); -int usb_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *pdata); u32 usb_write_port(struct adapter *adapter, u32 addr, u32 cnt, u8 *pmem); void usb_write_port_cancel(struct adapter *adapter); diff --git a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c index d2efa9d..80e7ef9 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_ops_linux.c @@ -615,33 +615,6 @@ int usb_write32(struct adapter *adapter, u32 addr, u32 val) return ret; } -int usb_writeN(struct adapter *adapter, u32 addr, u32 length, u8 *pdata) -{ - u8 request; - u8 requesttype; - u16 wvalue; - u16 index; - u16 len; - u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0}; - int ret; - - - request = 0x05; - requesttype = 0x00;/* write_out */ - index = 0;/* n/a */ - - wvalue = (u16)(addr&0x0000ffff); - len = length; - memcpy(buf, pdata, len); - - ret = usbctrl_vendorreq(adapter, request, wvalue, index, buf, len, requesttype); - - - return RTW_STATUS_CODE(ret); -} - - - static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs) { struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context; -- cgit v0.10.2 From ad6f87d016c22d63013cf889ecd4a5c598a17be0 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 23:28:37 +0100 Subject: staging: rtl8192e: rtl8192e: rtl_cam.c: Remove unused function Remove the function CAM_read_entry() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c index 6c64e08..89ea70b 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c @@ -167,35 +167,6 @@ void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig); } -void CAM_read_entry(struct net_device *dev, u32 iIndex) -{ - u32 target_command = 0; - u32 target_content = 0; - u8 entry_i = 0; - u32 ulStatus; - s32 i = 100; - - for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { - target_command = entry_i+CAM_CONTENT_COUNT*iIndex; - target_command = target_command | BIT31; - - while ((i--) >= 0) { - ulStatus = read_nic_dword(dev, RWCAM); - if (ulStatus & BIT31) - continue; - else - break; - } - write_nic_dword(dev, RWCAM, target_command); - RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A0: %x\n", - target_command); - target_content = read_nic_dword(dev, RCAMO); - RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x\n", - target_content); - } - printk(KERN_INFO "\n"); -} - void CamRestoreAllEntry(struct net_device *dev) { u8 EntryId = 0; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h index 7d075d3..3c4c0e6 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h @@ -41,6 +41,4 @@ void write_cam(struct net_device *dev, u8 addr, u32 data); void CamRestoreAllEntry(struct net_device *dev); -void CAM_read_entry(struct net_device *dev, u32 iIndex); - #endif -- cgit v0.10.2 From 2fd8feab59186a166052bdb6098117817abb92ea Mon Sep 17 00:00:00 2001 From: Karthik Nayak Date: Thu, 18 Dec 2014 14:50:11 +0530 Subject: Staging: rtl8192u: removed an unnecessary else statement As per checkpatch warning, removed an unnecessary else statement proceeding an if statement with a return. Signed-off-by: Karthik Nayak Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index 936565d..b3b508c 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -480,15 +480,13 @@ static void dm_bandwidth_autoswitch(struct net_device *dev) if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||!priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable){ return; - }else{ - if(priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false){//If send packets in 40 Mhz in 20/40 - if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz) - priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true; - }else{//in force send packets in 20 Mhz in 20/40 - if(priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz) - priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false; - - } + } + if(priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false){//If send packets in 40 Mhz in 20/40 + if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz) + priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true; + }else{//in force send packets in 20 Mhz in 20/40 + if(priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz) + priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false; } } // dm_BandwidthAutoSwitch -- cgit v0.10.2 From f4f5a59ff2e746885be3c1c06c1d0e8861a10ce8 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sat, 20 Dec 2014 13:17:46 +0100 Subject: staging: rtl8712: rtl871x_mp_ioctl.c: Remove some unused functions Removes some functions that are not used anywhere: oid_rt_pro_h2c_get_rate_table_hdl() oid_rt_pro_h2c_set_rate_table_hdl() oid_rt_pro_set_pwrstate_hdl() oid_rt_pro_qry_pwrstate_hdl() oid_rt_pro_set_basic_rate_hdl() oid_rt_pro_set_power_tracking_hdl() oid_rt_pro_set_data_rate_ex_hdl() oid_rt_pro_cfg_debug_message_hdl() oid_rt_poll_rx_status_hdl() oid_rt_pro_set_rf_intfs_hdl() oid_rt_wr_attrib_mem_hdl() oid_rt_rd_attrib_mem_hdl() oid_rt_pro8711_pkt_loss_hdl() oid_rt_pro8711_wi_poll_hdl() oid_rt_pro_write16_eeprom_hdl() oid_rt_pro_read16_eeprom_hdl() oid_rt_pro_write_txcmd_hdl() oid_rt_pro_burst_write_register_hdl() oid_rt_pro_burst_read_register_hdl() oid_rt_pro8711_join_bss_hdl() oid_rt_pro_set_pkt_test_mode_hdl() oid_rt_pro_set_tx_agc_offset_hdl() oid_rt_set_crystal_cap_hdl() oid_rt_pro_rw_efuse_pgpkt_hdl() oid_rt_pro_rx_packet_type_hdl() oid_rt_pro_query_dr_variable_hdl() oid_rt_pro_dele_sta_info_hdl() oid_rt_pro_add_sta_info_hdl() oid_rt_pro_encryption_ctrl_hdl() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c index a16f15e..49fa1d1 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c +++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c @@ -575,26 +575,6 @@ uint oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv return RNDIS_STATUS_SUCCESS; } -uint oid_rt_pro8711_join_bss_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - struct ndis_802_11_ssid *pssid; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_needed = (u32)sizeof(struct ndis_802_11_ssid); - *poid_par_priv->bytes_rw = 0; - if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed) - return RNDIS_STATUS_INVALID_LENGTH; - pssid = (struct ndis_802_11_ssid *)poid_par_priv->information_buf; - if (mp_start_joinbss(Adapter, pssid) == _FAIL) - status = RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_rw = sizeof(struct ndis_802_11_ssid); - return status; -} - uint oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv) { @@ -696,172 +676,6 @@ uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv) return status; } -uint oid_rt_pro_burst_read_register_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct burst_rw_reg *pBstRwReg; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - pBstRwReg = (struct burst_rw_reg *)poid_par_priv->information_buf; - r8712_read_mem(Adapter, pBstRwReg->offset, (u32)pBstRwReg->len, - pBstRwReg->Data); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_burst_write_register_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct burst_rw_reg *pBstRwReg; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - pBstRwReg = (struct burst_rw_reg *)poid_par_priv->information_buf; - r8712_write_mem(Adapter, pBstRwReg->offset, (u32)pBstRwReg->len, - pBstRwReg->Data); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_write_txcmd_hdl(struct oid_par_priv *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_read16_eeprom_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct eeprom_rw_param *pEEPROM; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - pEEPROM = (struct eeprom_rw_param *)poid_par_priv->information_buf; - pEEPROM->value = r8712_eeprom_read16(Adapter, - (u16)(pEEPROM->offset >> 1)); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_write16_eeprom_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct eeprom_rw_param *pEEPROM; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - pEEPROM = (struct eeprom_rw_param *)poid_par_priv->information_buf; - r8712_eeprom_write16(Adapter, (u16)(pEEPROM->offset >> 1), - pEEPROM->value); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro8711_wi_poll_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct mp_wiparam *pwi_param; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(struct mp_wiparam)) - return RNDIS_STATUS_INVALID_LENGTH; - if (Adapter->mppriv.workparam.bcompleted == false) - return RNDIS_STATUS_NOT_ACCEPTED; - pwi_param = (struct mp_wiparam *)poid_par_priv->information_buf; - memcpy(pwi_param, &Adapter->mppriv.workparam, - sizeof(struct mp_wiparam)); - Adapter->mppriv.act_in_progress = false; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro8711_pkt_loss_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(uint) * 2) - return RNDIS_STATUS_INVALID_LENGTH; - if (*(uint *)poid_par_priv->information_buf == 1) - Adapter->mppriv.rx_pktloss = 0; - *((uint *)poid_par_priv->information_buf+1) = - Adapter->mppriv.rx_pktloss; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_rd_attrib_mem_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_wr_attrib_mem_hdl(struct oid_par_priv *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_rf_intfs_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (r8712_setrfintfs_cmd(Adapter, *(unsigned char *) - poid_par_priv->information_buf) == _FAIL) - status = RNDIS_STATUS_NOT_ACCEPTED; - return status; -} - -uint oid_rt_poll_rx_status_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - memcpy(poid_par_priv->information_buf, - (unsigned char *)&Adapter->mppriv.rxstat, - sizeof(struct recv_stat)); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_cfg_debug_message_hdl(struct oid_par_priv - *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_data_rate_ex_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (r8712_setdatarate_cmd(Adapter, - poid_par_priv->information_buf) != _SUCCESS) - status = RNDIS_STATUS_NOT_ACCEPTED; - return status; -} - uint oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv) { struct _adapter *Adapter = (struct _adapter *) @@ -890,250 +704,12 @@ uint oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv) return RNDIS_STATUS_SUCCESS; } -uint oid_rt_pro_set_power_tracking_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(u8)) - return RNDIS_STATUS_INVALID_LENGTH; - if (!r8712_setptm_cmd(Adapter, *((u8 *)poid_par_priv->information_buf))) - status = RNDIS_STATUS_NOT_ACCEPTED; - return status; -} - -uint oid_rt_pro_set_basic_rate_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff}; - uint status = RNDIS_STATUS_SUCCESS; - u32 ratevalue; - u8 datarates[NumRates]; - int i; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - ratevalue = *((u32 *)poid_par_priv->information_buf); - for (i = 0; i < NumRates; i++) { - if (ratevalue == mpdatarate[i]) - datarates[i] = mpdatarate[i]; - else - datarates[i] = 0xff; - } - if (r8712_setbasicrate_cmd(Adapter, datarates) != _SUCCESS) - status = RNDIS_STATUS_NOT_ACCEPTED; - return status; -} - -uint oid_rt_pro_qry_pwrstate_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < 8) - return RNDIS_STATUS_INVALID_LENGTH; - *poid_par_priv->bytes_rw = 8; - memcpy(poid_par_priv->information_buf, - &(Adapter->pwrctrlpriv.pwr_mode), 8); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_pwrstate_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint pwr_mode, smart_ps; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_rw = 0; - *poid_par_priv->bytes_needed = 8; - if (poid_par_priv->information_buf_len < 8) - return RNDIS_STATUS_INVALID_LENGTH; - pwr_mode = *(uint *)(poid_par_priv->information_buf); - smart_ps = *(uint *)((addr_t)poid_par_priv->information_buf + 4); - if (pwr_mode != Adapter->pwrctrlpriv.pwr_mode || smart_ps != - Adapter->pwrctrlpriv.smart_ps) - r8712_set_ps_mode(Adapter, pwr_mode, smart_ps); - *poid_par_priv->bytes_rw = 8; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_h2c_set_rate_table_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - struct setratable_parm *prate_table; - u8 res; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_needed = sizeof(struct setratable_parm); - if (poid_par_priv->information_buf_len < - sizeof(struct setratable_parm)) - return RNDIS_STATUS_INVALID_LENGTH; - prate_table = (struct setratable_parm *)poid_par_priv->information_buf; - res = r8712_setrttbl_cmd(Adapter, prate_table); - if (res == _FAIL) - status = RNDIS_STATUS_FAILURE; - return status; -} - -uint oid_rt_pro_h2c_get_rate_table_hdl(struct oid_par_priv - *poid_par_priv) -{ - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_encryption_ctrl_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - struct security_priv *psecuritypriv = &Adapter->securitypriv; - enum ENCRY_CTRL_STATE encry_mode = 0; - - *poid_par_priv->bytes_needed = sizeof(u8); - if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed) - return RNDIS_STATUS_INVALID_LENGTH; - - if (poid_par_priv->type_of_oid == SET_OID) { - encry_mode = *((u8 *)poid_par_priv->information_buf); - switch (encry_mode) { - case HW_CONTROL: - psecuritypriv->sw_decrypt = false; - psecuritypriv->sw_encrypt = false; - break; - case SW_CONTROL: - psecuritypriv->sw_decrypt = true; - psecuritypriv->sw_encrypt = true; - break; - case HW_ENCRY_SW_DECRY: - psecuritypriv->sw_decrypt = true; - psecuritypriv->sw_encrypt = false; - break; - case SW_ENCRY_HW_DECRY: - psecuritypriv->sw_decrypt = false; - psecuritypriv->sw_encrypt = true; - break; - } - } else { - if ((psecuritypriv->sw_encrypt == false) && - (psecuritypriv->sw_decrypt == false)) - encry_mode = HW_CONTROL; - else if ((psecuritypriv->sw_encrypt == false) && - (psecuritypriv->sw_decrypt == true)) - encry_mode = HW_ENCRY_SW_DECRY; - else if ((psecuritypriv->sw_encrypt == true) && - (psecuritypriv->sw_decrypt == false)) - encry_mode = SW_ENCRY_HW_DECRY; - else if ((psecuritypriv->sw_encrypt == true) && - (psecuritypriv->sw_decrypt == true)) - encry_mode = SW_CONTROL; - *(u8 *)poid_par_priv->information_buf = encry_mode; - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - } - return RNDIS_STATUS_SUCCESS; -} -/*----------------------------------------------------------------------*/ -uint oid_rt_pro_add_sta_info_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - uint status = RNDIS_STATUS_SUCCESS; - - struct sta_info *psta = NULL; - u8 *macaddr; - - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - *poid_par_priv->bytes_needed = ETH_ALEN; - if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed) - return RNDIS_STATUS_INVALID_LENGTH; - macaddr = (u8 *) poid_par_priv->information_buf; - psta = r8712_get_stainfo(&Adapter->stapriv, macaddr); - if (psta == NULL) { /* the sta in sta_info_queue => do nothing*/ - psta = r8712_alloc_stainfo(&Adapter->stapriv, macaddr); - if (psta == NULL) - status = RNDIS_STATUS_FAILURE; - } - return status; -} -/*-------------------------------------------------------------------------*/ -uint oid_rt_pro_dele_sta_info_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - unsigned long irqL; - - struct sta_info *psta = NULL; - u8 *macaddr; - - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - *poid_par_priv->bytes_needed = ETH_ALEN; - if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed) - return RNDIS_STATUS_INVALID_LENGTH; - - macaddr = (u8 *)poid_par_priv->information_buf; - - psta = r8712_get_stainfo(&Adapter->stapriv, macaddr); - if (psta != NULL) { - spin_lock_irqsave(&(Adapter->stapriv.sta_hash_lock), irqL); - r8712_free_stainfo(Adapter, psta); - spin_unlock_irqrestore(&(Adapter->stapriv.sta_hash_lock), irqL); - } - - return RNDIS_STATUS_SUCCESS; -} /*--------------------------------------------------------------------------*/ static u32 mp_query_drv_var(struct _adapter *padapter, u8 offset, u32 var) { return var; } -uint oid_rt_pro_query_dr_variable_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - - struct DR_VARIABLE_STRUCT *pdrv_var; - - if (poid_par_priv->type_of_oid != QUERY_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - *poid_par_priv->bytes_needed = sizeof(struct DR_VARIABLE_STRUCT); - if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed) - return RNDIS_STATUS_INVALID_LENGTH; - pdrv_var = (struct DR_VARIABLE_STRUCT *)poid_par_priv->information_buf; - pdrv_var->variable = mp_query_drv_var(Adapter, pdrv_var->offset, - pdrv_var->variable); - *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; - return RNDIS_STATUS_SUCCESS; -} - -/*--------------------------------------------------------------------------*/ -uint oid_rt_pro_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv) -{ - return RNDIS_STATUS_SUCCESS; -} /*------------------------------------------------------------------------*/ uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv) { @@ -1192,38 +768,6 @@ uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv) return status; } /*----------------------------------------------------------------------*/ -uint oid_rt_pro_rw_efuse_pgpkt_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - struct PGPKT_STRUCT *ppgpkt; - - *poid_par_priv->bytes_rw = 0; - if (poid_par_priv->information_buf_len < sizeof(struct PGPKT_STRUCT)) - return RNDIS_STATUS_INVALID_LENGTH; - ppgpkt = (struct PGPKT_STRUCT *)poid_par_priv->information_buf; - if (poid_par_priv->type_of_oid == QUERY_OID) { - if (r8712_efuse_pg_packet_read(Adapter, ppgpkt->offset, - ppgpkt->data) == true) - *poid_par_priv->bytes_rw = - poid_par_priv->information_buf_len; - else - status = RNDIS_STATUS_FAILURE; - } else { - if (r8712_efuse_reg_init(Adapter) == true) { - if (r8712_efuse_pg_packet_write(Adapter, ppgpkt->offset, - ppgpkt->word_en, ppgpkt->data) == true) - *poid_par_priv->bytes_rw = - poid_par_priv->information_buf_len; - else - status = RNDIS_STATUS_FAILURE; - r8712_efuse_reg_uninit(Adapter); - } else - status = RNDIS_STATUS_FAILURE; - } - return status; -} uint oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_priv) @@ -1319,24 +863,6 @@ uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv) return RNDIS_STATUS_SUCCESS; } -uint oid_rt_set_crystal_cap_hdl(struct oid_par_priv *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 crystal_cap = 0; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - crystal_cap = *((u32 *)poid_par_priv->information_buf);/*4*/ - if (crystal_cap > 0xf) - return RNDIS_STATUS_NOT_ACCEPTED; - Adapter->mppriv.curr_crystalcap = crystal_cap; - r8712_SetCrystalCap(Adapter); - return RNDIS_STATUS_SUCCESS; -} - uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv) { @@ -1378,50 +904,6 @@ uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv return RNDIS_STATUS_SUCCESS; } -uint oid_rt_pro_set_tx_agc_offset_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - u32 txagc; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - if (poid_par_priv->information_buf_len < sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - txagc = *(u32 *)poid_par_priv->information_buf; - r8712_SetTxAGCOffset(Adapter, txagc); - return RNDIS_STATUS_SUCCESS; -} - -uint oid_rt_pro_set_pkt_test_mode_hdl(struct oid_par_priv - *poid_par_priv) -{ - struct _adapter *Adapter = (struct _adapter *) - (poid_par_priv->adapter_context); - uint status = RNDIS_STATUS_SUCCESS; - struct mlme_priv *pmlmepriv = &Adapter->mlmepriv; - struct mp_priv *pmppriv = &Adapter->mppriv; - u32 type; - - if (poid_par_priv->type_of_oid != SET_OID) - return RNDIS_STATUS_NOT_ACCEPTED; - - if (poid_par_priv->information_buf_len < sizeof(u32)) - return RNDIS_STATUS_INVALID_LENGTH; - - type = *(u32 *)poid_par_priv->information_buf; - - if (_LOOPBOOK_MODE_ == type) { - pmppriv->mode = type; - set_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE); /*append txdesc*/ - } else if (_2MAC_MODE_ == type) { - pmppriv->mode = type; - _clr_fwstate_(pmlmepriv, WIFI_MP_LPBK_STATE); - } else - status = RNDIS_STATUS_NOT_ACCEPTED; - return status; -} /*--------------------------------------------------------------------------*/ /*Linux*/ unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv) diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h index 850143d..8e7c7f8 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h +++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h @@ -86,41 +86,8 @@ struct DR_VARIABLE_STRUCT { int mp_start_joinbss(struct _adapter *padapter, struct ndis_802_11_ssid *pssid); /* oid_rtl_seg_87_11_00 */ -uint oid_rt_pro8711_join_bss_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_burst_read_register_hdl(struct oid_par_priv* - poid_par_priv); -uint oid_rt_pro_burst_write_register_hdl(struct oid_par_priv* - poid_par_priv); -uint oid_rt_pro_write_txcmd_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_read16_eeprom_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_write16_eeprom_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro8711_wi_poll_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro8711_pkt_loss_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_rd_attrib_mem_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_wr_attrib_mem_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_rf_intfs_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_poll_rx_status_hdl(struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_87_11_20 */ -uint oid_rt_pro_cfg_debug_message_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_data_rate_ex_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_basic_rate_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_power_tracking_hdl( - struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_87_11_50 */ -uint oid_rt_pro_qry_pwrstate_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_pwrstate_hdl( - struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_87_11_F0 */ -uint oid_rt_pro_h2c_set_rate_table_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_h2c_get_rate_table_hdl( - struct oid_par_priv *poid_par_priv); /* oid_rtl_seg_81_80_00 */ uint oid_rt_pro_set_data_rate_hdl( struct oid_par_priv *poid_par_priv); @@ -159,28 +126,15 @@ uint oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv); /* oid_rtl_seg_81_85 */ uint oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv); -/* oid_rtl_seg_87_12_00 */ -uint oid_rt_pro_encryption_ctrl_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_add_sta_info_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_dele_sta_info_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_query_dr_variable_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_rw_efuse_pgpkt_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_get_efuse_current_size_hdl( struct oid_par_priv *poid_par_priv); uint oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_set_crystal_cap_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv); uint oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_tx_agc_offset_hdl( - struct oid_par_priv *poid_par_priv); -uint oid_rt_pro_set_pkt_test_mode_hdl( - struct oid_par_priv *poid_par_priv); uint oid_rt_get_thermal_meter_hdl( struct oid_par_priv *poid_par_priv); uint oid_rt_reset_phy_rx_packet_count_hdl( -- cgit v0.10.2 From e575edfbd78e4588d90ced6814c72f529fbaadde Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sat, 20 Dec 2014 13:23:03 +0100 Subject: staging: rtl8188eu: core: rtw_mlme_ext.c: Remove unused function Remove the function NULL_hdl() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 901ede9..28918201 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -4937,11 +4937,6 @@ void addba_timer_hdl(void *function_context) } } -u8 NULL_hdl(struct adapter *padapter, u8 *pbuf) -{ - return H2C_SUCCESS; -} - u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf) { u8 type; diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 1920b1c..4f05aee 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -678,7 +678,6 @@ u8 read_bbreg_hdl(struct adapter *padapter, u8 *pbuf); u8 write_bbreg_hdl(struct adapter *padapter, u8 *pbuf); u8 read_rfreg_hdl(struct adapter *padapter, u8 *pbuf); u8 write_rfreg_hdl(struct adapter *padapter, u8 *pbuf); -u8 NULL_hdl(struct adapter *padapter, u8 *pbuf); u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf); u8 disconnect_hdl(struct adapter *padapter, u8 *pbuf); u8 createbss_hdl(struct adapter *padapter, u8 *pbuf); -- cgit v0.10.2 From 366de3a08c08be71377eca906b55108d239ec941 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sat, 20 Dec 2014 13:49:58 +0100 Subject: staging: rtl8192e: rtl8192e: rtl_pm.c: Remove some unused functions Removes some functions that are not used anywhere: rtl8192E_save_state() rtl8192E_enable_wake() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c index 8e1a5d5..0b4f764 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c @@ -22,12 +22,6 @@ #include "r8190P_rtl8256.h" #include "rtl_pm.h" -int rtl8192E_save_state(struct pci_dev *dev, pm_message_t state) -{ - printk(KERN_NOTICE "r8192E save state call (state %u).\n", state.event); - return -EAGAIN; -} - int rtl8192E_suspend(struct pci_dev *pdev, pm_message_t state) { @@ -124,11 +118,3 @@ out: return 0; } - -int rtl8192E_enable_wake(struct pci_dev *dev, pm_message_t state, int enable) -{ - printk(KERN_NOTICE "r8192E enable wake call (state %u, enable %d).\n", - state.event, enable); - return -EAGAIN; -} - diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h index e5299fc..7bfe448 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h @@ -23,9 +23,7 @@ #include #include -int rtl8192E_save_state(struct pci_dev *dev, pm_message_t state); int rtl8192E_suspend(struct pci_dev *dev, pm_message_t state); int rtl8192E_resume(struct pci_dev *dev); -int rtl8192E_enable_wake(struct pci_dev *dev, pm_message_t state, int enable); #endif -- cgit v0.10.2 From b5133fde1b7f9d9d5af40293b4c588c15e33d534 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 21 Dec 2014 18:53:37 +0100 Subject: staging: rtl8192e: rtllib_rx.c: Remove some unused functions Removes some functions that are not used anywhere: update_ibss_network() rtllib_SignalStrengthTranslate() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index fdc349e..1664040 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -2176,34 +2176,6 @@ int rtllib_parse_info_param(struct rtllib_device *ieee, return 0; } -static inline u8 rtllib_SignalStrengthTranslate(u8 CurrSS) -{ - u8 RetSS; - - if (CurrSS >= 71 && CurrSS <= 100) - RetSS = 90 + ((CurrSS - 70) / 3); - else if (CurrSS >= 41 && CurrSS <= 70) - RetSS = 78 + ((CurrSS - 40) / 3); - else if (CurrSS >= 31 && CurrSS <= 40) - RetSS = 66 + (CurrSS - 30); - else if (CurrSS >= 21 && CurrSS <= 30) - RetSS = 54 + (CurrSS - 20); - else if (CurrSS >= 5 && CurrSS <= 20) - RetSS = 42 + (((CurrSS - 5) * 2) / 3); - else if (CurrSS == 4) - RetSS = 36; - else if (CurrSS == 3) - RetSS = 27; - else if (CurrSS == 2) - RetSS = 18; - else if (CurrSS == 1) - RetSS = 9; - else - RetSS = CurrSS; - - return RetSS; -} - static long rtllib_translate_todbm(u8 signal_strength_index) { long signal_power; @@ -2331,13 +2303,6 @@ static inline int is_same_network(struct rtllib_network *src, (dst->capability & WLAN_CAPABILITY_ESS))); } -static inline void update_ibss_network(struct rtllib_network *dst, - struct rtllib_network *src) -{ - memcpy(&dst->stats, &src->stats, sizeof(struct rtllib_rx_stats)); - dst->last_scanned = jiffies; -} - static inline void update_network(struct rtllib_network *dst, struct rtllib_network *src) -- cgit v0.10.2 From 31f1c464bd6e09a75c53efb13fc28b514d7be345 Mon Sep 17 00:00:00 2001 From: Gangadhar Vukkesala Date: Sun, 21 Dec 2014 08:23:59 +0530 Subject: staging: rtl8192e: fixed a space coding style issue Fixed a space coding style issue in 3-dimensional array initialization which was found when running checkpatch.pl script on rtl819x_HTProc.c. Signed-off-by: Gangadhar Vukkesala Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192e/rtl819x_HTProc.c b/drivers/staging/rtl8192e/rtl819x_HTProc.c index c7f4508..1ea426b 100644 --- a/drivers/staging/rtl8192e/rtl819x_HTProc.c +++ b/drivers/staging/rtl8192e/rtl819x_HTProc.c @@ -34,13 +34,13 @@ u16 MCS_DATA_RATE[2][2][77] = { 468, 520, 0, 78, 104, 130, 117, 156, 195, 104, 130, 130, 156, 182, 182, 208, 156, 195, 195, 234, 273, 273, 312, 130, 156, 181, 156, 181, 208, 234, 208, 234, 260, 260, 286, 195, 234, 273, 234, 273, - 312, 351, 312, 351, 390, 390, 429} , + 312, 351, 312, 351, 390, 390, 429}, {14, 29, 43, 58, 87, 116, 130, 144, 29, 58, 87, 116, 173, 231, 260, 289, 43, 87, 130, 173, 260, 347, 390, 433, 58, 116, 173, 231, 347, 462, 520, 578, 0, 87, 116, 144, 130, 173, 217, 116, 144, 144, 173, 202, 202, 231, 173, 217, 217, 260, 303, 303, 347, 144, 173, 202, 173, 202, 231, 260, 231, 260, 289, 289, 318, 217, 260, 303, 260, 303, 347, 390, 347, 390, - 433, 433, 477} } , + 433, 433, 477} }, {{27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, 81, 162, 243, 324, 486, 648, 729, 810, 108, 216, 324, 432, 648, 864, 972, 1080, 12, 162, 216, 270, 243, 324, 405, 216, 270, 270, 324, -- cgit v0.10.2 From 0636b4603f83006166f2c8d80aaff4c157562724 Mon Sep 17 00:00:00 2001 From: Max Perepelitsyn Date: Fri, 2 Jan 2015 14:08:08 +0600 Subject: staging: rtl8712: remove spaces before commas checkpatch.pl fix for ERROR: space prohibited before that ',' (ctx:WxE) Signed-off-by: Max Perepelitsyn Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/rtl8712_cmd.h b/drivers/staging/rtl8712/rtl8712_cmd.h index 039ab3e..67e9e91 100644 --- a/drivers/staging/rtl8712/rtl8712_cmd.h +++ b/drivers/staging/rtl8712/rtl8712_cmd.h @@ -109,16 +109,16 @@ enum rtl8712_h2c_cmd { GEN_CMD_CODE(_DisconnectCtrlEx), /*61*/ /* To do, modify these h2c cmd, add or delete */ - GEN_CMD_CODE(_GetH2cLbk) , + GEN_CMD_CODE(_GetH2cLbk), /* WPS extra IE */ - GEN_CMD_CODE(_SetProbeReqExtraIE) , - GEN_CMD_CODE(_SetAssocReqExtraIE) , - GEN_CMD_CODE(_SetProbeRspExtraIE) , - GEN_CMD_CODE(_SetAssocRspExtraIE) , + GEN_CMD_CODE(_SetProbeReqExtraIE), + GEN_CMD_CODE(_SetAssocReqExtraIE), + GEN_CMD_CODE(_SetProbeRspExtraIE), + GEN_CMD_CODE(_SetAssocRspExtraIE), /* the following is driver will do */ - GEN_CMD_CODE(_GetCurDataRate) , + GEN_CMD_CODE(_GetCurDataRate), GEN_CMD_CODE(_GetTxRetrycnt), /* to record times that Tx retry to * transmit packet after association diff --git a/drivers/staging/rtl8712/rtl8712_event.h b/drivers/staging/rtl8712/rtl8712_event.h index 3d7f79e..29a4c23 100644 --- a/drivers/staging/rtl8712/rtl8712_event.h +++ b/drivers/staging/rtl8712/rtl8712_event.h @@ -27,7 +27,7 @@ #define _RTL8712_EVENT_H_ void r8712_event_handle(struct _adapter *padapter, uint *peventbuf); -void r8712_got_addbareq_event_callback(struct _adapter *adapter , u8 *pbuf); +void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf); enum rtl8712_c2h_event { GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/ diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index 73b7d86..9bb364f 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -196,7 +196,7 @@ static inline char *translate_scan(struct _adapter *padapter, if (p && ht_ielen > 0) { ht_cap = true; pht_capie = (struct ieee80211_ht_cap *)(p + 2); - memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2); + memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2); } /* Add the protocol name */ iwe.cmd = SIOCGIWNAME; @@ -1436,7 +1436,7 @@ static int r8711_wx_get_rate(struct net_device *dev, if (p && ht_ielen > 0) { ht_cap = true; pht_capie = (struct ieee80211_ht_cap *)(p + 2); - memcpy(&mcs_rate , pht_capie->supp_mcs_set, 2); + memcpy(&mcs_rate, pht_capie->supp_mcs_set, 2); bw_40MHz = (pht_capie->cap_info & IEEE80211_HT_CAP_SUP_WIDTH) ? 1 : 0; short_GI = (pht_capie->cap_info & diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c index b7462e8..977a833 100644 --- a/drivers/staging/rtl8712/rtl871x_mlme.c +++ b/drivers/staging/rtl8712/rtl871x_mlme.c @@ -93,7 +93,7 @@ struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv) return NULL; spin_lock_irqsave(&free_queue->lock, irqL); plist = free_queue->queue.next; - pnetwork = LIST_CONTAINOR(plist , struct wlan_network, list); + pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); list_del_init(&pnetwork->list); pnetwork->last_scanned = jiffies; pmlmepriv->num_of_scanned++; @@ -499,7 +499,7 @@ static int is_desired_network(struct _adapter *adapter, } /* TODO: Perry : For Power Management */ -void r8712_atimdone_event_callback(struct _adapter *adapter , u8 *pbuf) +void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf) { } diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h index 0526ba0..dbfb555 100644 --- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h +++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.h @@ -33,17 +33,17 @@ #define CMD_ALIVE BIT(2) enum Power_Mgnt { - PS_MODE_ACTIVE = 0 , - PS_MODE_MIN , - PS_MODE_MAX , - PS_MODE_DTIM , - PS_MODE_VOIP , - PS_MODE_UAPSD_WMM , - PS_MODE_UAPSD , - PS_MODE_IBSS , - PS_MODE_WWLAN , - PM_Radio_Off , - PM_Card_Disable , + PS_MODE_ACTIVE = 0, + PS_MODE_MIN, + PS_MODE_MAX, + PS_MODE_DTIM, + PS_MODE_VOIP, + PS_MODE_UAPSD_WMM, + PS_MODE_UAPSD, + PS_MODE_IBSS, + PS_MODE_WWLAN, + PM_Radio_Off, + PM_Card_Disable, PS_MODE_NUM }; diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c index de8acc1..1752121 100644 --- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c +++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c @@ -227,7 +227,7 @@ void r8712_free_all_stainfo(struct _adapter *padapter) struct sta_info, hash_list); plist = plist->next; if (pbcmc_stainfo != psta) - r8712_free_stainfo(padapter , psta); + r8712_free_stainfo(padapter, psta); } } spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL); diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c index 62a377e..a28af03 100644 --- a/drivers/staging/rtl8712/rtl871x_xmit.c +++ b/drivers/staging/rtl8712/rtl871x_xmit.c @@ -471,7 +471,7 @@ static sint xmitframe_swencrypt(struct _adapter *padapter, return _SUCCESS; } -static sint make_wlanhdr(struct _adapter *padapter , u8 *hdr, +static sint make_wlanhdr(struct _adapter *padapter, u8 *hdr, struct pkt_attrib *pattrib) { u16 *qc; diff --git a/drivers/staging/rtl8712/sta_info.h b/drivers/staging/rtl8712/sta_info.h index c4e0ef2..742dfa0 100644 --- a/drivers/staging/rtl8712/sta_info.h +++ b/drivers/staging/rtl8712/sta_info.h @@ -135,7 +135,7 @@ u32 _r8712_init_sta_priv(struct sta_priv *pstapriv); u32 _r8712_free_sta_priv(struct sta_priv *pstapriv); struct sta_info *r8712_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr); -void r8712_free_stainfo(struct _adapter *padapter , struct sta_info *psta); +void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta); void r8712_free_all_stainfo(struct _adapter *padapter); struct sta_info *r8712_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr); void r8712_init_bcmc_stainfo(struct _adapter *padapter); -- cgit v0.10.2 From c6d87638962000be057def45c35057e498c5b346 Mon Sep 17 00:00:00 2001 From: Rene Kolarik Date: Mon, 12 Jan 2015 02:31:57 +0100 Subject: drivers: staging: rtl8192u driver cleanup Correct redundant initialization reported by sparse Signed-off-by: Rene Kolarik Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index c451410..acaa723 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -241,7 +241,7 @@ static PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee, { //DIRECTION_VALUE dir; u8 dir; - bool search_dir[4] = {0, 0, 0, 0}; + bool search_dir[4] = {0}; struct list_head *psearch_list; //FIXME PTS_COMMON_INFO pRet = NULL; if(ieee->iw_mode == IW_MODE_MASTER) //ap mode -- cgit v0.10.2 From e77e19ac0fd5b9facdd4399972034c82aee770d1 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Sun, 4 Jan 2015 13:23:50 +0600 Subject: staging: rtl8192e: Fix duplicated conditional branch Signed-off-by: Alexander Kuleshov Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index 885315c..b8891c6 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c @@ -1661,8 +1661,8 @@ void dm_change_dynamic_initgain_thresh(struct net_device *dev, dm_digtable.rssi_low_thresh = dm_value; } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) { dm_digtable.rssi_high_power_highthresh = dm_value; - } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) { - dm_digtable.rssi_high_power_highthresh = dm_value; + } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_LOW) { + dm_digtable.rssi_high_power_lowthresh = dm_value; } else if (dm_type == DIG_TYPE_ENABLE) { dm_digtable.dig_state = DM_STA_DIG_MAX; dm_digtable.dig_enable_flag = true; -- cgit v0.10.2 From 8dcb6a251aad77d5699486596ea740d5cb0d1570 Mon Sep 17 00:00:00 2001 From: Vaishali Thakkar Date: Sat, 10 Jan 2015 16:05:32 +0530 Subject: Staging: rtl8192u: Remove check of ieee in rtl819x_BAProc.c This patch fixes following smatch warning: drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c:117 ieee80211_ADDBA() warn: variable dereferenced before check 'ieee' (see line 114) As ieee can not be NULL at this point, all such checks are removed. Signed-off-by: Vaishali Thakkar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index cd196ce..a9fd2cb 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -114,9 +114,9 @@ static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, P u16 len = ieee->tx_headroom + 9; //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2)) IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __func__, type, Dst, ieee->dev); - if (pBA == NULL||ieee == NULL) + if (pBA == NULL) { - IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee); + IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA is NULL\n"); return NULL; } skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME -- cgit v0.10.2 From ffcc4b59de22da4bc8a213457c25ac62f94b12eb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:39 -0700 Subject: staging: comedi: adl_pci9118: remove VIRT_TO_BUS dependancy This driver no longer uses virt_to_bus(). Remove the dependancy. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index a8201fe..1cdbf1f 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -724,7 +724,6 @@ config COMEDI_ADL_PCI9111 config COMEDI_ADL_PCI9118 tristate "ADLink PCI-9118DG, PCI-9118HG, PCI-9118HR support" depends on HAS_DMA - depends on VIRT_TO_BUS ---help--- Enable support for ADlink PCI-9118DG, PCI-9118HG, PCI-9118HR cards -- cgit v0.10.2 From f19810d21becb4f3a92ce8d0b7cc2a0657a153de Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:40 -0700 Subject: staging: comedi: das1800: reduce indent level of das1800_init_dma() An IRQ and at least one DMA channel are required to use DMA with this driver. Move the check to the caller to reduce the indent level of this function. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index be825d2..c415b57 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1240,72 +1240,70 @@ static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, struct das1800_private *devpriv = dev->private; unsigned long flags; - /* need an irq to do dma */ - if (dev->irq && dma0) { - /* encode dma0 and dma1 into 2 digit hexadecimal for switch */ - switch ((dma0 & 0x7) | (dma1 << 4)) { - case 0x5: /* dma0 == 5 */ - devpriv->dma_bits |= DMA_CH5; - break; - case 0x6: /* dma0 == 6 */ - devpriv->dma_bits |= DMA_CH6; - break; - case 0x7: /* dma0 == 7 */ - devpriv->dma_bits |= DMA_CH7; - break; - case 0x65: /* dma0 == 5, dma1 == 6 */ - devpriv->dma_bits |= DMA_CH5_CH6; - break; - case 0x76: /* dma0 == 6, dma1 == 7 */ - devpriv->dma_bits |= DMA_CH6_CH7; - break; - case 0x57: /* dma0 == 7, dma1 == 5 */ - devpriv->dma_bits |= DMA_CH7_CH5; - break; - default: - dev_err(dev->class_dev, - "only supports dma channels 5 through 7\n"); - dev_err(dev->class_dev, - "Dual dma only allows the following combinations:\n"); - dev_err(dev->class_dev, - "dma 5,6 / 6,7 / or 7,5\n"); - return -EINVAL; - } - if (request_dma(dma0, dev->driver->driver_name)) { + /* encode dma0 and dma1 into 2 digit hexadecimal for switch */ + switch ((dma0 & 0x7) | (dma1 << 4)) { + case 0x5: /* dma0 == 5 */ + devpriv->dma_bits |= DMA_CH5; + break; + case 0x6: /* dma0 == 6 */ + devpriv->dma_bits |= DMA_CH6; + break; + case 0x7: /* dma0 == 7 */ + devpriv->dma_bits |= DMA_CH7; + break; + case 0x65: /* dma0 == 5, dma1 == 6 */ + devpriv->dma_bits |= DMA_CH5_CH6; + break; + case 0x76: /* dma0 == 6, dma1 == 7 */ + devpriv->dma_bits |= DMA_CH6_CH7; + break; + case 0x57: /* dma0 == 7, dma1 == 5 */ + devpriv->dma_bits |= DMA_CH7_CH5; + break; + default: + dev_err(dev->class_dev, + "only supports dma channels 5 through 7\n"); + dev_err(dev->class_dev, + "Dual dma only allows the following combinations:\n"); + dev_err(dev->class_dev, + "dma 5,6 / 6,7 / or 7,5\n"); + return -EINVAL; + } + if (request_dma(dma0, dev->driver->driver_name)) { + dev_err(dev->class_dev, + "failed to allocate dma channel %i\n", dma0); + return -EINVAL; + } + devpriv->dma0 = dma0; + devpriv->dma_current = dma0; + if (dma1) { + if (request_dma(dma1, dev->driver->driver_name)) { dev_err(dev->class_dev, - "failed to allocate dma channel %i\n", dma0); + "failed to allocate dma channel %i\n", + dma1); return -EINVAL; } - devpriv->dma0 = dma0; - devpriv->dma_current = dma0; - if (dma1) { - if (request_dma(dma1, dev->driver->driver_name)) { - dev_err(dev->class_dev, - "failed to allocate dma channel %i\n", - dma1); - return -EINVAL; - } - devpriv->dma1 = dma1; - } - devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); - if (devpriv->ai_buf0 == NULL) + devpriv->dma1 = dma1; + } + devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if (devpriv->ai_buf0 == NULL) + return -ENOMEM; + devpriv->dma_current_buf = devpriv->ai_buf0; + if (dma1) { + devpriv->ai_buf1 = + kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if (devpriv->ai_buf1 == NULL) return -ENOMEM; - devpriv->dma_current_buf = devpriv->ai_buf0; - if (dma1) { - devpriv->ai_buf1 = - kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); - if (devpriv->ai_buf1 == NULL) - return -ENOMEM; - } - flags = claim_dma_lock(); - disable_dma(devpriv->dma0); - set_dma_mode(devpriv->dma0, DMA_MODE_READ); - if (dma1) { - disable_dma(devpriv->dma1); - set_dma_mode(devpriv->dma1, DMA_MODE_READ); - } - release_dma_lock(flags); } + flags = claim_dma_lock(); + disable_dma(devpriv->dma0); + set_dma_mode(devpriv->dma0, DMA_MODE_READ); + if (dma1) { + disable_dma(devpriv->dma1); + set_dma_mode(devpriv->dma1, DMA_MODE_READ); + } + release_dma_lock(flags); + return 0; } @@ -1437,9 +1435,12 @@ static int das1800_attach(struct comedi_device *dev, } } - ret = das1800_init_dma(dev, dma0, dma1); - if (ret < 0) - return ret; + /* an irq and one dma channel is required to use dma */ + if (dev->irq & dma0) { + ret = das1800_init_dma(dev, dma0, dma1); + if (ret < 0) + return ret; + } if (devpriv->ai_buf0 == NULL) { devpriv->ai_buf0 = -- cgit v0.10.2 From 1f190a73590ce0070d6a5b6ee0d50e076aafebd6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:41 -0700 Subject: staging: comedi: das1800: separate AI FIFO bounce buffer from DMA buffer This driver can use DMA or the hardware FIFO to read analog input samples. When DMA is enabled it's also possible for some async commands to cause DMA to be disabled and the FIFO is used instead. Currently the first DMA channels buffer is used for the bounce buffer when using the FIFO. For aesthetics, add a new member to the private data and use that for the FIFO bounce buffer. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index c415b57..2e087b1 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -433,6 +433,7 @@ struct das1800_private { uint16_t *ai_buf0; /* pointers to dma buffers */ uint16_t *ai_buf1; uint16_t *dma_current_buf; /* pointer to dma buffer currently being used */ + uint16_t *fifo_buf; /* bounce buffer for analog input FIFO */ unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */ unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */ unsigned short ao_update_bits; /* remembers the last write to the @@ -480,9 +481,9 @@ static void das1800_handle_fifo_half_full(struct comedi_device *dev, struct das1800_private *devpriv = dev->private; unsigned int nsamples = comedi_nsamples_left(s, FIFO_SIZE / 2); - insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, nsamples); - munge_data(dev, devpriv->ai_buf0, nsamples); - comedi_buf_write_samples(s, devpriv->ai_buf0, nsamples); + insw(dev->iobase + DAS1800_FIFO, devpriv->fifo_buf, nsamples); + munge_data(dev, devpriv->fifo_buf, nsamples); + comedi_buf_write_samples(s, devpriv->fifo_buf, nsamples); } static void das1800_handle_fifo_not_empty(struct comedi_device *dev, @@ -1442,12 +1443,9 @@ static int das1800_attach(struct comedi_device *dev, return ret; } - if (devpriv->ai_buf0 == NULL) { - devpriv->ai_buf0 = - kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL); - if (devpriv->ai_buf0 == NULL) - return -ENOMEM; - } + devpriv->fifo_buf = kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL); + if (!devpriv->fifo_buf) + return -ENOMEM; ret = comedi_alloc_subdevices(dev, 4); if (ret) @@ -1531,6 +1529,7 @@ static void das1800_detach(struct comedi_device *dev) free_dma(devpriv->dma1); kfree(devpriv->ai_buf0); kfree(devpriv->ai_buf1); + kfree(devpriv->fifo_buf); if (devpriv->iobase2) release_region(devpriv->iobase2, DAS1800_SIZE); } -- cgit v0.10.2 From fd8aab1a9c4505dc410f189c81911f8d6a99c6fc Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:42 -0700 Subject: staging: comedi: das1800: introduce struct das1800_dma_desc For aesthetics, introduce a struct to hold the DMA descriptor data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 2e087b1..2d376fd 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -420,6 +420,11 @@ static const struct das1800_board das1800_boards[] = { }, }; +struct das1800_dma_desc { + unsigned int chan; /* DMA channel */ + uint16_t *virt_addr; /* virtual address of DMA buffer */ +}; + struct das1800_private { unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */ unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */ @@ -427,12 +432,8 @@ struct das1800_private { /* dma bits for control register b, stored so that dma can be * turned on and off */ int dma_bits; - unsigned int dma0; /* dma channels used */ - unsigned int dma1; - unsigned int dma_current; /* dma channel currently in use */ - uint16_t *ai_buf0; /* pointers to dma buffers */ - uint16_t *ai_buf1; - uint16_t *dma_current_buf; /* pointer to dma buffer currently being used */ + struct das1800_dma_desc dma_desc[2]; + int cur_dma; uint16_t *fifo_buf; /* bounce buffer for analog input FIFO */ unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */ unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */ @@ -540,24 +541,18 @@ static void das1800_flush_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; + struct das1800_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; unsigned long flags; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; flags = claim_dma_lock(); - das1800_flush_dma_channel(dev, s, devpriv->dma_current, - devpriv->dma_current_buf); + das1800_flush_dma_channel(dev, s, dma->chan, dma->virt_addr); if (dual_dma) { /* switch to other channel and flush it */ - if (devpriv->dma_current == devpriv->dma0) { - devpriv->dma_current = devpriv->dma1; - devpriv->dma_current_buf = devpriv->ai_buf1; - } else { - devpriv->dma_current = devpriv->dma0; - devpriv->dma_current_buf = devpriv->ai_buf0; - } - das1800_flush_dma_channel(dev, s, devpriv->dma_current, - devpriv->dma_current_buf); + devpriv->cur_dma = 1 - devpriv->cur_dma; + dma = &devpriv->dma_desc[devpriv->cur_dma]; + das1800_flush_dma_channel(dev, s, dma->chan, dma->virt_addr); } release_dma_lock(flags); @@ -570,47 +565,43 @@ static void das1800_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int status) { struct das1800_private *devpriv = dev->private; + struct das1800_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; unsigned long flags; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; flags = claim_dma_lock(); - das1800_flush_dma_channel(dev, s, devpriv->dma_current, - devpriv->dma_current_buf); + das1800_flush_dma_channel(dev, s, dma->chan, dma->virt_addr); /* re-enable dma channel */ - set_dma_addr(devpriv->dma_current, - virt_to_bus(devpriv->dma_current_buf)); - set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size); - enable_dma(devpriv->dma_current); + set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); + set_dma_count(dma->chan, devpriv->dma_transfer_size); + enable_dma(dma->chan); release_dma_lock(flags); if (status & DMATC) { /* clear DMATC interrupt bit */ outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS); /* switch dma channels for next time, if appropriate */ - if (dual_dma) { - /* read data from the other channel next time */ - if (devpriv->dma_current == devpriv->dma0) { - devpriv->dma_current = devpriv->dma1; - devpriv->dma_current_buf = devpriv->ai_buf1; - } else { - devpriv->dma_current = devpriv->dma0; - devpriv->dma_current_buf = devpriv->ai_buf0; - } - } + if (dual_dma) + devpriv->cur_dma = 1 - devpriv->cur_dma; } } static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; + struct das1800_dma_desc *dma; + int i; outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */ outb(0x0, dev->iobase + DAS1800_CONTROL_B); /* disable interrupts and dma */ outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */ - if (devpriv->dma0) - disable_dma(devpriv->dma0); - if (devpriv->dma1) - disable_dma(devpriv->dma1); + + for (i = 0; i < 2; i++) { + dma = &devpriv->dma_desc[i]; + if (dma->chan) + disable_dma(dma->chan); + } + return 0; } @@ -1006,35 +997,37 @@ static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd) static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) { struct das1800_private *devpriv = dev->private; + struct das1800_dma_desc *dma = &devpriv->dma_desc[0]; unsigned long lock_flags; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0) return; + devpriv->cur_dma = 0; + /* determine a reasonable dma transfer size */ devpriv->dma_transfer_size = suggest_transfer_size(cmd); lock_flags = claim_dma_lock(); - disable_dma(devpriv->dma0); + disable_dma(dma->chan); /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ - clear_dma_ff(devpriv->dma0); - set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0)); + clear_dma_ff(dma->chan); + set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); /* set appropriate size of transfer */ - set_dma_count(devpriv->dma0, devpriv->dma_transfer_size); - devpriv->dma_current = devpriv->dma0; - devpriv->dma_current_buf = devpriv->ai_buf0; - enable_dma(devpriv->dma0); + set_dma_count(dma->chan, devpriv->dma_transfer_size); + enable_dma(dma->chan); /* set up dual dma if appropriate */ if (dual_dma) { - disable_dma(devpriv->dma1); + dma = &devpriv->dma_desc[1]; + disable_dma(dma->chan); /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ - clear_dma_ff(devpriv->dma1); - set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1)); + clear_dma_ff(dma->chan); + set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); /* set appropriate size of transfer */ - set_dma_count(devpriv->dma1, devpriv->dma_transfer_size); - enable_dma(devpriv->dma1); + set_dma_count(dma->chan, devpriv->dma_transfer_size); + enable_dma(dma->chan); } release_dma_lock(lock_flags); } @@ -1239,6 +1232,7 @@ static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, unsigned int dma1) { struct das1800_private *devpriv = dev->private; + struct das1800_dma_desc *dma; unsigned long flags; /* encode dma0 and dma1 into 2 digit hexadecimal for switch */ @@ -1270,40 +1264,39 @@ static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, "dma 5,6 / 6,7 / or 7,5\n"); return -EINVAL; } + + dma = &devpriv->dma_desc[0]; if (request_dma(dma0, dev->driver->driver_name)) { dev_err(dev->class_dev, "failed to allocate dma channel %i\n", dma0); return -EINVAL; } - devpriv->dma0 = dma0; - devpriv->dma_current = dma0; + dma->chan = dma0; + dma->virt_addr = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if (!dma->virt_addr) + return -ENOMEM; + flags = claim_dma_lock(); + disable_dma(dma->chan); + set_dma_mode(dma->chan, DMA_MODE_READ); + release_dma_lock(flags); + if (dma1) { + dma = &devpriv->dma_desc[1]; if (request_dma(dma1, dev->driver->driver_name)) { dev_err(dev->class_dev, "failed to allocate dma channel %i\n", dma1); return -EINVAL; } - devpriv->dma1 = dma1; - } - devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); - if (devpriv->ai_buf0 == NULL) - return -ENOMEM; - devpriv->dma_current_buf = devpriv->ai_buf0; - if (dma1) { - devpriv->ai_buf1 = - kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); - if (devpriv->ai_buf1 == NULL) + dma->chan = dma1; + dma->virt_addr = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); + if (!dma->virt_addr) return -ENOMEM; + flags = claim_dma_lock(); + disable_dma(dma->chan); + set_dma_mode(dma->chan, DMA_MODE_READ); + release_dma_lock(flags); } - flags = claim_dma_lock(); - disable_dma(devpriv->dma0); - set_dma_mode(devpriv->dma0, DMA_MODE_READ); - if (dma1) { - disable_dma(devpriv->dma1); - set_dma_mode(devpriv->dma1, DMA_MODE_READ); - } - release_dma_lock(flags); return 0; } @@ -1521,14 +1514,16 @@ static int das1800_attach(struct comedi_device *dev, static void das1800_detach(struct comedi_device *dev) { struct das1800_private *devpriv = dev->private; + struct das1800_dma_desc *dma; + int i; if (devpriv) { - if (devpriv->dma0) - free_dma(devpriv->dma0); - if (devpriv->dma1) - free_dma(devpriv->dma1); - kfree(devpriv->ai_buf0); - kfree(devpriv->ai_buf1); + for (i = 0; i < 2; i++) { + dma = &devpriv->dma_desc[i]; + if (dma->chan) + free_dma(dma->chan); + kfree(dma->virt_addr); + } kfree(devpriv->fifo_buf); if (devpriv->iobase2) release_region(devpriv->iobase2, DAS1800_SIZE); -- cgit v0.10.2 From 6e89008b06c344b49e27febdeb5fc7b84d35fb25 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:43 -0700 Subject: staging: comedi: das1800: tidy up das1800_init_dma() Refactor this function so that a for loop can be used to request and set up the two DMA descriptors. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 2d376fd..df28d36 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1228,15 +1228,24 @@ static int das1800_do_wbits(struct comedi_device *dev, return insn->n; } -static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, - unsigned int dma1) +static int das1800_init_dma(struct comedi_device *dev, + struct comedi_devconfig *it) { struct das1800_private *devpriv = dev->private; struct das1800_dma_desc *dma; + unsigned int *dma_chan; unsigned long flags; + int i; + + /* + * it->options[2] is DMA channel 0 + * it->options[3] is DMA channel 1 + * + * Encode the DMA channels into 2 digit hexadecimal for switch. + */ + dma_chan = &it->options[2]; - /* encode dma0 and dma1 into 2 digit hexadecimal for switch */ - switch ((dma0 & 0x7) | (dma1 << 4)) { + switch ((dma_chan[0] & 0x7) | (dma_chan[1] << 4)) { case 0x5: /* dma0 == 5 */ devpriv->dma_bits |= DMA_CH5; break; @@ -1265,33 +1274,24 @@ static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0, return -EINVAL; } - dma = &devpriv->dma_desc[0]; - if (request_dma(dma0, dev->driver->driver_name)) { - dev_err(dev->class_dev, - "failed to allocate dma channel %i\n", dma0); - return -EINVAL; - } - dma->chan = dma0; - dma->virt_addr = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); - if (!dma->virt_addr) - return -ENOMEM; - flags = claim_dma_lock(); - disable_dma(dma->chan); - set_dma_mode(dma->chan, DMA_MODE_READ); - release_dma_lock(flags); + for (i = 0; i < 2; i++) { + dma = &devpriv->dma_desc[i]; - if (dma1) { - dma = &devpriv->dma_desc[1]; - if (request_dma(dma1, dev->driver->driver_name)) { + if (dma_chan[i] == 0) + break; + + if (request_dma(dma_chan[i], dev->board_name)) { dev_err(dev->class_dev, "failed to allocate dma channel %i\n", - dma1); + dma_chan[i]); return -EINVAL; } - dma->chan = dma1; + dma->chan = dma_chan[i]; + dma->virt_addr = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); if (!dma->virt_addr) return -ENOMEM; + flags = claim_dma_lock(); disable_dma(dma->chan); set_dma_mode(dma->chan, DMA_MODE_READ); @@ -1366,8 +1366,6 @@ static int das1800_attach(struct comedi_device *dev, struct das1800_private *devpriv; struct comedi_subdevice *s; unsigned int irq = it->options[1]; - unsigned int dma0 = it->options[2]; - unsigned int dma1 = it->options[3]; int board; int ret; @@ -1430,8 +1428,8 @@ static int das1800_attach(struct comedi_device *dev, } /* an irq and one dma channel is required to use dma */ - if (dev->irq & dma0) { - ret = das1800_init_dma(dev, dma0, dma1); + if (dev->irq & it->options[2]) { + ret = das1800_init_dma(dev, it); if (ret < 0) return ret; } -- cgit v0.10.2 From a4b064ee4675686dfe31fcc54c3ec188141f6ee2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:44 -0700 Subject: staging: comedi: das1800: remove VIRT_TO_BUS dependancy Use dma_{alloc,free}_coherent() to allocate and free the DMA buffers. This removes the dependancy on VIRT_TO_BUS. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 1cdbf1f..fe030a3 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -309,7 +309,7 @@ config COMEDI_DAS800 config COMEDI_DAS1800 tristate "DAS1800 and compatible ISA card support" - depends on VIRT_TO_BUS && ISA_DMA_API + depends on ISA_DMA_API ---help--- Enable support for DAS1800 and compatible ISA cards Keithley Metrabyte DAS-1701ST, DAS-1701ST-DA, DAS-1701/AO, diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index df28d36..dd46a91 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -422,7 +422,8 @@ static const struct das1800_board das1800_boards[] = { struct das1800_dma_desc { unsigned int chan; /* DMA channel */ - uint16_t *virt_addr; /* virtual address of DMA buffer */ + void *virt_addr; /* virtual address of DMA buffer */ + dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ }; struct das1800_private { @@ -572,7 +573,7 @@ static void das1800_handle_dma(struct comedi_device *dev, flags = claim_dma_lock(); das1800_flush_dma_channel(dev, s, dma->chan, dma->virt_addr); /* re-enable dma channel */ - set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); + set_dma_addr(dma->chan, dma->hw_addr); set_dma_count(dma->chan, devpriv->dma_transfer_size); enable_dma(dma->chan); release_dma_lock(flags); @@ -1013,7 +1014,7 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ clear_dma_ff(dma->chan); - set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); + set_dma_addr(dma->chan, dma->hw_addr); /* set appropriate size of transfer */ set_dma_count(dma->chan, devpriv->dma_transfer_size); enable_dma(dma->chan); @@ -1024,7 +1025,7 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ clear_dma_ff(dma->chan); - set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); + set_dma_addr(dma->chan, dma->hw_addr); /* set appropriate size of transfer */ set_dma_count(dma->chan, devpriv->dma_transfer_size); enable_dma(dma->chan); @@ -1288,7 +1289,8 @@ static int das1800_init_dma(struct comedi_device *dev, } dma->chan = dma_chan[i]; - dma->virt_addr = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); + dma->virt_addr = dma_alloc_coherent(NULL, DMA_BUF_SIZE, + &dma->hw_addr, GFP_KERNEL); if (!dma->virt_addr) return -ENOMEM; @@ -1520,7 +1522,9 @@ static void das1800_detach(struct comedi_device *dev) dma = &devpriv->dma_desc[i]; if (dma->chan) free_dma(dma->chan); - kfree(dma->virt_addr); + if (dma->virt_addr) + dma_free_coherent(NULL, DMA_BUF_SIZE, + dma->virt_addr, dma->hw_addr); } kfree(devpriv->fifo_buf); if (devpriv->iobase2) -- cgit v0.10.2 From 99b21f22d2b6708bfe06507d5f8a6955766f8b27 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:45 -0700 Subject: staging: comedi: das1800: introduce das1800_free_dma() For aesthetics, introduce a helper function to free the DMA channels and allocated buffers. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index dd46a91..1eb5eab 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1303,6 +1303,25 @@ static int das1800_init_dma(struct comedi_device *dev, return 0; } +static void das1800_free_dma(struct comedi_device *dev) +{ + struct das1800_private *devpriv = dev->private; + struct das1800_dma_desc *dma; + int i; + + if (!devpriv) + return; + + for (i = 0; i < 2; i++) { + dma = &devpriv->dma_desc[i]; + if (dma->chan) + free_dma(dma->chan); + if (dma->virt_addr) + dma_free_coherent(NULL, DMA_BUF_SIZE, + dma->virt_addr, dma->hw_addr); + } +} + static int das1800_probe(struct comedi_device *dev) { const struct das1800_board *board = dev->board_ptr; @@ -1514,18 +1533,9 @@ static int das1800_attach(struct comedi_device *dev, static void das1800_detach(struct comedi_device *dev) { struct das1800_private *devpriv = dev->private; - struct das1800_dma_desc *dma; - int i; + das1800_free_dma(dev); if (devpriv) { - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; - if (dma->chan) - free_dma(dma->chan); - if (dma->virt_addr) - dma_free_coherent(NULL, DMA_BUF_SIZE, - dma->virt_addr, dma->hw_addr); - } kfree(devpriv->fifo_buf); if (devpriv->iobase2) release_region(devpriv->iobase2, DAS1800_SIZE); -- cgit v0.10.2 From 45478548425cc84d2d39cdac9daf446e5744877d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:46 -0700 Subject: staging: comedi: ni_at_a2150: remove 'volatile' from private data variable As indicated by checkpatch.pl, "WARNING: Use of volatile is usually wrong: ...", the 'count' member of the private data does not need to be volatile. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 69e543a..8265322 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -146,8 +146,7 @@ static const struct a2150_board a2150_boards[] = { }; struct a2150_private { - - volatile unsigned int count; /* number of data points left to be taken */ + unsigned int count; /* number of data points left to be taken */ unsigned int dma; /* dma channel */ uint16_t *dma_buffer; /* dma buffer */ unsigned int dma_transfer_size; /* size in bytes of dma transfers */ -- cgit v0.10.2 From 2447a27c877a1a4995a85eb4bc456551c0c5a5f9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:47 -0700 Subject: staging: comedi: ni_at_a2150: use comedi_bytes_per_sample() For aesthetics, use the helper function to get the byte size of each sample instead of using sizeof() the first buffer element. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 8265322..7380dac 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -551,14 +551,14 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* set size of transfer to fill in 1/3 second */ #define ONE_THIRD_SECOND 333333333 devpriv->dma_transfer_size = - sizeof(devpriv->dma_buffer[0]) * cmd->chanlist_len * + comedi_bytes_per_sample(s) * cmd->chanlist_len * ONE_THIRD_SECOND / cmd->scan_begin_arg; if (devpriv->dma_transfer_size > A2150_DMA_BUFFER_SIZE) devpriv->dma_transfer_size = A2150_DMA_BUFFER_SIZE; - if (devpriv->dma_transfer_size < sizeof(devpriv->dma_buffer[0])) - devpriv->dma_transfer_size = sizeof(devpriv->dma_buffer[0]); + if (devpriv->dma_transfer_size < comedi_bytes_per_sample(s)) + devpriv->dma_transfer_size = comedi_bytes_per_sample(s); devpriv->dma_transfer_size -= - devpriv->dma_transfer_size % sizeof(devpriv->dma_buffer[0]); + devpriv->dma_transfer_size % comedi_bytes_per_sample(s); set_dma_count(devpriv->dma, devpriv->dma_transfer_size); enable_dma(devpriv->dma); release_dma_lock(lock_flags); -- cgit v0.10.2 From 7cbb0ef93a63f7c0574d852607af71f348ccc751 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:48 -0700 Subject: staging: comedi: ni_at_a2150: introduce a2150_alloc_irq_dma() This driver requires an IRQ and DMA in order to support async commands. For aesthetics, introduce a helper function to request the IRQ and DMA channels and allocate the DMA buffer. Since the async command support is optional, make the helper function handle any request/allocation errors and allow the driver to still attach without async command support. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 7380dac..11b1681 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -676,6 +676,50 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return n; } +static void a2150_alloc_irq_dma(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct a2150_private *devpriv = dev->private; + unsigned int irq_num = it->options[1]; + unsigned int dma_chan = it->options[2]; + + /* + * Only IRQs 15, 14, 12-9, and 7-3 are valid. + * Only DMA channels 7-5 and 3-0 are valid. + * + * Both must be valid for async command support. + */ + if (irq_num > 15 || dma_chan > 7 || + !((1 << irq_num) & 0xdef8) || !((1 << dma_chan) & 0xef)) + return; + + /* + * Request the IRQ and DMA channels and allocate the DMA buffer. + * If the requests or allocation fail async command supprt will + * not be available. + */ + if (request_irq(irq_num, a2150_interrupt, 0, dev->board_name, dev)) + return; + if (request_dma(dma_chan, dev->board_name)) { + free_irq(irq_num, dev); + return; + } + devpriv->dma_buffer = kmalloc(A2150_DMA_BUFFER_SIZE, + GFP_KERNEL | GFP_DMA); + if (!devpriv->dma_buffer) { + free_dma(dma_chan); + free_irq(irq_num, dev); + return; + } + + dev->irq = irq_num; + devpriv->dma = dma_chan; + devpriv->irq_dma_bits = IRQ_LVL_BITS(irq_num) | DMA_CHAN_BITS(dma_chan); + + disable_dma(dma_chan); + set_dma_mode(dma_chan, DMA_MODE_READ); +} + /* probes board type, returns offset */ static int a2150_probe(struct comedi_device *dev) { @@ -689,8 +733,6 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct a2150_board *thisboard; struct a2150_private *devpriv; struct comedi_subdevice *s; - unsigned int irq = it->options[1]; - unsigned int dma = it->options[2]; static const int timeout = 2000; int i; int ret; @@ -711,31 +753,7 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) thisboard = dev->board_ptr; dev->board_name = thisboard->name; - if ((irq >= 3 && irq <= 7) || (irq >= 9 && irq <= 12) || - irq == 14 || irq == 15) { - ret = request_irq(irq, a2150_interrupt, 0, - dev->board_name, dev); - if (ret == 0) { - devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq); - dev->irq = irq; - } - } - - if (dev->irq && dma <= 7 && dma != 4) { - ret = request_dma(dma, dev->board_name); - if (ret == 0) { - devpriv->dma = dma; - devpriv->dma_buffer = kmalloc(A2150_DMA_BUFFER_SIZE, - GFP_KERNEL | GFP_DMA); - if (!devpriv->dma_buffer) - return -ENOMEM; - - disable_dma(dma); - set_dma_mode(dma, DMA_MODE_READ); - - devpriv->irq_dma_bits |= DMA_CHAN_BITS(dma); - } - } + a2150_alloc_irq_dma(dev, it); ret = comedi_alloc_subdevices(dev, 1); if (ret) @@ -749,7 +767,7 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->maxdata = 0xffff; s->range_table = &range_a2150; s->insn_read = a2150_ai_rinsn; - if (dev->irq && devpriv->dma) { + if (dev->irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; s->len_chanlist = s->n_chan; -- cgit v0.10.2 From b1478901b677dd430f4e97989f7f6e2dc8e54556 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:49 -0700 Subject: staging: comedi: ni_at_a2150: introduce a2150_free_dma() For aesthetics, introduce a helper function to free the DMA channel and buffer. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 11b1681..de2e877 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -720,6 +720,18 @@ static void a2150_alloc_irq_dma(struct comedi_device *dev, set_dma_mode(dma_chan, DMA_MODE_READ); } +static void a2150_free_dma(struct comedi_device *dev) +{ + struct a2150_private *devpriv = dev->private; + + if (!devpriv) + return; + + if (devpriv->dma) + free_dma(devpriv->dma); + kfree(devpriv->dma_buffer); +} + /* probes board type, returns offset */ static int a2150_probe(struct comedi_device *dev) { @@ -808,15 +820,9 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void a2150_detach(struct comedi_device *dev) { - struct a2150_private *devpriv = dev->private; - if (dev->iobase) outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG); - if (devpriv) { - if (devpriv->dma) - free_dma(devpriv->dma); - kfree(devpriv->dma_buffer); - } + a2150_free_dma(dev); comedi_legacy_detach(dev); }; -- cgit v0.10.2 From 5bf7d295610a0789dc649e4e45714fecd7d042b4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:50 -0700 Subject: staging: comedi: ni_at_a2150: introduce struct a2150_dma_desc For aesthetics, introduce a struct to hold the DMA descriptor data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index de2e877..a1300e0 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -145,11 +145,15 @@ static const struct a2150_board a2150_boards[] = { }, }; +struct a2150_dma_desc { + unsigned int chan; /* DMA channel */ + uint16_t *virt_addr; /* virtual address of DMA buffer */ + unsigned int size; /* size of DMA transfer (in bytes) */ +}; + struct a2150_private { + struct a2150_dma_desc dma_desc; unsigned int count; /* number of data points left to be taken */ - unsigned int dma; /* dma channel */ - uint16_t *dma_buffer; /* dma buffer */ - unsigned int dma_transfer_size; /* size in bytes of dma transfers */ int irq_dma_bits; /* irq/dma register bits */ int config_bits; /* config register bits */ }; @@ -162,6 +166,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) unsigned long flags; struct comedi_device *dev = d; struct a2150_private *devpriv = dev->private; + struct a2150_dma_desc *dma = &devpriv->dma_desc; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async; struct comedi_cmd *cmd; @@ -198,18 +203,18 @@ static irqreturn_t a2150_interrupt(int irq, void *d) } flags = claim_dma_lock(); - disable_dma(devpriv->dma); + disable_dma(dma->chan); /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ - clear_dma_ff(devpriv->dma); + clear_dma_ff(dma->chan); /* figure out how many points to read */ - max_points = comedi_bytes_to_samples(s, devpriv->dma_transfer_size); + max_points = comedi_bytes_to_samples(s, dma->size); /* residue is the number of points left to be done on the dma * transfer. It should always be zero at this point unless * the stop_src is set to external triggering. */ - residue = comedi_bytes_to_samples(s, get_dma_residue(devpriv->dma)); + residue = comedi_bytes_to_samples(s, get_dma_residue(dma->chan)); num_points = max_points - residue; if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT) num_points = devpriv->count; @@ -217,8 +222,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) /* figure out how many points will be stored next time */ leftover = 0; if (cmd->stop_src == TRIG_NONE) { - leftover = comedi_bytes_to_samples(s, - devpriv->dma_transfer_size); + leftover = comedi_bytes_to_samples(s, dma->size); } else if (devpriv->count > max_points) { leftover = devpriv->count - max_points; if (leftover > max_points) @@ -233,7 +237,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) for (i = 0; i < num_points; i++) { /* write data point to comedi buffer */ - dpnt = devpriv->dma_buffer[i]; + dpnt = dma->virt_addr[i]; /* convert from 2's complement to unsigned coding */ dpnt ^= 0x8000; comedi_buf_write_samples(s, &dpnt, 1); @@ -246,10 +250,10 @@ static irqreturn_t a2150_interrupt(int irq, void *d) } /* re-enable dma */ if (leftover) { - set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer)); - set_dma_count(devpriv->dma, + set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); + set_dma_count(dma->chan, comedi_samples_to_bytes(s, leftover)); - enable_dma(devpriv->dma); + enable_dma(dma->chan); } release_dma_lock(flags); @@ -264,13 +268,14 @@ static irqreturn_t a2150_interrupt(int irq, void *d) static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct a2150_private *devpriv = dev->private; + struct a2150_dma_desc *dma = &devpriv->dma_desc; /* disable dma on card */ devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT; outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); /* disable computer's dma */ - disable_dma(devpriv->dma); + disable_dma(dma->chan); /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); @@ -502,6 +507,7 @@ static int a2150_ai_cmdtest(struct comedi_device *dev, static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct a2150_private *devpriv = dev->private; + struct a2150_dma_desc *dma = &devpriv->dma_desc; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned long timer_base = dev->iobase + I8253_BASE_REG; @@ -543,24 +549,22 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* enable computer's dma */ lock_flags = claim_dma_lock(); - disable_dma(devpriv->dma); + disable_dma(dma->chan); /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ - clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer)); + clear_dma_ff(dma->chan); + set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); /* set size of transfer to fill in 1/3 second */ #define ONE_THIRD_SECOND 333333333 - devpriv->dma_transfer_size = - comedi_bytes_per_sample(s) * cmd->chanlist_len * - ONE_THIRD_SECOND / cmd->scan_begin_arg; - if (devpriv->dma_transfer_size > A2150_DMA_BUFFER_SIZE) - devpriv->dma_transfer_size = A2150_DMA_BUFFER_SIZE; - if (devpriv->dma_transfer_size < comedi_bytes_per_sample(s)) - devpriv->dma_transfer_size = comedi_bytes_per_sample(s); - devpriv->dma_transfer_size -= - devpriv->dma_transfer_size % comedi_bytes_per_sample(s); - set_dma_count(devpriv->dma, devpriv->dma_transfer_size); - enable_dma(devpriv->dma); + dma->size = comedi_bytes_per_sample(s) * cmd->chanlist_len * + ONE_THIRD_SECOND / cmd->scan_begin_arg; + if (dma->size > A2150_DMA_BUFFER_SIZE) + dma->size = A2150_DMA_BUFFER_SIZE; + if (dma->size < comedi_bytes_per_sample(s)) + dma->size = comedi_bytes_per_sample(s); + dma->size -= dma->size % comedi_bytes_per_sample(s); + set_dma_count(dma->chan, dma->size); + enable_dma(dma->chan); release_dma_lock(lock_flags); /* clear dma interrupt before enabling it, to try and get rid of that @@ -680,6 +684,7 @@ static void a2150_alloc_irq_dma(struct comedi_device *dev, struct comedi_devconfig *it) { struct a2150_private *devpriv = dev->private; + struct a2150_dma_desc *dma = &devpriv->dma_desc; unsigned int irq_num = it->options[1]; unsigned int dma_chan = it->options[2]; @@ -704,16 +709,15 @@ static void a2150_alloc_irq_dma(struct comedi_device *dev, free_irq(irq_num, dev); return; } - devpriv->dma_buffer = kmalloc(A2150_DMA_BUFFER_SIZE, - GFP_KERNEL | GFP_DMA); - if (!devpriv->dma_buffer) { + dma->virt_addr = kmalloc(A2150_DMA_BUFFER_SIZE, GFP_KERNEL | GFP_DMA); + if (!dma->virt_addr) { free_dma(dma_chan); free_irq(irq_num, dev); return; } dev->irq = irq_num; - devpriv->dma = dma_chan; + dma->chan = dma_chan; devpriv->irq_dma_bits = IRQ_LVL_BITS(irq_num) | DMA_CHAN_BITS(dma_chan); disable_dma(dma_chan); @@ -723,13 +727,15 @@ static void a2150_alloc_irq_dma(struct comedi_device *dev, static void a2150_free_dma(struct comedi_device *dev) { struct a2150_private *devpriv = dev->private; + struct a2150_dma_desc *dma; if (!devpriv) return; - if (devpriv->dma) - free_dma(devpriv->dma); - kfree(devpriv->dma_buffer); + dma = &devpriv->dma_desc; + if (dma->chan) + free_dma(dma->chan); + kfree(dma->virt_addr); } /* probes board type, returns offset */ -- cgit v0.10.2 From 6d26275177e9fb086273944b3e8fc51db5aff460 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:51 -0700 Subject: staging: comedi: ni_at_a2150: remove VIRT_TO_BUS dependancy Use dma_{alloc,free}_coherent() to allocate and free the DMA buffers. This removes the dependancy on VIRT_TO_BUS. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index fe030a3..982b03f 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -462,7 +462,7 @@ config COMEDI_ADQ12B config COMEDI_NI_AT_A2150 tristate "NI AT-A2150 ISA card support" - depends on VIRT_TO_BUS && ISA_DMA_API + depends on ISA_DMA_API ---help--- Enable support for National Instruments AT-A2150 cards diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index a1300e0..3905097 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -147,7 +147,8 @@ static const struct a2150_board a2150_boards[] = { struct a2150_dma_desc { unsigned int chan; /* DMA channel */ - uint16_t *virt_addr; /* virtual address of DMA buffer */ + void *virt_addr; /* virtual address of DMA buffer */ + dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ unsigned int size; /* size of DMA transfer (in bytes) */ }; @@ -170,6 +171,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async; struct comedi_cmd *cmd; + unsigned short *buf = dma->virt_addr; unsigned int max_points, num_points, residue, leftover; unsigned short dpnt; @@ -237,7 +239,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) for (i = 0; i < num_points; i++) { /* write data point to comedi buffer */ - dpnt = dma->virt_addr[i]; + dpnt = buf[i]; /* convert from 2's complement to unsigned coding */ dpnt ^= 0x8000; comedi_buf_write_samples(s, &dpnt, 1); @@ -250,7 +252,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) } /* re-enable dma */ if (leftover) { - set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); + set_dma_addr(dma->chan, dma->hw_addr); set_dma_count(dma->chan, comedi_samples_to_bytes(s, leftover)); enable_dma(dma->chan); @@ -553,7 +555,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ clear_dma_ff(dma->chan); - set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); + set_dma_addr(dma->chan, dma->hw_addr); /* set size of transfer to fill in 1/3 second */ #define ONE_THIRD_SECOND 333333333 dma->size = comedi_bytes_per_sample(s) * cmd->chanlist_len * @@ -709,7 +711,8 @@ static void a2150_alloc_irq_dma(struct comedi_device *dev, free_irq(irq_num, dev); return; } - dma->virt_addr = kmalloc(A2150_DMA_BUFFER_SIZE, GFP_KERNEL | GFP_DMA); + dma->virt_addr = dma_alloc_coherent(NULL, A2150_DMA_BUFFER_SIZE, + &dma->hw_addr, GFP_KERNEL); if (!dma->virt_addr) { free_dma(dma_chan); free_irq(irq_num, dev); @@ -735,7 +738,9 @@ static void a2150_free_dma(struct comedi_device *dev) dma = &devpriv->dma_desc; if (dma->chan) free_dma(dma->chan); - kfree(dma->virt_addr); + if (dma->virt_addr) + dma_free_coherent(NULL, A2150_DMA_BUFFER_SIZE, + dma->virt_addr, dma->hw_addr); } /* probes board type, returns offset */ -- cgit v0.10.2 From 4d1c15c08f6620ac912d56a800a0322e64a7e3e5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:52 -0700 Subject: staging: comedi: ni_labpc: introduce struct labpc_dma_desc For aesthetics, introduce a struct to hold the DMA descriptor data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index ac2c01f..7ba7f2f 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -34,6 +34,13 @@ struct labpc_boardinfo { unsigned is_labpc1200:1; /* has extra regs compared to pc+ */ }; +struct labpc_dma_desc { + unsigned int chan; /* DMA channel */ + u16 *virt_addr; /* virtual address of DMA buffer */ + phys_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ + unsigned int size; /* size of DMA transfer (in bytes) */ +}; + struct labpc_private { /* number of data points left to be taken */ unsigned long long count; @@ -61,11 +68,9 @@ struct labpc_private { * conversions */ unsigned int divisor_b1; - unsigned int dma_chan; /* dma channel to use */ - u16 *dma_buffer; /* buffer ai will dma into */ - phys_addr_t dma_addr; - /* transfer size in bytes for current transfer */ - unsigned int dma_transfer_size; + + struct labpc_dma_desc dma_desc; + /* we are using dma/fifo-half-full/etc. */ enum transfer_type current_transfer; /* diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 6d38605..b7217a7 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -60,22 +60,23 @@ static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct labpc_private *devpriv = dev->private; + struct labpc_dma_desc *dma = &devpriv->dma_desc; struct comedi_cmd *cmd = &s->async->cmd; unsigned long irq_flags; irq_flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); + disable_dma(dma->chan); /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ - clear_dma_ff(devpriv->dma_chan); - set_dma_addr(devpriv->dma_chan, devpriv->dma_addr); + clear_dma_ff(dma->chan); + set_dma_addr(dma->chan, dma->hw_addr); /* set appropriate size of transfer */ - devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd); + dma->size = labpc_suggest_transfer_size(cmd); if (cmd->stop_src == TRIG_COUNT && - devpriv->count * sample_size < devpriv->dma_transfer_size) - devpriv->dma_transfer_size = devpriv->count * sample_size; - set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); - enable_dma(devpriv->dma_chan); + devpriv->count * sample_size < dma->size) + dma->size = devpriv->count * sample_size; + set_dma_count(dma->chan, dma->size); + enable_dma(dma->chan); release_dma_lock(irq_flags); /* set CMD3 bits for caller to enable DMA and interrupt */ devpriv->cmd3 |= (CMD3_DMAEN | CMD3_DMATCINTEN); @@ -85,6 +86,7 @@ EXPORT_SYMBOL_GPL(labpc_setup_dma); void labpc_drain_dma(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; + struct labpc_dma_desc *dma = &devpriv->dma_desc; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; @@ -95,18 +97,18 @@ void labpc_drain_dma(struct comedi_device *dev) status = devpriv->stat1; flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); + disable_dma(dma->chan); /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ - clear_dma_ff(devpriv->dma_chan); + clear_dma_ff(dma->chan); /* figure out how many points to read */ - max_points = devpriv->dma_transfer_size / sample_size; + max_points = dma->size / sample_size; /* residue is the number of points left to be done on the dma * transfer. It should always be zero at this point unless * the stop_src is set to external triggering. */ - residue = get_dma_residue(devpriv->dma_chan) / sample_size; + residue = get_dma_residue(dma->chan) / sample_size; num_points = max_points - residue; if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_points) num_points = devpriv->count; @@ -114,21 +116,21 @@ void labpc_drain_dma(struct comedi_device *dev) /* figure out how many points will be stored next time */ leftover = 0; if (cmd->stop_src != TRIG_COUNT) { - leftover = devpriv->dma_transfer_size / sample_size; + leftover = dma->size / sample_size; } else if (devpriv->count > num_points) { leftover = devpriv->count - num_points; if (leftover > max_points) leftover = max_points; } - comedi_buf_write_samples(s, devpriv->dma_buffer, num_points); + comedi_buf_write_samples(s, dma->virt_addr, num_points); if (cmd->stop_src == TRIG_COUNT) devpriv->count -= num_points; /* set address and count for next transfer */ - set_dma_addr(devpriv->dma_chan, devpriv->dma_addr); - set_dma_count(devpriv->dma_chan, leftover * sample_size); + set_dma_addr(dma->chan, dma->hw_addr); + set_dma_count(dma->chan, leftover * sample_size); release_dma_lock(flags); } EXPORT_SYMBOL_GPL(labpc_drain_dma); @@ -136,10 +138,11 @@ EXPORT_SYMBOL_GPL(labpc_drain_dma); static void handle_isa_dma(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; + struct labpc_dma_desc *dma = &devpriv->dma_desc; labpc_drain_dma(dev); - enable_dma(devpriv->dma_chan); + enable_dma(dma->chan); /* clear dma tc interrupt */ devpriv->write_byte(dev, 0x1, DMATC_CLEAR_REG); @@ -163,6 +166,7 @@ EXPORT_SYMBOL_GPL(labpc_handle_dma_status); int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) { struct labpc_private *devpriv = dev->private; + struct labpc_dma_desc *dma = &devpriv->dma_desc; void *dma_buffer; unsigned long dma_flags; int ret; @@ -180,13 +184,13 @@ int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) return ret; } - devpriv->dma_buffer = dma_buffer; - devpriv->dma_chan = dma_chan; - devpriv->dma_addr = virt_to_bus(devpriv->dma_buffer); + dma->virt_addr = dma_buffer; + dma->chan = dma_chan; + dma->hw_addr = virt_to_bus(dma->virt_addr); dma_flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); + disable_dma(dma->chan); + set_dma_mode(dma->chan, DMA_MODE_READ); release_dma_lock(dma_flags); return 0; @@ -196,13 +200,11 @@ EXPORT_SYMBOL_GPL(labpc_init_dma_chan); void labpc_free_dma_chan(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; + struct labpc_dma_desc *dma = &devpriv->dma_desc; - kfree(devpriv->dma_buffer); - devpriv->dma_buffer = NULL; - if (devpriv->dma_chan) { - free_dma(devpriv->dma_chan); - devpriv->dma_chan = 0; - } + kfree(dma->virt_addr); + if (dma->chan) + free_dma(dma->chan); } EXPORT_SYMBOL_GPL(labpc_free_dma_chan); diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h index 771af4b..2582f22 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.h +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h @@ -13,7 +13,7 @@ static inline bool labpc_have_dma_chan(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; - return (bool)devpriv->dma_chan; + return (bool)devpriv->dma_desc.chan; } int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan); -- cgit v0.10.2 From 9ff24fd577fdc6744ca328bdee59133b1094aede Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:53 -0700 Subject: staging: comedi: ni_labpc_isadma: tidy up labpc_init_dma_chan() DMA support is optional for the labpc driver. The return value from labpc_init_dma_chan() is not even checked by the caller. Change the return type to void and tidy up the function a bit. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index b7217a7..829c4e4 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -163,28 +163,24 @@ void labpc_handle_dma_status(struct comedi_device *dev) } EXPORT_SYMBOL_GPL(labpc_handle_dma_status); -int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) +void labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) { struct labpc_private *devpriv = dev->private; struct labpc_dma_desc *dma = &devpriv->dma_desc; - void *dma_buffer; unsigned long dma_flags; - int ret; if (dma_chan != 1 && dma_chan != 3) - return -EINVAL; + return; - dma_buffer = kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA); - if (!dma_buffer) - return -ENOMEM; + if (request_dma(dma_chan, dev->board_name)) + return; - ret = request_dma(dma_chan, dev->board_name); - if (ret) { - kfree(dma_buffer); - return ret; + dma->virt_addr = kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA); + if (!dma->virt_addr) { + free_dma(dma_chan); + return; } - dma->virt_addr = dma_buffer; dma->chan = dma_chan; dma->hw_addr = virt_to_bus(dma->virt_addr); @@ -192,8 +188,6 @@ int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) disable_dma(dma->chan); set_dma_mode(dma->chan, DMA_MODE_READ); release_dma_lock(dma_flags); - - return 0; } EXPORT_SYMBOL_GPL(labpc_init_dma_chan); diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h index 2582f22..8f062f7 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.h +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h @@ -16,7 +16,7 @@ static inline bool labpc_have_dma_chan(struct comedi_device *dev) return (bool)devpriv->dma_desc.chan; } -int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan); +void labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan); void labpc_free_dma_chan(struct comedi_device *dev); void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s); void labpc_drain_dma(struct comedi_device *dev); @@ -29,10 +29,9 @@ static inline bool labpc_have_dma_chan(struct comedi_device *dev) return false; } -static inline int labpc_init_dma_chan(struct comedi_device *dev, - unsigned int dma_chan) +static inline void labpc_init_dma_chan(struct comedi_device *dev, + unsigned int dma_chan) { - return -ENOTSUPP; } static inline void labpc_free_dma_chan(struct comedi_device *dev) -- cgit v0.10.2 From 05e511cf966fd1c806960679c579633b6c566129 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:54 -0700 Subject: staging: comedi: ni_labpc: remove VIRT_TO_BUS dependancy Use dma_{alloc,free}_coherent() to allocate and free the DMA buffers. This removes the dependancy on VIRT_TO_BUS. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 982b03f..76d66e0 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -502,7 +502,7 @@ config COMEDI_NI_ATMIO16D config COMEDI_NI_LABPC_ISA tristate "NI Lab-PC and compatibles ISA support" select COMEDI_NI_LABPC - select COMEDI_NI_LABPC_ISADMA if ISA_DMA_API && VIRT_TO_BUS + select COMEDI_NI_LABPC_ISADMA if ISA_DMA_API ---help--- Enable support for National Instruments Lab-PC and compatibles Lab-PC-1200, Lab-PC-1200AI, Lab-PC+. diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index 7ba7f2f..c26d7ee 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -36,8 +36,8 @@ struct labpc_boardinfo { struct labpc_dma_desc { unsigned int chan; /* DMA channel */ - u16 *virt_addr; /* virtual address of DMA buffer */ - phys_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ + void *virt_addr; /* virtual address of DMA buffer */ + dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ unsigned int size; /* size of DMA transfer (in bytes) */ }; diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 829c4e4..ecdbe11 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -175,14 +175,14 @@ void labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) if (request_dma(dma_chan, dev->board_name)) return; - dma->virt_addr = kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA); + dma->virt_addr = dma_alloc_coherent(NULL, dma_buffer_size, + &dma->hw_addr, GFP_KERNEL); if (!dma->virt_addr) { free_dma(dma_chan); return; } dma->chan = dma_chan; - dma->hw_addr = virt_to_bus(dma->virt_addr); dma_flags = claim_dma_lock(); disable_dma(dma->chan); @@ -196,7 +196,9 @@ void labpc_free_dma_chan(struct comedi_device *dev) struct labpc_private *devpriv = dev->private; struct labpc_dma_desc *dma = &devpriv->dma_desc; - kfree(dma->virt_addr); + if (dma->virt_addr) + dma_free_coherent(NULL, dma_buffer_size, + dma->virt_addr, dma->hw_addr); if (dma->chan) free_dma(dma->chan); } -- cgit v0.10.2 From 655cd94018c9b98b9aabab8960e5b3772a5bafaf Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:55 -0700 Subject: staging: comedi: pcl818: introduce pcl818_alloc_dma() DMA is optional with this driver. Introduce a helper function to request the DMA channel and allocate the buffers. Don't fail the driver attach if the user passed an invalid DMA channel or the channel cannot be requested. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 8edea35..b25ff35 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1054,13 +1054,40 @@ static void pcl818_set_ai_range_table(struct comedi_device *dev, } } +static int pcl818_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) +{ + struct pcl818_private *devpriv = dev->private; + int i; + + if (!(dma_chan == 3 || dma_chan == 1)) + return 0; + + if (request_dma(dma_chan, dev->board_name)) + return 0; + devpriv->dma = dma_chan; + + devpriv->dmapages = 2; /* we need 16KB */ + devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; + + for (i = 0; i < 2; i++) { + unsigned long dmabuf; + + dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); + if (!dmabuf) + return -ENOMEM; + + devpriv->dmabuf[i] = dmabuf; + devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); + } + return 0; +} + static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl818_board *board = dev->board_ptr; struct pcl818_private *devpriv; struct comedi_subdevice *s; int ret; - int i; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -1084,30 +1111,10 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->usefifo = 1; /* we need an IRQ to do DMA on channel 3 or 1 */ - if (dev->irq && board->has_dma && - (it->options[2] == 3 || it->options[2] == 1)) { - ret = request_dma(it->options[2], dev->board_name); - if (ret) { - dev_err(dev->class_dev, - "unable to request DMA channel %d\n", - it->options[2]); - return -EBUSY; - } - devpriv->dma = it->options[2]; - - devpriv->dmapages = 2; /* we need 16KB */ - devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; - - for (i = 0; i < 2; i++) { - unsigned long dmabuf; - - dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); - if (!dmabuf) - return -ENOMEM; - - devpriv->dmabuf[i] = dmabuf; - devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); - } + if (dev->irq && board->has_dma) { + ret = pcl818_alloc_dma(dev, it->options[2]); + if (ret) + return ret; } ret = comedi_alloc_subdevices(dev, 4); -- cgit v0.10.2 From 665ee190c99d05940ed0959717b78ef176b92e95 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:56 -0700 Subject: staging: comedi: pcl818: introduce pcl818_dma_free() For aesthetics, move the freeing of the DMA channel and the buffers to a helper function. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index b25ff35..beb03ec 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1082,6 +1082,22 @@ static int pcl818_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) return 0; } +static void pcl818_free_dma(struct comedi_device *dev) +{ + struct pcl818_private *devpriv = dev->private; + int i; + + if (!devpriv) + return; + + if (devpriv->dma) + free_dma(devpriv->dma); + for (i = 0; i < 2; i++) { + if (devpriv->dmabuf[i]) + free_pages(devpriv->dmabuf[i], devpriv->dmapages); + } +} + static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl818_board *board = dev->board_ptr; @@ -1217,13 +1233,8 @@ static void pcl818_detach(struct comedi_device *dev) if (devpriv) { pcl818_ai_cancel(dev, dev->read_subdev); pcl818_reset(dev); - if (devpriv->dma) - free_dma(devpriv->dma); - if (devpriv->dmabuf[0]) - free_pages(devpriv->dmabuf[0], devpriv->dmapages); - if (devpriv->dmabuf[1]) - free_pages(devpriv->dmabuf[1], devpriv->dmapages); } + pcl818_free_dma(dev); comedi_legacy_detach(dev); } -- cgit v0.10.2 From b8e7048bab32b6571dd4930f9a94622556a01ad4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:57 -0700 Subject: staging: comedi: pcl818: introduce struct pcl818_dma_desc For aesthetics, introduce a struct to hold the DMA descriptor data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index beb03ec..f34c5cc 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -302,13 +302,17 @@ static const struct pcl818_board boardtypes[] = { }, }; +struct pcl818_dma_desc { + unsigned long dmabuf; /* pointers to begin of DMA buffers */ + unsigned int hwdmaptr; /* hardware address of DMA buffers */ +}; + struct pcl818_private { unsigned int dma; /* used DMA, 0=don't use DMA */ unsigned int dmapages; unsigned int hwdmasize; - unsigned long dmabuf[2]; /* pointers to begin of DMA buffers */ - unsigned int hwdmaptr[2]; /* hardware address of DMA buffers */ - int next_dma_buf; /* which DMA buffer will be used next round */ + struct pcl818_dma_desc dma_desc[2]; + int cur_dma; long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */ unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */ unsigned int ns_min; /* manimal allowed delay between samples (in us) for actual card */ @@ -343,6 +347,7 @@ static void pcl818_ai_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl818_private *devpriv = dev->private; + struct pcl818_dma_desc *dma = &devpriv->dma_desc[0]; struct comedi_cmd *cmd = &s->async->cmd; unsigned int flags; unsigned int bytes; @@ -358,11 +363,11 @@ static void pcl818_ai_setup_dma(struct comedi_device *dev, bytes = devpriv->hwdmasize; } - devpriv->next_dma_buf = 0; + devpriv->cur_dma = 0; set_dma_mode(devpriv->dma, DMA_MODE_READ); flags = claim_dma_lock(); clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); + set_dma_addr(devpriv->dma, dma->hwdmaptr); set_dma_count(devpriv->dma, bytes); release_dma_lock(flags); enable_dma(devpriv->dma); @@ -373,16 +378,17 @@ static void pcl818_ai_setup_next_dma(struct comedi_device *dev, { struct pcl818_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; + struct pcl818_dma_desc *dma; unsigned long flags; disable_dma(devpriv->dma); - devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; + devpriv->cur_dma = 1 - devpriv->cur_dma; if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { /* switch dma bufs */ + dma = &devpriv->dma_desc[devpriv->cur_dma]; set_dma_mode(devpriv->dma, DMA_MODE_READ); flags = claim_dma_lock(); - set_dma_addr(devpriv->dma, - devpriv->hwdmaptr[devpriv->next_dma_buf]); + set_dma_addr(devpriv->dma, dma->hwdmaptr); if (devpriv->dma_runs_to_end || cmd->stop_src == TRIG_NONE) set_dma_count(devpriv->dma, devpriv->hwdmasize); else @@ -558,15 +564,14 @@ static void pcl818_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl818_private *devpriv = dev->private; - unsigned short *ptr; + struct pcl818_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; + unsigned short *ptr = (unsigned short *)dma->dmabuf; unsigned int chan; unsigned int val; int i, len, bufptr; pcl818_ai_setup_next_dma(dev, s); - ptr = (unsigned short *)devpriv->dmabuf[1 - devpriv->next_dma_buf]; - len = devpriv->hwdmasize >> 1; bufptr = 0; @@ -1057,6 +1062,7 @@ static void pcl818_set_ai_range_table(struct comedi_device *dev, static int pcl818_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) { struct pcl818_private *devpriv = dev->private; + struct pcl818_dma_desc *dma; int i; if (!(dma_chan == 3 || dma_chan == 1)) @@ -1070,14 +1076,12 @@ static int pcl818_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; for (i = 0; i < 2; i++) { - unsigned long dmabuf; + dma = &devpriv->dma_desc[i]; - dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); - if (!dmabuf) + dma->dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); + if (!dma->dmabuf) return -ENOMEM; - - devpriv->dmabuf[i] = dmabuf; - devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); + dma->hwdmaptr = virt_to_bus((void *)dma->dmabuf); } return 0; } @@ -1085,6 +1089,7 @@ static int pcl818_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) static void pcl818_free_dma(struct comedi_device *dev) { struct pcl818_private *devpriv = dev->private; + struct pcl818_dma_desc *dma; int i; if (!devpriv) @@ -1093,8 +1098,9 @@ static void pcl818_free_dma(struct comedi_device *dev) if (devpriv->dma) free_dma(devpriv->dma); for (i = 0; i < 2; i++) { - if (devpriv->dmabuf[i]) - free_pages(devpriv->dmabuf[i], devpriv->dmapages); + dma = &devpriv->dma_desc[i]; + if (dma->dmabuf) + free_pages(dma->dmabuf, devpriv->dmapages); } } -- cgit v0.10.2 From 7a37b7a7556fe6b4108ad7cea25a484b87d11ee9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:58 -0700 Subject: staging: comedi: pcl818: remove VIRT_TO_BUS dependancy Use dma_{alloc,free}_coherent() to allocate and free the DMA buffers. This removes the dependancy on VIRT_TO_BUS. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 76d66e0..c48ee22 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -188,7 +188,7 @@ config COMEDI_PCL816 config COMEDI_PCL818 tristate "Advantech PCL-718 and PCL-818 ISA card support" - depends on VIRT_TO_BUS && ISA_DMA_API + depends on ISA_DMA_API ---help--- Enable support for Advantech PCL-818 ISA cards PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818 and PCL-718 diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index f34c5cc..3656ecf 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -303,13 +303,12 @@ static const struct pcl818_board boardtypes[] = { }; struct pcl818_dma_desc { - unsigned long dmabuf; /* pointers to begin of DMA buffers */ - unsigned int hwdmaptr; /* hardware address of DMA buffers */ + void *virt_addr; /* virtual address of DMA buffer */ + dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ }; struct pcl818_private { unsigned int dma; /* used DMA, 0=don't use DMA */ - unsigned int dmapages; unsigned int hwdmasize; struct pcl818_dma_desc dma_desc[2]; int cur_dma; @@ -367,7 +366,7 @@ static void pcl818_ai_setup_dma(struct comedi_device *dev, set_dma_mode(devpriv->dma, DMA_MODE_READ); flags = claim_dma_lock(); clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, dma->hwdmaptr); + set_dma_addr(devpriv->dma, dma->hw_addr); set_dma_count(devpriv->dma, bytes); release_dma_lock(flags); enable_dma(devpriv->dma); @@ -388,7 +387,7 @@ static void pcl818_ai_setup_next_dma(struct comedi_device *dev, dma = &devpriv->dma_desc[devpriv->cur_dma]; set_dma_mode(devpriv->dma, DMA_MODE_READ); flags = claim_dma_lock(); - set_dma_addr(devpriv->dma, dma->hwdmaptr); + set_dma_addr(devpriv->dma, dma->hw_addr); if (devpriv->dma_runs_to_end || cmd->stop_src == TRIG_NONE) set_dma_count(devpriv->dma, devpriv->hwdmasize); else @@ -565,7 +564,7 @@ static void pcl818_handle_dma(struct comedi_device *dev, { struct pcl818_private *devpriv = dev->private; struct pcl818_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; - unsigned short *ptr = (unsigned short *)dma->dmabuf; + unsigned short *ptr = dma->virt_addr; unsigned int chan; unsigned int val; int i, len, bufptr; @@ -1072,16 +1071,15 @@ static int pcl818_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) return 0; devpriv->dma = dma_chan; - devpriv->dmapages = 2; /* we need 16KB */ - devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; + devpriv->hwdmasize = PAGE_SIZE * 4; /* we need 16KB */ for (i = 0; i < 2; i++) { dma = &devpriv->dma_desc[i]; - dma->dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); - if (!dma->dmabuf) + dma->virt_addr = dma_alloc_coherent(NULL, devpriv->hwdmasize, + &dma->hw_addr, GFP_KERNEL); + if (!dma->virt_addr) return -ENOMEM; - dma->hwdmaptr = virt_to_bus((void *)dma->dmabuf); } return 0; } @@ -1099,8 +1097,9 @@ static void pcl818_free_dma(struct comedi_device *dev) free_dma(devpriv->dma); for (i = 0; i < 2; i++) { dma = &devpriv->dma_desc[i]; - if (dma->dmabuf) - free_pages(dma->dmabuf, devpriv->dmapages); + if (dma->virt_addr) + dma_free_coherent(NULL, devpriv->hwdmasize, + dma->virt_addr, dma->hw_addr); } } -- cgit v0.10.2 From 1c53093a1dea755f5ab9598d57b78f9a9444262d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:55:59 -0700 Subject: staging: comedi: pcl818: fix pcl818_handle_dma() for short DMA transaction Currently this function always transfers the full DMA buffer to the comedi async buffer. When the cmd->stop_src == TRIG_COUNT the last DMA transfer might be smaller than the buffer size. This results in invalid data being added to the asunc buffer. Add a 'size' member to the DMA descriptor and initialize it with the actual size of the DMA transfer. Use that in pcl818_handle_dma() to return the proper number of samples. Use the comedi_bytes_to_samples() helper to convert the byte size to comedi samples. Remove the unnecessary 'bufptr' local variable. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 3656ecf..19f6b59 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -305,6 +305,7 @@ static const struct pcl818_board boardtypes[] = { struct pcl818_dma_desc { void *virt_addr; /* virtual address of DMA buffer */ dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ + unsigned int size; /* transfer size (in bytes) */ }; struct pcl818_private { @@ -349,17 +350,17 @@ static void pcl818_ai_setup_dma(struct comedi_device *dev, struct pcl818_dma_desc *dma = &devpriv->dma_desc[0]; struct comedi_cmd *cmd = &s->async->cmd; unsigned int flags; - unsigned int bytes; disable_dma(devpriv->dma); /* disable dma */ - bytes = devpriv->hwdmasize; if (cmd->stop_src == TRIG_COUNT) { - bytes = cmd->stop_arg * comedi_bytes_per_scan(s); - devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize; - devpriv->last_dma_run = bytes % devpriv->hwdmasize; + dma->size = cmd->stop_arg * comedi_bytes_per_scan(s); + devpriv->dma_runs_to_end = dma->size / devpriv->hwdmasize; + devpriv->last_dma_run = dma->size % devpriv->hwdmasize; devpriv->dma_runs_to_end--; if (devpriv->dma_runs_to_end >= 0) - bytes = devpriv->hwdmasize; + dma->size = devpriv->hwdmasize; + } else { + dma->size = devpriv->hwdmasize; } devpriv->cur_dma = 0; @@ -367,7 +368,7 @@ static void pcl818_ai_setup_dma(struct comedi_device *dev, flags = claim_dma_lock(); clear_dma_ff(devpriv->dma); set_dma_addr(devpriv->dma, dma->hw_addr); - set_dma_count(devpriv->dma, bytes); + set_dma_count(devpriv->dma, dma->size); release_dma_lock(flags); enable_dma(devpriv->dma); } @@ -385,13 +386,14 @@ static void pcl818_ai_setup_next_dma(struct comedi_device *dev, if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { /* switch dma bufs */ dma = &devpriv->dma_desc[devpriv->cur_dma]; + if (devpriv->dma_runs_to_end || cmd->stop_src == TRIG_NONE) + dma->size = devpriv->hwdmasize; + else + dma->size = devpriv->last_dma_run; set_dma_mode(devpriv->dma, DMA_MODE_READ); flags = claim_dma_lock(); set_dma_addr(devpriv->dma, dma->hw_addr); - if (devpriv->dma_runs_to_end || cmd->stop_src == TRIG_NONE) - set_dma_count(devpriv->dma, devpriv->hwdmasize); - else - set_dma_count(devpriv->dma, devpriv->last_dma_run); + set_dma_count(devpriv->dma, dma->size); release_dma_lock(flags); enable_dma(devpriv->dma); } @@ -565,17 +567,15 @@ static void pcl818_handle_dma(struct comedi_device *dev, struct pcl818_private *devpriv = dev->private; struct pcl818_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; unsigned short *ptr = dma->virt_addr; + unsigned int nsamples = comedi_bytes_to_samples(s, dma->size); unsigned int chan; unsigned int val; - int i, len, bufptr; + int i; pcl818_ai_setup_next_dma(dev, s); - len = devpriv->hwdmasize >> 1; - bufptr = 0; - - for (i = 0; i < len; i++) { - val = ptr[bufptr++]; + for (i = 0; i < nsamples; i++) { + val = ptr[i]; chan = val & 0xf; val = (val >> 4) & s->maxdata; -- cgit v0.10.2 From 1fa51639e551bee7de73122b8bbafd509eae52fa Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:00 -0700 Subject: staging: comedi: pcl816: introduce pcl816_alloc_dma() The IRA and DMA are optional with this driver but both are required to support async commands. Introduce a helper function to request the IRQ and DMA channel and allocate the buffers. Don't fail the driver attach if the user passed an invalid IRQ or DMA channel or they cannot be requested. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 73deb4b..0374f83 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -657,13 +657,59 @@ static void pcl816_reset(struct comedi_device *dev) outb(0, dev->iobase + PCL816_DO_DI_MSB_REG); } +static int pcl816_alloc_dma(struct comedi_device *dev, + unsigned int irq_num, unsigned int dma_chan) +{ + struct pcl816_private *devpriv = dev->private; + int i; + + /* + * Only IRQs 2-7 are valid. + * Only DMA channels 3 and 1 are valid. + * + * Both must be valid for async command support. + */ + if (!(irq_num >= 2 && irq_num <= 7) || + !(dma_chan == 3 || dma_chan == 1)) + return 0; + + /* + * Request the IRQ and DMA channels and allocate the DMA buffers. + * If the requests or allocations fail async command supprt will + * not be available. + */ + if (request_irq(irq_num, pcl816_interrupt, 0, dev->board_name, dev)) + return 0; + if (request_dma(dma_chan, dev->board_name)) { + free_irq(irq_num, dev); + return 0; + } + + dev->irq = irq_num; + devpriv->dma = dma_chan; + + devpriv->dmapages = 2; /* we need 16KB */ + devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; + + for (i = 0; i < 2; i++) { + unsigned long dmabuf; + + dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); + if (!dmabuf) + return -ENOMEM; + + devpriv->dmabuf[i] = dmabuf; + devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); + } + return 0; +} + static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl816_board *board = dev->board_ptr; struct pcl816_private *devpriv; struct comedi_subdevice *s; int ret; - int i; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -673,39 +719,14 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - /* we can use IRQ 2-7 for async command support */ - if (it->options[1] >= 2 && it->options[1] <= 7) { - ret = request_irq(it->options[1], pcl816_interrupt, 0, - dev->board_name, dev); - if (ret == 0) - dev->irq = it->options[1]; - } - - /* we need an IRQ to do DMA on channel 3 or 1 */ - if (dev->irq && (it->options[2] == 3 || it->options[2] == 1)) { - ret = request_dma(it->options[2], dev->board_name); - if (ret) { - dev_err(dev->class_dev, - "unable to request DMA channel %d\n", - it->options[2]); - return -EBUSY; - } - devpriv->dma = it->options[2]; - - devpriv->dmapages = 2; /* we need 16KB */ - devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; - - for (i = 0; i < 2; i++) { - unsigned long dmabuf; - - dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); - if (!dmabuf) - return -ENOMEM; - - devpriv->dmabuf[i] = dmabuf; - devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); - } - } + /* + * An IRQ and DMA are required to support async commands. + * pcl816_alloc_dma() will only fail if the DMA buffers + * cannot be allocated. + */ + ret = pcl816_alloc_dma(dev, it->options[1], it->options[2]); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 4); if (ret) @@ -718,7 +739,7 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->maxdata = board->ai_maxdata; s->range_table = &range_pcl816; s->insn_read = pcl816_ai_insn_read; - if (devpriv->dma) { + if (dev->irq) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; s->len_chanlist = board->ai_chanlist; -- cgit v0.10.2 From d7b8bbb6a7c22fd3b830161febfaa89f1d820f09 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:01 -0700 Subject: staging: comedi: pcl816: introduce pcl816_free_dma() For aesthetics, move the freeing of the DMA channel and the buffers to a helper function. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 0374f83..4cff02a 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -704,6 +704,22 @@ static int pcl816_alloc_dma(struct comedi_device *dev, return 0; } +static void pcl816_free_dma(struct comedi_device *dev) +{ + struct pcl816_private *devpriv = dev->private; + int i; + + if (!devpriv) + return; + + if (devpriv->dma) + free_dma(devpriv->dma); + for (i = 0; i < 2; i++) { + if (devpriv->dmabuf[i]) + free_pages(devpriv->dmabuf[i], devpriv->dmapages); + } +} + static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl816_board *board = dev->board_ptr; @@ -785,18 +801,11 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcl816_detach(struct comedi_device *dev) { - struct pcl816_private *devpriv = dev->private; - if (dev->private) { pcl816_ai_cancel(dev, dev->read_subdev); pcl816_reset(dev); - if (devpriv->dma) - free_dma(devpriv->dma); - if (devpriv->dmabuf[0]) - free_pages(devpriv->dmabuf[0], devpriv->dmapages); - if (devpriv->dmabuf[1]) - free_pages(devpriv->dmabuf[1], devpriv->dmapages); } + pcl816_free_dma(dev); comedi_legacy_detach(dev); } -- cgit v0.10.2 From 16d87782c560fac81627ddc9368b4f7100a1c2f7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:02 -0700 Subject: staging: comedi: pcl816: introduce struct pcl816_dma_desc For aesthetics, introduce a struct to hold the DMA descriptor data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 4cff02a..49c1f17 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -113,13 +113,17 @@ static const struct pcl816_board boardtypes[] = { }, }; +struct pcl816_dma_desc { + unsigned long virt_addr; /* virtual address of DMA buffer */ + unsigned int hw_addr; /* hardware (bus) address of DMA buffer */ +}; + struct pcl816_private { unsigned int dma; /* used DMA, 0=don't use DMA */ unsigned int dmapages; unsigned int hwdmasize; - unsigned long dmabuf[2]; /* pointers to begin of DMA buffers */ - unsigned int hwdmaptr[2]; /* hardware address of DMA buffers */ - int next_dma_buf; /* which DMA buffer will be used next round */ + struct pcl816_dma_desc dma_desc[2]; + int cur_dma; long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */ unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */ unsigned int ai_poll_ptr; /* how many sampes transfer poll */ @@ -152,6 +156,7 @@ static void pcl816_ai_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl816_private *devpriv = dev->private; + struct pcl816_dma_desc *dma = &devpriv->dma_desc[0]; struct comedi_cmd *cmd = &s->async->cmd; unsigned int dma_flags; unsigned int bytes; @@ -172,11 +177,11 @@ static void pcl816_ai_setup_dma(struct comedi_device *dev, } else devpriv->dma_runs_to_end = -1; - devpriv->next_dma_buf = 0; + devpriv->cur_dma = 0; set_dma_mode(devpriv->dma, DMA_MODE_READ); dma_flags = claim_dma_lock(); clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); + set_dma_addr(devpriv->dma, dma->hw_addr); set_dma_count(devpriv->dma, bytes); release_dma_lock(dma_flags); enable_dma(devpriv->dma); @@ -187,16 +192,17 @@ static void pcl816_ai_setup_next_dma(struct comedi_device *dev, { struct pcl816_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; + struct pcl816_dma_desc *dma; unsigned long dma_flags; disable_dma(devpriv->dma); if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { /* switch dma bufs */ - devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; + devpriv->cur_dma = 1 - devpriv->cur_dma; + dma = &devpriv->dma_desc[devpriv->cur_dma]; set_dma_mode(devpriv->dma, DMA_MODE_READ); dma_flags = claim_dma_lock(); - set_dma_addr(devpriv->dma, - devpriv->hwdmaptr[devpriv->next_dma_buf]); + set_dma_addr(devpriv->dma, dma->hw_addr); if (devpriv->dma_runs_to_end) set_dma_count(devpriv->dma, devpriv->hwdmasize); else @@ -318,7 +324,7 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) struct comedi_device *dev = d; struct comedi_subdevice *s = dev->read_subdev; struct pcl816_private *devpriv = dev->private; - unsigned short *ptr; + struct pcl816_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; unsigned int bufptr; unsigned int len; @@ -333,15 +339,14 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) return IRQ_HANDLED; } - ptr = (unsigned short *)devpriv->dmabuf[devpriv->next_dma_buf]; - pcl816_ai_setup_next_dma(dev, s); len = (devpriv->hwdmasize >> 1) - devpriv->ai_poll_ptr; bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; - transfer_from_dma_buf(dev, s, ptr, bufptr, len); + transfer_from_dma_buf(dev, s, (unsigned short *)dma->virt_addr, + bufptr, len); pcl816_ai_clear_eoc(dev); @@ -521,6 +526,7 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl816_private *devpriv = dev->private; + struct pcl816_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; unsigned long flags; unsigned int top1, top2, i; @@ -546,9 +552,7 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } - transfer_from_dma_buf(dev, s, - (unsigned short *)devpriv->dmabuf[devpriv-> - next_dma_buf], + transfer_from_dma_buf(dev, s, (unsigned short *)dma->virt_addr, devpriv->ai_poll_ptr, top2); devpriv->ai_poll_ptr = top1; /* new buffer position */ @@ -661,6 +665,7 @@ static int pcl816_alloc_dma(struct comedi_device *dev, unsigned int irq_num, unsigned int dma_chan) { struct pcl816_private *devpriv = dev->private; + struct pcl816_dma_desc *dma; int i; /* @@ -692,14 +697,12 @@ static int pcl816_alloc_dma(struct comedi_device *dev, devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; for (i = 0; i < 2; i++) { - unsigned long dmabuf; + dma = &devpriv->dma_desc[i]; - dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); - if (!dmabuf) + dma->virt_addr = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); + if (!dma->virt_addr) return -ENOMEM; - - devpriv->dmabuf[i] = dmabuf; - devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); + dma->hw_addr = virt_to_bus((void *)dma->virt_addr); } return 0; } @@ -707,6 +710,7 @@ static int pcl816_alloc_dma(struct comedi_device *dev, static void pcl816_free_dma(struct comedi_device *dev) { struct pcl816_private *devpriv = dev->private; + struct pcl816_dma_desc *dma; int i; if (!devpriv) @@ -715,8 +719,9 @@ static void pcl816_free_dma(struct comedi_device *dev) if (devpriv->dma) free_dma(devpriv->dma); for (i = 0; i < 2; i++) { - if (devpriv->dmabuf[i]) - free_pages(devpriv->dmabuf[i], devpriv->dmapages); + dma = &devpriv->dma_desc[i]; + if (dma->virt_addr) + free_pages(dma->virt_addr, devpriv->dmapages); } } -- cgit v0.10.2 From a2c3966d18a93540f49c2c8cc3dda5ce6c9399a7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:03 -0700 Subject: staging: comedi: pcl816: remove VIRT_TO_BUS dependancy Use dma_{alloc,free}_coherent() to allocate and free the DMA buffers. This removes the dependancy on VIRT_TO_BUS. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index c48ee22..59c17e6 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -179,7 +179,7 @@ config COMEDI_PCL812 config COMEDI_PCL816 tristate "Advantech PCL-814 and PCL-816 ISA card support" - depends on VIRT_TO_BUS && ISA_DMA_API + depends on ISA_DMA_API ---help--- Enable support for Advantech PCL-814 and PCL-816 ISA cards diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 49c1f17..1b76085 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -114,13 +114,12 @@ static const struct pcl816_board boardtypes[] = { }; struct pcl816_dma_desc { - unsigned long virt_addr; /* virtual address of DMA buffer */ - unsigned int hw_addr; /* hardware (bus) address of DMA buffer */ + void *virt_addr; /* virtual address of DMA buffer */ + dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ }; struct pcl816_private { unsigned int dma; /* used DMA, 0=don't use DMA */ - unsigned int dmapages; unsigned int hwdmasize; struct pcl816_dma_desc dma_desc[2]; int cur_dma; @@ -345,8 +344,7 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; - transfer_from_dma_buf(dev, s, (unsigned short *)dma->virt_addr, - bufptr, len); + transfer_from_dma_buf(dev, s, dma->virt_addr, bufptr, len); pcl816_ai_clear_eoc(dev); @@ -552,7 +550,7 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } - transfer_from_dma_buf(dev, s, (unsigned short *)dma->virt_addr, + transfer_from_dma_buf(dev, s, dma->virt_addr, devpriv->ai_poll_ptr, top2); devpriv->ai_poll_ptr = top1; /* new buffer position */ @@ -693,16 +691,15 @@ static int pcl816_alloc_dma(struct comedi_device *dev, dev->irq = irq_num; devpriv->dma = dma_chan; - devpriv->dmapages = 2; /* we need 16KB */ - devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; + devpriv->hwdmasize = PAGE_SIZE * 4; /* we need 16KB */ for (i = 0; i < 2; i++) { dma = &devpriv->dma_desc[i]; - dma->virt_addr = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); + dma->virt_addr = dma_alloc_coherent(NULL, devpriv->hwdmasize, + &dma->hw_addr, GFP_KERNEL); if (!dma->virt_addr) return -ENOMEM; - dma->hw_addr = virt_to_bus((void *)dma->virt_addr); } return 0; } @@ -721,7 +718,8 @@ static void pcl816_free_dma(struct comedi_device *dev) for (i = 0; i < 2; i++) { dma = &devpriv->dma_desc[i]; if (dma->virt_addr) - free_pages(dma->virt_addr, devpriv->dmapages); + dma_free_coherent(NULL, devpriv->hwdmasize, + dma->virt_addr, dma->hw_addr); } } -- cgit v0.10.2 From ceb41be712b68fac4ac834120a80fc3cb8e5ac37 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:04 -0700 Subject: staging: comedi: pcl816: fix short DMA transactions When the cmd->stop_src == TRIG_COUNT the last DMA transfer might be smaller than the buffer size. This results in invalid data being added to the async buffer. Add a 'size' member to the DMA descriptor and initialize it with the actual size of the DMA transfer. Use that in interrupt and ai subdevice (*poll) function to return the proper number of samples. Use the comedi_bytes_to_samples() helper to convert the byte size to comedi samples in the interrupt handler. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 1b76085..f880cb9 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -116,6 +116,7 @@ static const struct pcl816_board boardtypes[] = { struct pcl816_dma_desc { void *virt_addr; /* virtual address of DMA buffer */ dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ + unsigned int size; /* transfer size (in bytes) */ }; struct pcl816_private { @@ -158,30 +159,30 @@ static void pcl816_ai_setup_dma(struct comedi_device *dev, struct pcl816_dma_desc *dma = &devpriv->dma_desc[0]; struct comedi_cmd *cmd = &s->async->cmd; unsigned int dma_flags; - unsigned int bytes; - bytes = devpriv->hwdmasize; if (cmd->stop_src == TRIG_COUNT) { /* how many */ - bytes = cmd->stop_arg * comedi_bytes_per_scan(s); + dma->size = cmd->stop_arg * comedi_bytes_per_scan(s); /* how many DMA pages we must fill */ - devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize; + devpriv->dma_runs_to_end = dma->size / devpriv->hwdmasize; /* on last dma transfer must be moved */ - devpriv->last_dma_run = bytes % devpriv->hwdmasize; + devpriv->last_dma_run = dma->size % devpriv->hwdmasize; devpriv->dma_runs_to_end--; if (devpriv->dma_runs_to_end >= 0) - bytes = devpriv->hwdmasize; - } else + dma->size = devpriv->hwdmasize; + } else { + dma->size = devpriv->hwdmasize; devpriv->dma_runs_to_end = -1; + } devpriv->cur_dma = 0; set_dma_mode(devpriv->dma, DMA_MODE_READ); dma_flags = claim_dma_lock(); clear_dma_ff(devpriv->dma); set_dma_addr(devpriv->dma, dma->hw_addr); - set_dma_count(devpriv->dma, bytes); + set_dma_count(devpriv->dma, dma->size); release_dma_lock(dma_flags); enable_dma(devpriv->dma); } @@ -199,13 +200,14 @@ static void pcl816_ai_setup_next_dma(struct comedi_device *dev, /* switch dma bufs */ devpriv->cur_dma = 1 - devpriv->cur_dma; dma = &devpriv->dma_desc[devpriv->cur_dma]; + if (devpriv->dma_runs_to_end) + dma->size = devpriv->hwdmasize; + else + dma->size = devpriv->last_dma_run; set_dma_mode(devpriv->dma, DMA_MODE_READ); dma_flags = claim_dma_lock(); set_dma_addr(devpriv->dma, dma->hw_addr); - if (devpriv->dma_runs_to_end) - set_dma_count(devpriv->dma, devpriv->hwdmasize); - else - set_dma_count(devpriv->dma, devpriv->last_dma_run); + set_dma_count(devpriv->dma, dma->size); release_dma_lock(dma_flags); enable_dma(devpriv->dma); } @@ -324,8 +326,8 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) struct comedi_subdevice *s = dev->read_subdev; struct pcl816_private *devpriv = dev->private; struct pcl816_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; + unsigned int nsamples; unsigned int bufptr; - unsigned int len; if (!dev->attached || !devpriv->ai_cmd_running) { pcl816_ai_clear_eoc(dev); @@ -340,11 +342,11 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) pcl816_ai_setup_next_dma(dev, s); - len = (devpriv->hwdmasize >> 1) - devpriv->ai_poll_ptr; + nsamples = comedi_bytes_to_samples(s, dma->size) - devpriv->ai_poll_ptr; bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; - transfer_from_dma_buf(dev, s, dma->virt_addr, bufptr, len); + transfer_from_dma_buf(dev, s, dma->virt_addr, bufptr, nsamples); pcl816_ai_clear_eoc(dev); @@ -542,7 +544,7 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) } /* where is now DMA in buffer */ - top1 = devpriv->hwdmasize - top1; + top1 = dma->size - top1; top1 >>= 1; /* sample position */ top2 = top1 - devpriv->ai_poll_ptr; if (top2 < 1) { /* no new samples */ -- cgit v0.10.2 From 075400af763d1a16bbbaa7e5963b9ede9765e2ad Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:05 -0700 Subject: staging: comedi: pcl812: introduce pcl812_alloc_dma() DMA is optional with this driver. Introduce a helper function to request the DMA channel and allocate the buffers. Don't fail the driver attach if the user passed an invalid DMA channel or the channel cannot be requested. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index ac243ca..38cf14e 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1192,6 +1192,34 @@ static void pcl812_set_ai_range_table(struct comedi_device *dev, } } +static int pcl812_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) +{ + struct pcl812_private *devpriv = dev->private; + int i; + + if (!(dma_chan == 3 || dma_chan == 1)) + return 0; + + if (request_dma(dma_chan, dev->board_name)) + return 0; + devpriv->dma = dma_chan; + + devpriv->dmapages = 1; /* we want 8KB */ + devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; + + for (i = 0; i < 2; i++) { + unsigned long dmabuf; + + dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); + if (!dmabuf) + return -ENOMEM; + + devpriv->dmabuf[i] = dmabuf; + devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); + } + return 0; +} + static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl812_board *board = dev->board_ptr; @@ -1200,7 +1228,6 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) int n_subdevices; int subdev; int ret; - int i; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -1218,30 +1245,10 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* we need an IRQ to do DMA on channel 3 or 1 */ - if (dev->irq && board->has_dma && - (it->options[2] == 3 || it->options[2] == 1)) { - ret = request_dma(it->options[2], dev->board_name); - if (ret) { - dev_err(dev->class_dev, - "unable to request DMA channel %d\n", - it->options[2]); - return -EBUSY; - } - devpriv->dma = it->options[2]; - - devpriv->dmapages = 1; /* we want 8KB */ - devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; - - for (i = 0; i < 2; i++) { - unsigned long dmabuf; - - dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); - if (!dmabuf) - return -ENOMEM; - - devpriv->dmabuf[i] = dmabuf; - devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); - } + if (dev->irq && board->has_dma) { + ret = pcl812_alloc_dma(dev, it->options[2]); + if (ret) + return ret; } /* differential analog inputs? */ -- cgit v0.10.2 From 91ac6981bc09784122585d1ccf1267efcbc5934d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:06 -0700 Subject: staging: comedi: pcl812: introduce pcl812_free_dma() For aesthetics, move the freeing of the DMA channel and the buffers to a helper function. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 38cf14e..b628f06 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1220,6 +1220,22 @@ static int pcl812_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) return 0; } +static void pcl812_free_dma(struct comedi_device *dev) +{ + struct pcl812_private *devpriv = dev->private; + int i; + + if (!devpriv) + return; + + for (i = 0; i < 2; i++) { + if (devpriv->dmabuf[i]) + free_pages(devpriv->dmabuf[i], devpriv->dmapages); + } + if (devpriv->dma) + free_dma(devpriv->dma); +} + static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct pcl812_board *board = dev->board_ptr; @@ -1391,16 +1407,7 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void pcl812_detach(struct comedi_device *dev) { - struct pcl812_private *devpriv = dev->private; - - if (devpriv) { - if (devpriv->dmabuf[0]) - free_pages(devpriv->dmabuf[0], devpriv->dmapages); - if (devpriv->dmabuf[1]) - free_pages(devpriv->dmabuf[1], devpriv->dmapages); - if (devpriv->dma) - free_dma(devpriv->dma); - } + pcl812_free_dma(dev); comedi_legacy_detach(dev); } -- cgit v0.10.2 From d8332a68976fc58ef79284548636f86b3f1c124e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:07 -0700 Subject: staging: comedi: pcl812: introduce struct pcl812_dma_desc For aesthetics, introduce a struct to hold the DMA descriptor data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index b628f06..d9f94c9 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -506,6 +506,12 @@ static const struct pcl812_board boardtypes[] = { }, }; +struct pcl812_dma_desc { + unsigned long virt_addr; /* virtual address of DMA buffer */ + unsigned int hw_addr; /* hardware (bus) address of DMA buffer */ + unsigned int size; /* transfer size (in bytes) */ +}; + struct pcl812_private { unsigned char dma; /* >0 use dma ( usedDMA channel) */ unsigned char range_correction; /* =1 we must add 1 to range number */ @@ -514,10 +520,8 @@ struct pcl812_private { unsigned int ai_poll_ptr; /* how many sampes transfer poll */ unsigned int dmapages; unsigned int hwdmasize; - unsigned long dmabuf[2]; /* PTR to DMA buf */ - unsigned int hwdmaptr[2]; /* HW PTR to DMA buf */ - unsigned int dmabytestomove[2]; /* how many bytes DMA transfer */ - int next_dma_buf; /* which buffer is next to use */ + struct pcl812_dma_desc dma_desc[2]; + int cur_dma; unsigned int dma_runs_to_end; /* how many times we must switch DMA buffers */ unsigned int last_dma_run; /* how many bytes to transfer on last DMA buffer */ unsigned int max_812_ai_mode0_rangewait; /* setling time for gain */ @@ -549,23 +553,23 @@ static void pcl812_ai_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; + struct pcl812_dma_desc *dma0 = &devpriv->dma_desc[0]; + struct pcl812_dma_desc *dma1 = &devpriv->dma_desc[1]; struct comedi_cmd *cmd = &s->async->cmd; unsigned int dma_flags; unsigned int bytes; /* we use EOS, so adapt DMA buffer to one scan */ if (devpriv->ai_eos) { - devpriv->dmabytestomove[0] = comedi_bytes_per_scan(s); - devpriv->dmabytestomove[1] = comedi_bytes_per_scan(s); + dma0->size = comedi_bytes_per_scan(s); + dma1->size = comedi_bytes_per_scan(s); devpriv->dma_runs_to_end = 1; } else { - devpriv->dmabytestomove[0] = devpriv->hwdmasize; - devpriv->dmabytestomove[1] = devpriv->hwdmasize; + dma0->size = devpriv->hwdmasize; + dma1->size = devpriv->hwdmasize; if (s->async->prealloc_bufsz < devpriv->hwdmasize) { - devpriv->dmabytestomove[0] = - s->async->prealloc_bufsz; - devpriv->dmabytestomove[1] = - s->async->prealloc_bufsz; + dma0->size = s->async->prealloc_bufsz; + dma1->size = s->async->prealloc_bufsz; } if (cmd->stop_src == TRIG_NONE) { devpriv->dma_runs_to_end = 1; @@ -574,32 +578,29 @@ static void pcl812_ai_setup_dma(struct comedi_device *dev, bytes = cmd->stop_arg * comedi_bytes_per_scan(s); /* how many DMA pages we must fill */ - devpriv->dma_runs_to_end = - bytes / devpriv->dmabytestomove[0]; + devpriv->dma_runs_to_end = bytes / dma0->size; /* on last dma transfer must be moved */ - devpriv->last_dma_run = - bytes % devpriv->dmabytestomove[0]; + devpriv->last_dma_run = bytes % dma0->size; if (devpriv->dma_runs_to_end == 0) - devpriv->dmabytestomove[0] = - devpriv->last_dma_run; + dma0->size = devpriv->last_dma_run; devpriv->dma_runs_to_end--; } } - if (devpriv->dmabytestomove[0] > devpriv->hwdmasize) { - devpriv->dmabytestomove[0] = devpriv->hwdmasize; + if (dma0->size > devpriv->hwdmasize) { + dma0->size = devpriv->hwdmasize; devpriv->ai_eos = 0; } - if (devpriv->dmabytestomove[1] > devpriv->hwdmasize) { - devpriv->dmabytestomove[1] = devpriv->hwdmasize; + if (dma1->size > devpriv->hwdmasize) { + dma1->size = devpriv->hwdmasize; devpriv->ai_eos = 0; } - devpriv->next_dma_buf = 0; + devpriv->cur_dma = 0; set_dma_mode(devpriv->dma, DMA_MODE_READ); dma_flags = claim_dma_lock(); clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]); - set_dma_count(devpriv->dma, devpriv->dmabytestomove[0]); + set_dma_addr(devpriv->dma, dma0->hw_addr); + set_dma_count(devpriv->dma, dma0->size); release_dma_lock(dma_flags); enable_dma(devpriv->dma); } @@ -608,21 +609,20 @@ static void pcl812_ai_setup_next_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; + struct pcl812_dma_desc *dma; unsigned long dma_flags; - devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; + devpriv->cur_dma = 1 - devpriv->cur_dma; + dma = &devpriv->dma_desc[devpriv->cur_dma]; disable_dma(devpriv->dma); set_dma_mode(devpriv->dma, DMA_MODE_READ); dma_flags = claim_dma_lock(); - set_dma_addr(devpriv->dma, devpriv->hwdmaptr[devpriv->next_dma_buf]); + set_dma_addr(devpriv->dma, dma->hw_addr); if (devpriv->ai_eos) { - set_dma_count(devpriv->dma, - devpriv->dmabytestomove[devpriv->next_dma_buf]); + set_dma_count(devpriv->dma, dma->size); } else { if (devpriv->dma_runs_to_end) { - set_dma_count(devpriv->dma, - devpriv->dmabytestomove[devpriv-> - next_dma_buf]); + set_dma_count(devpriv->dma, dma->size); } else { set_dma_count(devpriv->dma, devpriv->last_dma_run); } @@ -895,19 +895,17 @@ static void pcl812_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; - int len, bufptr; - unsigned short *ptr; - - ptr = (unsigned short *)devpriv->dmabuf[devpriv->next_dma_buf]; - len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) - - devpriv->ai_poll_ptr; + struct pcl812_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; + unsigned int nsamples; + int bufptr; pcl812_ai_setup_next_dma(dev, s); + nsamples = comedi_bytes_to_samples(s, dma->size) - devpriv->ai_poll_ptr; bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; - transfer_from_dma_buf(dev, s, ptr, bufptr, len); + transfer_from_dma_buf(dev, s, (void *)dma->virt_addr, bufptr, nsamples); } static irqreturn_t pcl812_interrupt(int irq, void *d) @@ -935,6 +933,7 @@ static irqreturn_t pcl812_interrupt(int irq, void *d) static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; + struct pcl812_dma_desc *dma; unsigned long flags; unsigned int top1, top2, i; @@ -956,7 +955,8 @@ static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } /* where is now DMA in buffer */ - top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1; + dma = &devpriv->dma_desc[1 - devpriv->cur_dma]; + top1 = dma->size - top1; top1 >>= 1; /* sample position */ top2 = top1 - devpriv->ai_poll_ptr; if (top2 < 1) { /* no new samples */ @@ -964,9 +964,7 @@ static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } - transfer_from_dma_buf(dev, s, - (void *)devpriv->dmabuf[1 - - devpriv->next_dma_buf], + transfer_from_dma_buf(dev, s, (void *)dma->virt_addr, devpriv->ai_poll_ptr, top2); devpriv->ai_poll_ptr = top1; /* new buffer position */ @@ -1195,6 +1193,7 @@ static void pcl812_set_ai_range_table(struct comedi_device *dev, static int pcl812_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) { struct pcl812_private *devpriv = dev->private; + struct pcl812_dma_desc *dma; int i; if (!(dma_chan == 3 || dma_chan == 1)) @@ -1208,14 +1207,13 @@ static int pcl812_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; for (i = 0; i < 2; i++) { - unsigned long dmabuf; + dma = &devpriv->dma_desc[i]; - dmabuf = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); - if (!dmabuf) + dma->virt_addr = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); + if (!dma->virt_addr) return -ENOMEM; - devpriv->dmabuf[i] = dmabuf; - devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf); + dma->hw_addr = virt_to_bus((void *)dma->virt_addr); } return 0; } @@ -1223,14 +1221,16 @@ static int pcl812_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) static void pcl812_free_dma(struct comedi_device *dev) { struct pcl812_private *devpriv = dev->private; + struct pcl812_dma_desc *dma; int i; if (!devpriv) return; for (i = 0; i < 2; i++) { - if (devpriv->dmabuf[i]) - free_pages(devpriv->dmabuf[i], devpriv->dmapages); + dma = &devpriv->dma_desc[i]; + if (dma->virt_addr) + free_pages(dma->virt_addr, devpriv->dmapages); } if (devpriv->dma) free_dma(devpriv->dma); -- cgit v0.10.2 From 9fe11ffeb1db5cd589931c5bc529b4d040def643 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:08 -0700 Subject: staging: comedi: pcl812: remove VIRT_TO_BUS dependancy Use dma_{alloc,free}_coherent() to allocate and free the DMA buffers. This removes the dependancy on VIRT_TO_BUS. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 59c17e6..4441600 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -168,7 +168,7 @@ config COMEDI_PCL730 config COMEDI_PCL812 tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216" - depends on VIRT_TO_BUS && ISA_DMA_API + depends on ISA_DMA_API ---help--- Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216, ICP DAS A-821PGH/PGL/PGL-NDA, diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index d9f94c9..2c2e7dd 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -507,8 +507,8 @@ static const struct pcl812_board boardtypes[] = { }; struct pcl812_dma_desc { - unsigned long virt_addr; /* virtual address of DMA buffer */ - unsigned int hw_addr; /* hardware (bus) address of DMA buffer */ + void *virt_addr; /* virtual address of DMA buffer */ + dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ unsigned int size; /* transfer size (in bytes) */ }; @@ -518,7 +518,6 @@ struct pcl812_private { unsigned int last_ai_chanspec; unsigned char mode_reg_int; /* there is stored INT number for some card */ unsigned int ai_poll_ptr; /* how many sampes transfer poll */ - unsigned int dmapages; unsigned int hwdmasize; struct pcl812_dma_desc dma_desc[2]; int cur_dma; @@ -905,7 +904,7 @@ static void pcl812_handle_dma(struct comedi_device *dev, bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; - transfer_from_dma_buf(dev, s, (void *)dma->virt_addr, bufptr, nsamples); + transfer_from_dma_buf(dev, s, dma->virt_addr, bufptr, nsamples); } static irqreturn_t pcl812_interrupt(int irq, void *d) @@ -964,7 +963,7 @@ static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } - transfer_from_dma_buf(dev, s, (void *)dma->virt_addr, + transfer_from_dma_buf(dev, s, dma->virt_addr, devpriv->ai_poll_ptr, top2); devpriv->ai_poll_ptr = top1; /* new buffer position */ @@ -1203,17 +1202,15 @@ static int pcl812_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) return 0; devpriv->dma = dma_chan; - devpriv->dmapages = 1; /* we want 8KB */ - devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE; + devpriv->hwdmasize = PAGE_SIZE * 2; /* we want 8KB */ for (i = 0; i < 2; i++) { dma = &devpriv->dma_desc[i]; - dma->virt_addr = __get_dma_pages(GFP_KERNEL, devpriv->dmapages); + dma->virt_addr = dma_alloc_coherent(NULL, devpriv->hwdmasize, + &dma->hw_addr, GFP_KERNEL); if (!dma->virt_addr) return -ENOMEM; - - dma->hw_addr = virt_to_bus((void *)dma->virt_addr); } return 0; } @@ -1230,7 +1227,8 @@ static void pcl812_free_dma(struct comedi_device *dev) for (i = 0; i < 2; i++) { dma = &devpriv->dma_desc[i]; if (dma->virt_addr) - free_pages(dma->virt_addr, devpriv->dmapages); + dma_free_coherent(NULL, devpriv->hwdmasize, + dma->virt_addr, dma->hw_addr); } if (devpriv->dma) free_dma(devpriv->dma); -- cgit v0.10.2 From d5702e34761bd821709234e7900ddbfd19f1c321 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:09 -0700 Subject: staging: comedi: dt282x: introduce dt282x_alloc_dma() The IRA and DMA are optional with this driver but both are required to support async commands. Introduce a helper function to request the IRQ and DMA channel and allocate the buffers. Don't fail the driver attach if the user passed an invalid IRQ or DMA channel or they cannot be requested. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index cfa0f97..873aae6 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1053,26 +1053,49 @@ static const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x) return ai_range_table[x]; } -static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2) +static int dt282x_alloc_dma(struct comedi_device *dev, + struct comedi_devconfig *it) { struct dt282x_private *devpriv = dev->private; - int ret; + unsigned int irq_num = it->options[1]; + unsigned int dma_chan[2]; + int i; - ret = request_dma(dma1, "dt282x A"); - if (ret) - return -EBUSY; - devpriv->dma[0].chan = dma1; + if (it->options[2] < it->options[3]) { + dma_chan[0] = it->options[2]; + dma_chan[1] = it->options[3]; + } else { + dma_chan[0] = it->options[3]; + dma_chan[1] = it->options[2]; + } - ret = request_dma(dma2, "dt282x B"); - if (ret) - return -EBUSY; - devpriv->dma[1].chan = dma2; + if (!irq_num || dma_chan[0] == dma_chan[1] || + dma_chan[0] < 5 || dma_chan[0] > 7 || + dma_chan[1] < 5 || dma_chan[1] > 7) + return 0; + + if (request_irq(irq_num, dt282x_interrupt, 0, dev->board_name, dev)) + return 0; + if (request_dma(dma_chan[0], dev->board_name)) { + free_irq(irq_num, dev); + return 0; + } + if (request_dma(dma_chan[1], dev->board_name)) { + free_dma(dma_chan[0]); + free_irq(irq_num, dev); + return 0; + } + + dev->irq = irq_num; devpriv->dma_maxsize = PAGE_SIZE; - devpriv->dma[0].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); - devpriv->dma[1].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); - if (!devpriv->dma[0].buf || !devpriv->dma[1].buf) - return -ENOMEM; + for (i = 0; i < 2; i++) { + devpriv->dma[i].chan = dma_chan[i]; + devpriv->dma[i].buf = + (void *)__get_free_page(GFP_KERNEL | GFP_DMA); + if (!devpriv->dma[i].buf) + return -ENOMEM; + } return 0; } @@ -1150,36 +1173,9 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; /* an IRQ and 2 DMA channels are required for async command support */ - if (it->options[1] && it->options[2] && it->options[3]) { - unsigned int irq = it->options[1]; - unsigned int dma1 = it->options[2]; - unsigned int dma2 = it->options[3]; - - if (dma2 < dma1) { - unsigned int swap; - - swap = dma1; - dma1 = dma2; - dma2 = swap; - } - - if (dma1 != dma2 && - dma1 >= 5 && dma1 <= 7 && - dma2 >= 5 && dma2 <= 7) { - ret = request_irq(irq, dt282x_interrupt, 0, - dev->board_name, dev); - if (ret == 0) { - dev->irq = irq; - - ret = dt282x_grab_dma(dev, dma1, dma2); - if (ret < 0) { - dt282x_free_dma(dev); - free_irq(dev->irq, dev); - dev->irq = 0; - } - } - } - } + ret = dt282x_alloc_dma(dev, it); + if (ret) + return ret; ret = comedi_alloc_subdevices(dev, 3); if (ret) -- cgit v0.10.2 From eca331c20fbedaf04b28b79f388ae0836db33e5e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:10 -0700 Subject: staging: comedi: dt282x: introduce struct dt282x_dma_desc For aesthetics, introduce a struct to hold the DMA descriptor data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 873aae6..8ee6186 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -300,6 +300,12 @@ static const struct dt282x_board boardtypes[] = { }, }; +struct dt282x_dma_desc { + unsigned int chan; /* DMA channel */ + unsigned short *virt_addr; /* virtual address of DMA buffer */ + unsigned int size; /* transfer size (in bytes) */ +}; + struct dt282x_private { unsigned int ad_2scomp:1; @@ -312,21 +318,16 @@ struct dt282x_private { int ntrig; int nread; - struct { - int chan; - unsigned short *buf; /* DMA buffer */ - int size; /* size of current transfer */ - } dma[2]; + struct dt282x_dma_desc dma_desc[2]; int dma_maxsize; /* max size of DMA transfer (in bytes) */ - int current_dma_index; + int cur_dma; int dma_dir; }; static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) { struct dt282x_private *devpriv = dev->private; - int dma_chan; - unsigned long dma_ptr; + struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index]; unsigned long flags; if (!devpriv->ntrig) @@ -338,18 +339,16 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) n = devpriv->ntrig * 2; devpriv->ntrig -= n / 2; - devpriv->dma[dma_index].size = n; - dma_chan = devpriv->dma[dma_index].chan; - dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); + dma->size = n; - set_dma_mode(dma_chan, DMA_MODE_READ); + set_dma_mode(dma->chan, DMA_MODE_READ); flags = claim_dma_lock(); - clear_dma_ff(dma_chan); - set_dma_addr(dma_chan, dma_ptr); - set_dma_count(dma_chan, n); + clear_dma_ff(dma->chan); + set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); + set_dma_count(dma->chan, dma->size); release_dma_lock(flags); - enable_dma(dma_chan); + enable_dma(dma->chan); return n; } @@ -357,22 +356,19 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) { struct dt282x_private *devpriv = dev->private; - int dma_chan; - unsigned long dma_ptr; + struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index]; unsigned long flags; - devpriv->dma[dma_index].size = n; - dma_chan = devpriv->dma[dma_index].chan; - dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf); + dma->size = n; - set_dma_mode(dma_chan, DMA_MODE_WRITE); + set_dma_mode(dma->chan, DMA_MODE_WRITE); flags = claim_dma_lock(); - clear_dma_ff(dma_chan); - set_dma_addr(dma_chan, dma_ptr); - set_dma_count(dma_chan, n); + clear_dma_ff(dma->chan); + set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); + set_dma_count(dma->chan, dma->size); release_dma_lock(flags); - enable_dma(dma_chan); + enable_dma(dma->chan); return n; } @@ -381,8 +377,8 @@ static void dt282x_disable_dma(struct comedi_device *dev) { struct dt282x_private *devpriv = dev->private; - disable_dma(devpriv->dma[0].chan); - disable_dma(devpriv->dma[1].chan); + disable_dma(devpriv->dma_desc[0].chan); + disable_dma(devpriv->dma_desc[1].chan); } static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags) @@ -444,11 +440,11 @@ static unsigned int dt282x_ao_setup_dma(struct comedi_device *dev, int cur_dma) { struct dt282x_private *devpriv = dev->private; - void *ptr = devpriv->dma[cur_dma].buf; + struct dt282x_dma_desc *dma = &devpriv->dma_desc[cur_dma]; unsigned int nsamples = comedi_bytes_to_samples(s, devpriv->dma_maxsize); unsigned int nbytes; - nbytes = comedi_buf_read_samples(s, ptr, nsamples); + nbytes = comedi_buf_read_samples(s, dma->virt_addr, nsamples); if (nbytes) dt282x_prep_ao_dma(dev, cur_dma, nbytes); else @@ -461,39 +457,35 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev, struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; - int cur_dma = devpriv->current_dma_index; + struct dt282x_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, dev->iobase + DT2821_SUPCSR_REG); - disable_dma(devpriv->dma[cur_dma].chan); + disable_dma(dma->chan); - devpriv->current_dma_index = 1 - cur_dma; - - if (!dt282x_ao_setup_dma(dev, s, cur_dma)) + if (!dt282x_ao_setup_dma(dev, s, devpriv->cur_dma)) s->async->events |= COMEDI_CB_OVERFLOW; + + devpriv->cur_dma = 1 - devpriv->cur_dma; } static void dt282x_ai_dma_interrupt(struct comedi_device *dev, struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; - int cur_dma = devpriv->current_dma_index; - void *ptr = devpriv->dma[cur_dma].buf; - int size = devpriv->dma[cur_dma].size; - unsigned int nsamples = comedi_bytes_to_samples(s, size); + struct dt282x_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; + unsigned int nsamples = comedi_bytes_to_samples(s, dma->size); int ret; outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, dev->iobase + DT2821_SUPCSR_REG); - disable_dma(devpriv->dma[cur_dma].chan); + disable_dma(dma->chan); - devpriv->current_dma_index = 1 - cur_dma; - - dt282x_munge(dev, s, ptr, size); - ret = comedi_buf_write_samples(s, ptr, nsamples); - if (ret != size) + dt282x_munge(dev, s, dma->virt_addr, dma->size); + ret = comedi_buf_write_samples(s, dma->virt_addr, nsamples); + if (ret != dma->size) return; devpriv->nread -= nsamples; @@ -514,7 +506,9 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev, } #endif /* restart the channel */ - dt282x_prep_ai_dma(dev, cur_dma, 0); + dt282x_prep_ai_dma(dev, devpriv->cur_dma, 0); + + devpriv->cur_dma = 1 - devpriv->cur_dma; } static irqreturn_t dt282x_interrupt(int irq, void *d) @@ -769,7 +763,7 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->nread = devpriv->ntrig; devpriv->dma_dir = DMA_MODE_READ; - devpriv->current_dma_index = 0; + devpriv->cur_dma = 0; dt282x_prep_ai_dma(dev, 0, 0); if (devpriv->ntrig) { dt282x_prep_ai_dma(dev, 1, 0); @@ -949,7 +943,7 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->nread = devpriv->ntrig; devpriv->dma_dir = DMA_MODE_WRITE; - devpriv->current_dma_index = 0; + devpriv->cur_dma = 0; outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG); @@ -1090,10 +1084,11 @@ static int dt282x_alloc_dma(struct comedi_device *dev, devpriv->dma_maxsize = PAGE_SIZE; for (i = 0; i < 2; i++) { - devpriv->dma[i].chan = dma_chan[i]; - devpriv->dma[i].buf = - (void *)__get_free_page(GFP_KERNEL | GFP_DMA); - if (!devpriv->dma[i].buf) + struct dt282x_dma_desc *dma = &devpriv->dma_desc[i]; + + dma->chan = dma_chan[i]; + dma->virt_addr = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); + if (!dma->virt_addr) return -ENOMEM; } @@ -1103,18 +1098,18 @@ static int dt282x_alloc_dma(struct comedi_device *dev, static void dt282x_free_dma(struct comedi_device *dev) { struct dt282x_private *devpriv = dev->private; + struct dt282x_dma_desc *dma; int i; if (!devpriv) return; for (i = 0; i < 2; i++) { - if (devpriv->dma[i].chan) - free_dma(devpriv->dma[i].chan); - if (devpriv->dma[i].buf) - free_page((unsigned long)devpriv->dma[i].buf); - devpriv->dma[i].chan = 0; - devpriv->dma[i].buf = NULL; + dma = &devpriv->dma_desc[i]; + if (dma->chan) + free_dma(dma->chan); + if (dma->virt_addr) + free_page((unsigned long)dma->virt_addr); } } -- cgit v0.10.2 From ef98a104c2ffa885de4e5bb76fb2e80fa677f7c5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:11 -0700 Subject: staging: comedi: dt282x: remove VIRT_TO_BUS dependancy Use dma_{alloc,free}_coherent() to allocate and free the DMA buffers. This removes the dependancy on VIRT_TO_BUS. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 4441600..37f33c4 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -372,7 +372,7 @@ config COMEDI_DT2817 config COMEDI_DT282X tristate "Data Translation DT2821 series and DT-EZ ISA card support" - depends on VIRT_TO_BUS && ISA_DMA_API + depends on ISA_DMA_API ---help--- Enable support for Data Translation DT2821 series including DT-EZ DT2821, DT2821-F-16SE, DT2821-F-8DI, DT2821-G-16SE, DT2821-G-8DI, diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 8ee6186..f24ad66 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -302,7 +302,8 @@ static const struct dt282x_board boardtypes[] = { struct dt282x_dma_desc { unsigned int chan; /* DMA channel */ - unsigned short *virt_addr; /* virtual address of DMA buffer */ + void *virt_addr; /* virtual address of DMA buffer */ + dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ unsigned int size; /* transfer size (in bytes) */ }; @@ -344,7 +345,7 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) set_dma_mode(dma->chan, DMA_MODE_READ); flags = claim_dma_lock(); clear_dma_ff(dma->chan); - set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); + set_dma_addr(dma->chan, dma->hw_addr); set_dma_count(dma->chan, dma->size); release_dma_lock(flags); @@ -364,7 +365,7 @@ static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) set_dma_mode(dma->chan, DMA_MODE_WRITE); flags = claim_dma_lock(); clear_dma_ff(dma->chan); - set_dma_addr(dma->chan, virt_to_bus(dma->virt_addr)); + set_dma_addr(dma->chan, dma->hw_addr); set_dma_count(dma->chan, dma->size); release_dma_lock(flags); @@ -1087,7 +1088,8 @@ static int dt282x_alloc_dma(struct comedi_device *dev, struct dt282x_dma_desc *dma = &devpriv->dma_desc[i]; dma->chan = dma_chan[i]; - dma->virt_addr = (void *)__get_free_page(GFP_KERNEL | GFP_DMA); + dma->virt_addr = dma_alloc_coherent(NULL, devpriv->dma_maxsize, + &dma->hw_addr, GFP_KERNEL); if (!dma->virt_addr) return -ENOMEM; } @@ -1109,7 +1111,8 @@ static void dt282x_free_dma(struct comedi_device *dev) if (dma->chan) free_dma(dma->chan); if (dma->virt_addr) - free_page((unsigned long)dma->virt_addr); + dma_free_coherent(NULL, devpriv->dma_maxsize, + dma->virt_addr, dma->hw_addr); } } -- cgit v0.10.2 From 38a7d4999a68af0c18216279971fa7acd8ec7345 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:12 -0700 Subject: staging: comedi: das16: introduce struct das16_dma_desc For aesthetics, introduce a struct to hold the DMA descriptor data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 64b0ada..1c32cbc 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -439,6 +439,11 @@ static inline int timer_period(void) return HZ / 20; } +struct das16_dma_desc { + uint16_t *virt_addr; /* virtual address of DMA buffer */ + dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ +}; + struct das16_private_struct { unsigned int clockbase; unsigned int ctrl_reg; @@ -446,9 +451,8 @@ struct das16_private_struct { unsigned int divisor1; unsigned int divisor2; unsigned int dma_chan; - uint16_t *dma_buffer[2]; - dma_addr_t dma_buffer_addr[2]; - unsigned int current_buffer; + struct das16_dma_desc dma_desc[2]; + unsigned int cur_dma; unsigned int dma_transfer_size; struct comedi_lrange *user_ai_range_table; struct comedi_lrange *user_ao_range_table; @@ -528,11 +532,12 @@ static void das16_interrupt(struct comedi_device *dev) struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; + struct das16_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; + struct das16_dma_desc *nxt_dma; unsigned long spin_flags; unsigned long dma_flags; unsigned int nsamples; int num_bytes, residue; - int buffer_index; spin_lock_irqsave(&dev->spinlock, spin_flags); if (!(devpriv->ctrl_reg & DAS16_CTRL_DMAE)) { @@ -558,14 +563,13 @@ static void das16_interrupt(struct comedi_device *dev) async->events |= COMEDI_CB_EOA; } - buffer_index = devpriv->current_buffer; - devpriv->current_buffer = (devpriv->current_buffer + 1) % 2; + devpriv->cur_dma = 1 - devpriv->cur_dma; devpriv->adc_byte_count -= num_bytes; /* re-enable dma */ if ((async->events & COMEDI_CB_EOA) == 0) { - set_dma_addr(devpriv->dma_chan, - devpriv->dma_buffer_addr[devpriv->current_buffer]); + nxt_dma = &devpriv->dma_desc[devpriv->cur_dma]; + set_dma_addr(devpriv->dma_chan, nxt_dma->hw_addr); set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); enable_dma(devpriv->dma_chan); } @@ -574,8 +578,7 @@ static void das16_interrupt(struct comedi_device *dev) spin_unlock_irqrestore(&dev->spinlock, spin_flags); nsamples = comedi_bytes_to_samples(s, num_bytes); - comedi_buf_write_samples(s, devpriv->dma_buffer[buffer_index], - nsamples); + comedi_buf_write_samples(s, dma->virt_addr, nsamples); comedi_handle_events(dev, s); } @@ -746,6 +749,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) { const struct das16_board *board = dev->board_ptr; struct das16_private_struct *devpriv = dev->private; + struct das16_dma_desc *dma = &devpriv->dma_desc[0]; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned int byte; @@ -800,9 +804,8 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ clear_dma_ff(devpriv->dma_chan); - devpriv->current_buffer = 0; - set_dma_addr(devpriv->dma_chan, - devpriv->dma_buffer_addr[devpriv->current_buffer]); + devpriv->cur_dma = 0; + set_dma_addr(devpriv->dma_chan, dma->hw_addr); devpriv->dma_transfer_size = DAS16_DMA_SIZE; set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); enable_dma(devpriv->dma_chan); @@ -1067,13 +1070,13 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* allocate dma buffers */ for (i = 0; i < 2; i++) { - void *p; + struct das16_dma_desc *dma = &devpriv->dma_desc[i]; - p = pci_alloc_consistent(NULL, DAS16_DMA_SIZE, - &devpriv->dma_buffer_addr[i]); - if (!p) + dma->virt_addr = pci_alloc_consistent(NULL, + DAS16_DMA_SIZE, + &dma->hw_addr); + if (!dma->virt_addr) return -ENOMEM; - devpriv->dma_buffer[i] = p; } flags = claim_dma_lock(); @@ -1219,6 +1222,7 @@ static void das16_detach(struct comedi_device *dev) { const struct das16_board *board = dev->board_ptr; struct das16_private_struct *devpriv = dev->private; + struct das16_dma_desc *dma; int i; if (devpriv) { @@ -1228,11 +1232,11 @@ static void das16_detach(struct comedi_device *dev) das16_reset(dev); for (i = 0; i < 2; i++) { - if (devpriv->dma_buffer[i]) + dma = &devpriv->dma_desc[i]; + if (dma->virt_addr) pci_free_consistent(NULL, DAS16_DMA_SIZE, - devpriv->dma_buffer[i], - devpriv-> - dma_buffer_addr[i]); + dma->virt_addr, + dma->hw_addr); } if (devpriv->dma_chan) free_dma(devpriv->dma_chan); -- cgit v0.10.2 From 7447cd60a3700aa915b45e18afddd338eaaec117 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:13 -0700 Subject: staging: comedi: das16 introduce das16_alloc_dma() DMA is optional with this driver. Introduce a helper function to request the DMA channel and allocate the buffers. Don't fail the driver attach if the user passed an invalid DMA channel or the channel cannot be requested. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 1c32cbc..0f4a587 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -993,6 +993,41 @@ static void das16_reset(struct comedi_device *dev) outb(0, dev->iobase + DAS16_TIMER_BASE_REG + i8254_control_reg); } +static int das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) +{ + struct das16_private_struct *devpriv = dev->private; + struct das16_dma_desc *dma; + unsigned long flags; + int i; + + if (!(dma_chan == 1 || dma_chan == 3)) + return 0; + + if (request_dma(dma_chan, dev->board_name)) + return 0; + devpriv->dma_chan = dma_chan; + + for (i = 0; i < 2; i++) { + dma = &devpriv->dma_desc[i]; + + dma->virt_addr = pci_alloc_consistent(NULL, DAS16_DMA_SIZE, + &dma->hw_addr); + if (!dma->virt_addr) + return -ENOMEM; + } + + flags = claim_dma_lock(); + disable_dma(devpriv->dma_chan); + set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); + release_dma_lock(flags); + + init_timer(&devpriv->timer); + devpriv->timer.function = das16_timer_interrupt; + devpriv->timer.data = (unsigned long)dev; + + return 0; +} + static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct das16_board *board = dev->board_ptr; @@ -1000,7 +1035,6 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_subdevice *s; struct comedi_lrange *lrange; struct comedi_krange *krange; - unsigned int dma_chan = it->options[2]; unsigned int status; int ret; @@ -1055,39 +1089,9 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->clockbase = I8254_OSC_BASE_1MHZ; } - /* initialize dma */ - if (dma_chan == 1 || dma_chan == 3) { - unsigned long flags; - int i; - - if (request_dma(dma_chan, dev->board_name)) { - dev_err(dev->class_dev, - "failed to request dma channel %i\n", - dma_chan); - return -EINVAL; - } - devpriv->dma_chan = dma_chan; - - /* allocate dma buffers */ - for (i = 0; i < 2; i++) { - struct das16_dma_desc *dma = &devpriv->dma_desc[i]; - - dma->virt_addr = pci_alloc_consistent(NULL, - DAS16_DMA_SIZE, - &dma->hw_addr); - if (!dma->virt_addr) - return -ENOMEM; - } - - flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); - release_dma_lock(flags); - - init_timer(&devpriv->timer); - devpriv->timer.function = das16_timer_interrupt; - devpriv->timer.data = (unsigned long)dev; - } + ret = das16_alloc_dma(dev, it->options[2]); + if (ret) + return ret; /* get any user-defined input range */ if (board->ai_pg == das16_pg_none && -- cgit v0.10.2 From 742c4a095973f696cc9337e8ae39c3c4a834f7db Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:14 -0700 Subject: staging: comedi: das16: introduce das16_free_dma() For aesthetics, move the freeing of the DMA channel and the buffers to a helper function. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 0f4a587..e0b41ae 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1028,6 +1028,24 @@ static int das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) return 0; } +static void das16_free_dma(struct comedi_device *dev) +{ + struct das16_private_struct *devpriv = dev->private; + struct das16_dma_desc *dma; + int i; + + if (devpriv->timer.data) + del_timer_sync(&devpriv->timer); + for (i = 0; i < 2; i++) { + dma = &devpriv->dma_desc[i]; + if (dma->virt_addr) + pci_free_consistent(NULL, DAS16_DMA_SIZE, + dma->virt_addr, dma->hw_addr); + } + if (devpriv->dma_chan) + free_dma(devpriv->dma_chan); +} + static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct das16_board *board = dev->board_ptr; @@ -1226,24 +1244,11 @@ static void das16_detach(struct comedi_device *dev) { const struct das16_board *board = dev->board_ptr; struct das16_private_struct *devpriv = dev->private; - struct das16_dma_desc *dma; - int i; if (devpriv) { - if (devpriv->timer.data) - del_timer_sync(&devpriv->timer); if (dev->iobase) das16_reset(dev); - - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; - if (dma->virt_addr) - pci_free_consistent(NULL, DAS16_DMA_SIZE, - dma->virt_addr, - dma->hw_addr); - } - if (devpriv->dma_chan) - free_dma(devpriv->dma_chan); + das16_free_dma(dev); kfree(devpriv->user_ai_range_table); kfree(devpriv->user_ao_range_table); -- cgit v0.10.2 From ed07758759ad3fd2b7b18a1f821c2ad7e84376d0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 12 Jan 2015 10:56:15 -0700 Subject: staging: comedi: das16: board is not a PCI device The DAS16 board is an ISA device not a PCI device. For aesthetics, use dma_{alloc,free}_coherent() to allocate and free the DMA buffers instead of the PCI versions. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index e0b41ae..294cd81 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -72,7 +72,6 @@ #include #include #include -#include #include #include @@ -1010,8 +1009,8 @@ static int das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) for (i = 0; i < 2; i++) { dma = &devpriv->dma_desc[i]; - dma->virt_addr = pci_alloc_consistent(NULL, DAS16_DMA_SIZE, - &dma->hw_addr); + dma->virt_addr = dma_alloc_coherent(NULL, DAS16_DMA_SIZE, + &dma->hw_addr, GFP_KERNEL); if (!dma->virt_addr) return -ENOMEM; } @@ -1039,8 +1038,8 @@ static void das16_free_dma(struct comedi_device *dev) for (i = 0; i < 2; i++) { dma = &devpriv->dma_desc[i]; if (dma->virt_addr) - pci_free_consistent(NULL, DAS16_DMA_SIZE, - dma->virt_addr, dma->hw_addr); + dma_free_coherent(NULL, DAS16_DMA_SIZE, + dma->virt_addr, dma->hw_addr); } if (devpriv->dma_chan) free_dma(devpriv->dma_chan); -- cgit v0.10.2 From 9cf2765f5e39ffd600715a4b19e5fface154ba32 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:20 -0700 Subject: staging: comedi: pcl818: introduce pcl818_isadma_program() Introduce a helper function to program the ISA DMA controller. Program the ISA DMA as described in Documentation/DMA-ISA-LPC.txt. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 19f6b59..4f5f4e9 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -328,6 +328,20 @@ struct pcl818_private { unsigned int ai_cmd_canceled:1; }; +static void pcl818_isadma_program(unsigned int dma_chan, + struct pcl818_dma_desc *dma) +{ + unsigned long flags; + + flags = claim_dma_lock(); + clear_dma_ff(dma_chan); + set_dma_mode(dma_chan, DMA_MODE_READ); + set_dma_addr(dma_chan, dma->hw_addr); + set_dma_count(dma_chan, dma->size); + enable_dma(dma_chan); + release_dma_lock(flags); +} + static void pcl818_start_pacer(struct comedi_device *dev, bool load_counters) { struct pcl818_private *devpriv = dev->private; @@ -349,7 +363,6 @@ static void pcl818_ai_setup_dma(struct comedi_device *dev, struct pcl818_private *devpriv = dev->private; struct pcl818_dma_desc *dma = &devpriv->dma_desc[0]; struct comedi_cmd *cmd = &s->async->cmd; - unsigned int flags; disable_dma(devpriv->dma); /* disable dma */ if (cmd->stop_src == TRIG_COUNT) { @@ -364,13 +377,8 @@ static void pcl818_ai_setup_dma(struct comedi_device *dev, } devpriv->cur_dma = 0; - set_dma_mode(devpriv->dma, DMA_MODE_READ); - flags = claim_dma_lock(); - clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, dma->hw_addr); - set_dma_count(devpriv->dma, dma->size); - release_dma_lock(flags); - enable_dma(devpriv->dma); + + pcl818_isadma_program(devpriv->dma, dma); } static void pcl818_ai_setup_next_dma(struct comedi_device *dev, @@ -379,7 +387,6 @@ static void pcl818_ai_setup_next_dma(struct comedi_device *dev, struct pcl818_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; struct pcl818_dma_desc *dma; - unsigned long flags; disable_dma(devpriv->dma); devpriv->cur_dma = 1 - devpriv->cur_dma; @@ -390,12 +397,8 @@ static void pcl818_ai_setup_next_dma(struct comedi_device *dev, dma->size = devpriv->hwdmasize; else dma->size = devpriv->last_dma_run; - set_dma_mode(devpriv->dma, DMA_MODE_READ); - flags = claim_dma_lock(); - set_dma_addr(devpriv->dma, dma->hw_addr); - set_dma_count(devpriv->dma, dma->size); - release_dma_lock(flags); - enable_dma(devpriv->dma); + + pcl818_isadma_program(devpriv->dma, dma); } devpriv->dma_runs_to_end--; -- cgit v0.10.2 From bed8d5381c8cf34fd7511cd02bb7e312ec83addf Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:21 -0700 Subject: staging: comedi: pcl818: introduce pcl818_isadma_disable() According to Documentation/DMA-ISA-LPC.txt, the DMA lock needs to be claimed before using any of the ISA DMA routines. Introduce a helper function to disable the ISA DMA controller and add the necessary locking calls. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 4f5f4e9..a1279c2 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -342,6 +342,15 @@ static void pcl818_isadma_program(unsigned int dma_chan, release_dma_lock(flags); } +static void pcl818_isadma_disable(unsigned int dma_chan) +{ + unsigned long flags; + + flags = claim_dma_lock(); + disable_dma(dma_chan); + release_dma_lock(flags); +} + static void pcl818_start_pacer(struct comedi_device *dev, bool load_counters) { struct pcl818_private *devpriv = dev->private; @@ -364,7 +373,7 @@ static void pcl818_ai_setup_dma(struct comedi_device *dev, struct pcl818_dma_desc *dma = &devpriv->dma_desc[0]; struct comedi_cmd *cmd = &s->async->cmd; - disable_dma(devpriv->dma); /* disable dma */ + pcl818_isadma_disable(devpriv->dma); if (cmd->stop_src == TRIG_COUNT) { dma->size = cmd->stop_arg * comedi_bytes_per_scan(s); devpriv->dma_runs_to_end = dma->size / devpriv->hwdmasize; @@ -388,7 +397,7 @@ static void pcl818_ai_setup_next_dma(struct comedi_device *dev, struct comedi_cmd *cmd = &s->async->cmd; struct pcl818_dma_desc *dma; - disable_dma(devpriv->dma); + pcl818_isadma_disable(devpriv->dma); devpriv->cur_dma = 1 - devpriv->cur_dma; if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { /* switch dma bufs */ @@ -879,7 +888,7 @@ static int pcl818_ai_cancel(struct comedi_device *dev, return 0; } } - disable_dma(devpriv->dma); + pcl818_isadma_disable(devpriv->dma); } outb(PCL818_CTRL_DISABLE_TRIG, dev->iobase + PCL818_CTRL_REG); -- cgit v0.10.2 From d77bf9736b11671f803e830c5bead436a415d040 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:22 -0700 Subject: staging: comedi: pcl816: introduce pcl816_isadma_program() Introduce a helper function to program the ISA DMA controller. Program the ISA DMA as described in Documentation/DMA-ISA-LPC.txt. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index f880cb9..e0d91a1 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -133,6 +133,20 @@ struct pcl816_private { unsigned int ai_cmd_canceled:1; }; +static void pcl816_isadma_program(unsigned int dma_chan, + struct pcl816_dma_desc *dma) +{ + unsigned long flags; + + flags = claim_dma_lock(); + clear_dma_ff(dma_chan); + set_dma_mode(dma_chan, DMA_MODE_READ); + set_dma_addr(dma_chan, dma->hw_addr); + set_dma_count(dma_chan, dma->size); + enable_dma(dma_chan); + release_dma_lock(flags); +} + static void pcl816_start_pacer(struct comedi_device *dev, bool load_counters) { struct pcl816_private *devpriv = dev->private; @@ -158,7 +172,6 @@ static void pcl816_ai_setup_dma(struct comedi_device *dev, struct pcl816_private *devpriv = dev->private; struct pcl816_dma_desc *dma = &devpriv->dma_desc[0]; struct comedi_cmd *cmd = &s->async->cmd; - unsigned int dma_flags; if (cmd->stop_src == TRIG_COUNT) { /* how many */ @@ -178,13 +191,8 @@ static void pcl816_ai_setup_dma(struct comedi_device *dev, } devpriv->cur_dma = 0; - set_dma_mode(devpriv->dma, DMA_MODE_READ); - dma_flags = claim_dma_lock(); - clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, dma->hw_addr); - set_dma_count(devpriv->dma, dma->size); - release_dma_lock(dma_flags); - enable_dma(devpriv->dma); + + pcl816_isadma_program(devpriv->dma, dma); } static void pcl816_ai_setup_next_dma(struct comedi_device *dev, @@ -193,7 +201,6 @@ static void pcl816_ai_setup_next_dma(struct comedi_device *dev, struct pcl816_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; struct pcl816_dma_desc *dma; - unsigned long dma_flags; disable_dma(devpriv->dma); if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { @@ -204,12 +211,8 @@ static void pcl816_ai_setup_next_dma(struct comedi_device *dev, dma->size = devpriv->hwdmasize; else dma->size = devpriv->last_dma_run; - set_dma_mode(devpriv->dma, DMA_MODE_READ); - dma_flags = claim_dma_lock(); - set_dma_addr(devpriv->dma, dma->hw_addr); - set_dma_count(devpriv->dma, dma->size); - release_dma_lock(dma_flags); - enable_dma(devpriv->dma); + + pcl816_isadma_program(devpriv->dma, dma); } devpriv->dma_runs_to_end--; -- cgit v0.10.2 From 65fdfedbc06169bc49fbbdab205659237a06568c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:23 -0700 Subject: staging: comedi: pcl816: introduce pcl816_isadma_disable() According to Documentation/DMA-ISA-LPC.txt, the DMA lock needs to be claimed before using any of the ISA DMA routines. Introduce a helper function to disable the ISA DMA controller and add the necessary locking calls. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index e0d91a1..d2ce775 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -147,6 +147,15 @@ static void pcl816_isadma_program(unsigned int dma_chan, release_dma_lock(flags); } +static void pcl816_isadma_disable(unsigned int dma_chan) +{ + unsigned long flags; + + flags = claim_dma_lock(); + disable_dma(dma_chan); + release_dma_lock(flags); +} + static void pcl816_start_pacer(struct comedi_device *dev, bool load_counters) { struct pcl816_private *devpriv = dev->private; @@ -202,7 +211,7 @@ static void pcl816_ai_setup_next_dma(struct comedi_device *dev, struct comedi_cmd *cmd = &s->async->cmd; struct pcl816_dma_desc *dma; - disable_dma(devpriv->dma); + pcl816_isadma_disable(devpriv->dma); if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { /* switch dma bufs */ devpriv->cur_dma = 1 - devpriv->cur_dma; -- cgit v0.10.2 From f609c29dfb7a5729bfab9384fad45fbf12653c67 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:24 -0700 Subject: staging: comedi: dt282x: introduce dt282x_isadma_program() Introduce a helper function to program the ISA DMA controller. Program the ISA DMA as described in Documentation/DMA-ISA-LPC.txt. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index f24ad66..2d01c6c 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -305,6 +305,7 @@ struct dt282x_dma_desc { void *virt_addr; /* virtual address of DMA buffer */ dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ unsigned int size; /* transfer size (in bytes) */ + char mode; /* DMA_MODE_* */ }; struct dt282x_private { @@ -325,11 +326,23 @@ struct dt282x_private { int dma_dir; }; +static void dt282x_isadma_program(struct dt282x_dma_desc *dma) +{ + unsigned long flags; + + flags = claim_dma_lock(); + clear_dma_ff(dma->chan); + set_dma_mode(dma->chan, dma->mode); + set_dma_addr(dma->chan, dma->hw_addr); + set_dma_count(dma->chan, dma->size); + enable_dma(dma->chan); + release_dma_lock(flags); +} + static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) { struct dt282x_private *devpriv = dev->private; struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index]; - unsigned long flags; if (!devpriv->ntrig) return 0; @@ -341,15 +354,9 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) devpriv->ntrig -= n / 2; dma->size = n; + dma->mode = DMA_MODE_READ; - set_dma_mode(dma->chan, DMA_MODE_READ); - flags = claim_dma_lock(); - clear_dma_ff(dma->chan); - set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, dma->size); - release_dma_lock(flags); - - enable_dma(dma->chan); + dt282x_isadma_program(dma); return n; } @@ -358,18 +365,11 @@ static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) { struct dt282x_private *devpriv = dev->private; struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index]; - unsigned long flags; dma->size = n; + dma->mode = DMA_MODE_WRITE; - set_dma_mode(dma->chan, DMA_MODE_WRITE); - flags = claim_dma_lock(); - clear_dma_ff(dma->chan); - set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, dma->size); - release_dma_lock(flags); - - enable_dma(dma->chan); + dt282x_isadma_program(dma); return n; } -- cgit v0.10.2 From 7877445b5c1bb10078ef72db65df1553f4cbd73e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:25 -0700 Subject: staging: comedi: dt282x: introduce dt282x_isadma_disable() According to Documentation/DMA-ISA-LPC.txt, the DMA lock needs to be claimed before using any of the ISA DMA routines. Introduce a helper function to disable the ISA DMA controller and add the necessary locking calls. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 2d01c6c..54c679a 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -339,6 +339,15 @@ static void dt282x_isadma_program(struct dt282x_dma_desc *dma) release_dma_lock(flags); } +static void dt282x_isadma_disable(struct dt282x_dma_desc *dma) +{ + unsigned long flags; + + flags = claim_dma_lock(); + disable_dma(dma->chan); + release_dma_lock(flags); +} + static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) { struct dt282x_private *devpriv = dev->private; @@ -377,9 +386,10 @@ static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) static void dt282x_disable_dma(struct comedi_device *dev) { struct dt282x_private *devpriv = dev->private; + int i; - disable_dma(devpriv->dma_desc[0].chan); - disable_dma(devpriv->dma_desc[1].chan); + for (i = 0; i < 2; i++) + dt282x_isadma_disable(&devpriv->dma_desc[i]); } static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags) @@ -463,7 +473,7 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev, outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, dev->iobase + DT2821_SUPCSR_REG); - disable_dma(dma->chan); + dt282x_isadma_disable(dma); if (!dt282x_ao_setup_dma(dev, s, devpriv->cur_dma)) s->async->events |= COMEDI_CB_OVERFLOW; @@ -482,7 +492,7 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev, outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, dev->iobase + DT2821_SUPCSR_REG); - disable_dma(dma->chan); + dt282x_isadma_disable(dma); dt282x_munge(dev, s, dma->virt_addr, dma->size); ret = comedi_buf_write_samples(s, dma->virt_addr, nsamples); -- cgit v0.10.2 From 38f23ed0a61d83fb67afd01895989cae7ee29581 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:26 -0700 Subject: staging: comedi: das1800: pass dma descriptor to das1800_flush_dma_channel() Instead of passing the dma descriptor 'chan' and 'virt_addr' just pass the dma descriptor. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 1eb5eab..f99aa79 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -515,25 +515,25 @@ static void das1800_handle_fifo_not_empty(struct comedi_device *dev, * Assumes dma lock is held */ static void das1800_flush_dma_channel(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int channel, uint16_t *buffer) + struct das1800_dma_desc *dma) { struct das1800_private *devpriv = dev->private; unsigned int nbytes; unsigned int nsamples; - disable_dma(channel); + disable_dma(dma->chan); /* clear flip-flop to make sure 2-byte registers * get set correctly */ - clear_dma_ff(channel); + clear_dma_ff(dma->chan); /* figure out how many points to read */ - nbytes = devpriv->dma_transfer_size - get_dma_residue(channel); + nbytes = devpriv->dma_transfer_size - get_dma_residue(dma->chan); nsamples = comedi_bytes_to_samples(s, nbytes); nsamples = comedi_nsamples_left(s, nsamples); - munge_data(dev, buffer, nsamples); - comedi_buf_write_samples(s, buffer, nsamples); + munge_data(dev, dma->virt_addr, nsamples); + comedi_buf_write_samples(s, dma->virt_addr, nsamples); } /* flushes remaining data from board when external trigger has stopped acquisition @@ -547,13 +547,13 @@ static void das1800_flush_dma(struct comedi_device *dev, const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; flags = claim_dma_lock(); - das1800_flush_dma_channel(dev, s, dma->chan, dma->virt_addr); + das1800_flush_dma_channel(dev, s, dma); if (dual_dma) { /* switch to other channel and flush it */ devpriv->cur_dma = 1 - devpriv->cur_dma; dma = &devpriv->dma_desc[devpriv->cur_dma]; - das1800_flush_dma_channel(dev, s, dma->chan, dma->virt_addr); + das1800_flush_dma_channel(dev, s, dma); } release_dma_lock(flags); @@ -571,7 +571,7 @@ static void das1800_handle_dma(struct comedi_device *dev, const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; flags = claim_dma_lock(); - das1800_flush_dma_channel(dev, s, dma->chan, dma->virt_addr); + das1800_flush_dma_channel(dev, s, dma); /* re-enable dma channel */ set_dma_addr(dma->chan, dma->hw_addr); set_dma_count(dma->chan, devpriv->dma_transfer_size); -- cgit v0.10.2 From 5d12431c5cb5955d6b98700cc665414553986ef2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:27 -0700 Subject: staging: comedi: das1800: move dma transfer 'size' to dma descriptor For asethetics, move the variable that holds the dma transfer 'size' into the dma descriptor. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index f99aa79..c8ad7dd 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -424,6 +424,7 @@ struct das1800_dma_desc { unsigned int chan; /* DMA channel */ void *virt_addr; /* virtual address of DMA buffer */ dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ + unsigned int size; /* transfer size (in bytes) */ }; struct das1800_private { @@ -436,7 +437,6 @@ struct das1800_private { struct das1800_dma_desc dma_desc[2]; int cur_dma; uint16_t *fifo_buf; /* bounce buffer for analog input FIFO */ - unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */ unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */ unsigned short ao_update_bits; /* remembers the last write to the * 'update' dac */ @@ -517,7 +517,6 @@ static void das1800_flush_dma_channel(struct comedi_device *dev, struct comedi_subdevice *s, struct das1800_dma_desc *dma) { - struct das1800_private *devpriv = dev->private; unsigned int nbytes; unsigned int nsamples; @@ -528,7 +527,7 @@ static void das1800_flush_dma_channel(struct comedi_device *dev, clear_dma_ff(dma->chan); /* figure out how many points to read */ - nbytes = devpriv->dma_transfer_size - get_dma_residue(dma->chan); + nbytes = dma->size - get_dma_residue(dma->chan); nsamples = comedi_bytes_to_samples(s, nbytes); nsamples = comedi_nsamples_left(s, nsamples); @@ -574,7 +573,7 @@ static void das1800_handle_dma(struct comedi_device *dev, das1800_flush_dma_channel(dev, s, dma); /* re-enable dma channel */ set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, devpriv->dma_transfer_size); + set_dma_count(dma->chan, dma->size); enable_dma(dma->chan); release_dma_lock(flags); @@ -1001,6 +1000,7 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) struct das1800_dma_desc *dma = &devpriv->dma_desc[0]; unsigned long lock_flags; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; + unsigned int bytes; if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0) return; @@ -1008,7 +1008,9 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) devpriv->cur_dma = 0; /* determine a reasonable dma transfer size */ - devpriv->dma_transfer_size = suggest_transfer_size(cmd); + bytes = suggest_transfer_size(cmd); + + dma->size = bytes; lock_flags = claim_dma_lock(); disable_dma(dma->chan); /* clear flip-flop to make sure 2-byte registers for @@ -1016,18 +1018,19 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) clear_dma_ff(dma->chan); set_dma_addr(dma->chan, dma->hw_addr); /* set appropriate size of transfer */ - set_dma_count(dma->chan, devpriv->dma_transfer_size); + set_dma_count(dma->chan, dma->size); enable_dma(dma->chan); /* set up dual dma if appropriate */ if (dual_dma) { dma = &devpriv->dma_desc[1]; + dma->size = bytes; disable_dma(dma->chan); /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ clear_dma_ff(dma->chan); set_dma_addr(dma->chan, dma->hw_addr); /* set appropriate size of transfer */ - set_dma_count(dma->chan, devpriv->dma_transfer_size); + set_dma_count(dma->chan, dma->size); enable_dma(dma->chan); } release_dma_lock(lock_flags); -- cgit v0.10.2 From dec3aa4fff19e00e2f5be6213adfa4124b93fc19 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:28 -0700 Subject: staging: comedi: das1800: introduce das1800_isadma_program() Introduce a helper function to program the ISA DMA controller. Program the ISA DMA as described in Documentation/DMA-ISA-LPC.txt. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index c8ad7dd..6df58cd 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -452,6 +452,19 @@ static const struct comedi_lrange range_ao_2 = { }; */ +static void das1800_isadma_program(struct das1800_dma_desc *dma) +{ + unsigned long flags; + + flags = claim_dma_lock(); + clear_dma_ff(dma->chan); + set_dma_mode(dma->chan, DMA_MODE_READ); + set_dma_addr(dma->chan, dma->hw_addr); + set_dma_count(dma->chan, dma->size); + enable_dma(dma->chan); + release_dma_lock(flags); +} + static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev, uint16_t sample) { @@ -571,12 +584,11 @@ static void das1800_handle_dma(struct comedi_device *dev, flags = claim_dma_lock(); das1800_flush_dma_channel(dev, s, dma); - /* re-enable dma channel */ - set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, dma->size); - enable_dma(dma->chan); release_dma_lock(flags); + /* re-enable dma channel */ + das1800_isadma_program(dma); + if (status & DMATC) { /* clear DMATC interrupt bit */ outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS); @@ -998,8 +1010,6 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) { struct das1800_private *devpriv = dev->private; struct das1800_dma_desc *dma = &devpriv->dma_desc[0]; - unsigned long lock_flags; - const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; unsigned int bytes; if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0) @@ -1011,29 +1021,14 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) bytes = suggest_transfer_size(cmd); dma->size = bytes; - lock_flags = claim_dma_lock(); - disable_dma(dma->chan); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(dma->chan); - set_dma_addr(dma->chan, dma->hw_addr); - /* set appropriate size of transfer */ - set_dma_count(dma->chan, dma->size); - enable_dma(dma->chan); - /* set up dual dma if appropriate */ - if (dual_dma) { + das1800_isadma_program(dma); + + /* set up dual dma if appropriate */ + if (devpriv->irq_dma_bits & DMA_DUAL) { dma = &devpriv->dma_desc[1]; dma->size = bytes; - disable_dma(dma->chan); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(dma->chan); - set_dma_addr(dma->chan, dma->hw_addr); - /* set appropriate size of transfer */ - set_dma_count(dma->chan, dma->size); - enable_dma(dma->chan); + das1800_isadma_program(dma); } - release_dma_lock(lock_flags); } /* programs channel/gain list into card */ @@ -1299,7 +1294,6 @@ static int das1800_init_dma(struct comedi_device *dev, flags = claim_dma_lock(); disable_dma(dma->chan); - set_dma_mode(dma->chan, DMA_MODE_READ); release_dma_lock(flags); } -- cgit v0.10.2 From ae4e131e0b5ab57313371aa7d773ac8b01fdb2c7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:29 -0700 Subject: staging: comedi: das1800: introduce das1800_isadma_disable() Introduce a helper function to disable and the ISA DMA controller and return the residue as described in Documentation/DMA-ISA-LPC.txt. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 6df58cd..6359fe6 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -465,6 +465,19 @@ static void das1800_isadma_program(struct das1800_dma_desc *dma) release_dma_lock(flags); } +static unsigned int das1800_isadma_disable(unsigned int dma_chan) +{ + unsigned long flags; + unsigned int residue; + + flags = claim_dma_lock(); + disable_dma(dma_chan); + residue = get_dma_residue(dma_chan); + release_dma_lock(flags); + + return residue; +} + static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev, uint16_t sample) { @@ -524,23 +537,16 @@ static void das1800_handle_fifo_not_empty(struct comedi_device *dev, } } -/* Utility function used by das1800_flush_dma() and das1800_handle_dma(). - * Assumes dma lock is held */ +/* Utility function used by das1800_flush_dma() and das1800_handle_dma() */ static void das1800_flush_dma_channel(struct comedi_device *dev, struct comedi_subdevice *s, struct das1800_dma_desc *dma) { - unsigned int nbytes; + unsigned int residue = das1800_isadma_disable(dma->chan); + unsigned int nbytes = dma->size - residue; unsigned int nsamples; - disable_dma(dma->chan); - - /* clear flip-flop to make sure 2-byte registers - * get set correctly */ - clear_dma_ff(dma->chan); - /* figure out how many points to read */ - nbytes = dma->size - get_dma_residue(dma->chan); nsamples = comedi_bytes_to_samples(s, nbytes); nsamples = comedi_nsamples_left(s, nsamples); @@ -555,10 +561,8 @@ static void das1800_flush_dma(struct comedi_device *dev, { struct das1800_private *devpriv = dev->private; struct das1800_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; - unsigned long flags; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; - flags = claim_dma_lock(); das1800_flush_dma_channel(dev, s, dma); if (dual_dma) { @@ -568,8 +572,6 @@ static void das1800_flush_dma(struct comedi_device *dev, das1800_flush_dma_channel(dev, s, dma); } - release_dma_lock(flags); - /* get any remaining samples in fifo */ das1800_handle_fifo_not_empty(dev, s); } @@ -579,12 +581,9 @@ static void das1800_handle_dma(struct comedi_device *dev, { struct das1800_private *devpriv = dev->private; struct das1800_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; - unsigned long flags; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; - flags = claim_dma_lock(); das1800_flush_dma_channel(dev, s, dma); - release_dma_lock(flags); /* re-enable dma channel */ das1800_isadma_program(dma); @@ -611,7 +610,7 @@ static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) for (i = 0; i < 2; i++) { dma = &devpriv->dma_desc[i]; if (dma->chan) - disable_dma(dma->chan); + das1800_isadma_disable(dma->chan); } return 0; @@ -1233,7 +1232,6 @@ static int das1800_init_dma(struct comedi_device *dev, struct das1800_private *devpriv = dev->private; struct das1800_dma_desc *dma; unsigned int *dma_chan; - unsigned long flags; int i; /* @@ -1292,9 +1290,7 @@ static int das1800_init_dma(struct comedi_device *dev, if (!dma->virt_addr) return -ENOMEM; - flags = claim_dma_lock(); - disable_dma(dma->chan); - release_dma_lock(flags); + das1800_isadma_disable(dma->chan); } return 0; -- cgit v0.10.2 From 59e561f3a6a21ac7c10e9ac039a470d6c186eff9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:30 -0700 Subject: staging: comedi: das16: move dma transfer 'size' to dma descriptor For asethetics, move the variable that holds the dma transfer 'size' into the dma descriptor. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 294cd81..f8c444c 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -441,6 +441,7 @@ static inline int timer_period(void) struct das16_dma_desc { uint16_t *virt_addr; /* virtual address of DMA buffer */ dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ + unsigned int size; /* transfer size (in bytes) */ }; struct das16_private_struct { @@ -452,7 +453,6 @@ struct das16_private_struct { unsigned int dma_chan; struct das16_dma_desc dma_desc[2]; unsigned int cur_dma; - unsigned int dma_transfer_size; struct comedi_lrange *user_ai_range_table; struct comedi_lrange *user_ao_range_table; struct timer_list timer; @@ -549,12 +549,12 @@ static void das16_interrupt(struct comedi_device *dev) residue = disable_dma_on_even(dev); /* figure out how many points to read */ - if (residue > devpriv->dma_transfer_size) { + if (residue > dma->size) { dev_err(dev->class_dev, "residue > transfer size!\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; num_bytes = 0; } else - num_bytes = devpriv->dma_transfer_size - residue; + num_bytes = dma->size - residue; if (cmd->stop_src == TRIG_COUNT && num_bytes >= devpriv->adc_byte_count) { @@ -569,7 +569,8 @@ static void das16_interrupt(struct comedi_device *dev) if ((async->events & COMEDI_CB_EOA) == 0) { nxt_dma = &devpriv->dma_desc[devpriv->cur_dma]; set_dma_addr(devpriv->dma_chan, nxt_dma->hw_addr); - set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); + nxt_dma->size = DAS16_DMA_SIZE; + set_dma_count(devpriv->dma_chan, nxt_dma->size); enable_dma(devpriv->dma_chan); } release_dma_lock(dma_flags); @@ -805,8 +806,8 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) clear_dma_ff(devpriv->dma_chan); devpriv->cur_dma = 0; set_dma_addr(devpriv->dma_chan, dma->hw_addr); - devpriv->dma_transfer_size = DAS16_DMA_SIZE; - set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); + dma->size = DAS16_DMA_SIZE; + set_dma_count(devpriv->dma_chan, dma->size); enable_dma(devpriv->dma_chan); release_dma_lock(flags); -- cgit v0.10.2 From 0196285ebd08e08faab32016f09ae66e1da5d398 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:31 -0700 Subject: staging: comedi: das16: introduce das16_isadma_program() Introduce a helper function to program the ISA DMA controller. Program the ISA DMA as described in Documentation/DMA-ISA-LPC.txt. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index f8c444c..f997966 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -461,6 +461,20 @@ struct das16_private_struct { unsigned int can_burst:1; }; +static void das16_isadma_program(unsigned int dma_chan, + struct das16_dma_desc *dma) +{ + unsigned long flags; + + flags = claim_dma_lock(); + clear_dma_ff(dma_chan); + set_dma_mode(dma_chan, DMA_MODE_READ); + set_dma_addr(dma_chan, dma->hw_addr); + set_dma_count(dma_chan, dma->size); + enable_dma(dma_chan); + release_dma_lock(flags); +} + static void das16_ai_enable(struct comedi_device *dev, unsigned int mode, unsigned int src) { @@ -547,6 +561,7 @@ static void das16_interrupt(struct comedi_device *dev) dma_flags = claim_dma_lock(); clear_dma_ff(devpriv->dma_chan); residue = disable_dma_on_even(dev); + release_dma_lock(dma_flags); /* figure out how many points to read */ if (residue > dma->size) { @@ -565,15 +580,12 @@ static void das16_interrupt(struct comedi_device *dev) devpriv->cur_dma = 1 - devpriv->cur_dma; devpriv->adc_byte_count -= num_bytes; - /* re-enable dma */ + /* re-enable dma */ if ((async->events & COMEDI_CB_EOA) == 0) { nxt_dma = &devpriv->dma_desc[devpriv->cur_dma]; - set_dma_addr(devpriv->dma_chan, nxt_dma->hw_addr); nxt_dma->size = DAS16_DMA_SIZE; - set_dma_count(devpriv->dma_chan, nxt_dma->size); - enable_dma(devpriv->dma_chan); + das16_isadma_program(devpriv->dma_chan, nxt_dma); } - release_dma_lock(dma_flags); spin_unlock_irqrestore(&dev->spinlock, spin_flags); @@ -798,18 +810,10 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) } outb(byte, dev->iobase + DAS16_PACER_REG); - /* set up dma transfer */ - flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(devpriv->dma_chan); + /* set up dma transfer */ devpriv->cur_dma = 0; - set_dma_addr(devpriv->dma_chan, dma->hw_addr); dma->size = DAS16_DMA_SIZE; - set_dma_count(devpriv->dma_chan, dma->size); - enable_dma(devpriv->dma_chan); - release_dma_lock(flags); + das16_isadma_program(devpriv->dma_chan, dma); /* set up timer */ spin_lock_irqsave(&dev->spinlock, flags); @@ -1018,7 +1022,6 @@ static int das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) flags = claim_dma_lock(); disable_dma(devpriv->dma_chan); - set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); release_dma_lock(flags); init_timer(&devpriv->timer); -- cgit v0.10.2 From a1ce5f037ee83c1addb114179a776d505be1ddd5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:32 -0700 Subject: staging: comedi: das16: introduce das16_isadma_disable() Introduce a helper function to disable and the ISA DMA controller and return the residue as described in Documentation/DMA-ISA-LPC.txt. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index f997966..09d65fc 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -475,6 +475,19 @@ static void das16_isadma_program(unsigned int dma_chan, release_dma_lock(flags); } +static unsigned int das16_isadma_disable(unsigned int dma_chan) +{ + unsigned long flags; + unsigned int residue; + + flags = claim_dma_lock(); + disable_dma(dma_chan); + residue = get_dma_residue(dma_chan); + release_dma_lock(flags); + + return residue; +} + static void das16_ai_enable(struct comedi_device *dev, unsigned int mode, unsigned int src) { @@ -514,23 +527,24 @@ static int disable_dma_on_even(struct comedi_device *dev) struct das16_private_struct *devpriv = dev->private; static const int disable_limit = 100; static const int enable_timeout = 100; - int residue; + unsigned long flags; + unsigned int residue; int new_residue; int i; int j; - disable_dma(devpriv->dma_chan); - residue = get_dma_residue(devpriv->dma_chan); + residue = das16_isadma_disable(devpriv->dma_chan); for (i = 0; i < disable_limit && (residue % 2); ++i) { + flags = claim_dma_lock(); enable_dma(devpriv->dma_chan); for (j = 0; j < enable_timeout; ++j) { udelay(2); new_residue = get_dma_residue(devpriv->dma_chan); + release_dma_lock(flags); if (new_residue != residue) break; } - disable_dma(devpriv->dma_chan); - residue = get_dma_residue(devpriv->dma_chan); + residue = das16_isadma_disable(devpriv->dma_chan); } if (i == disable_limit) { dev_err(dev->class_dev, @@ -548,7 +562,6 @@ static void das16_interrupt(struct comedi_device *dev) struct das16_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; struct das16_dma_desc *nxt_dma; unsigned long spin_flags; - unsigned long dma_flags; unsigned int nsamples; int num_bytes, residue; @@ -558,10 +571,7 @@ static void das16_interrupt(struct comedi_device *dev) return; } - dma_flags = claim_dma_lock(); - clear_dma_ff(devpriv->dma_chan); residue = disable_dma_on_even(dev); - release_dma_lock(dma_flags); /* figure out how many points to read */ if (residue > dma->size) { @@ -1001,7 +1011,6 @@ static int das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) { struct das16_private_struct *devpriv = dev->private; struct das16_dma_desc *dma; - unsigned long flags; int i; if (!(dma_chan == 1 || dma_chan == 3)) @@ -1020,9 +1029,7 @@ static int das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) return -ENOMEM; } - flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - release_dma_lock(flags); + das16_isadma_disable(devpriv->dma_chan); init_timer(&devpriv->timer); devpriv->timer.function = das16_timer_interrupt; -- cgit v0.10.2 From 1ec64b74c9182e443e8ea26ea3d6df4cdda7e578 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:33 -0700 Subject: staging: comedi: pcl812: introduce pcl812_isadma_program() Introduce a helper function to program the ISA DMA controller. Program the ISA DMA as described in Documentation/DMA-ISA-LPC.txt. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 2c2e7dd..6b38147 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -533,6 +533,20 @@ struct pcl812_private { unsigned int ai_eos:1; }; +static void pcl812_isadma_program(unsigned int dma_chan, + struct pcl812_dma_desc *dma) +{ + unsigned long flags; + + flags = claim_dma_lock(); + clear_dma_ff(dma_chan); + set_dma_mode(dma_chan, DMA_MODE_READ); + set_dma_addr(dma_chan, dma->hw_addr); + set_dma_count(dma_chan, dma->size); + enable_dma(dma_chan); + release_dma_lock(flags); +} + static void pcl812_start_pacer(struct comedi_device *dev, bool load_timers) { struct pcl812_private *devpriv = dev->private; @@ -555,7 +569,6 @@ static void pcl812_ai_setup_dma(struct comedi_device *dev, struct pcl812_dma_desc *dma0 = &devpriv->dma_desc[0]; struct pcl812_dma_desc *dma1 = &devpriv->dma_desc[1]; struct comedi_cmd *cmd = &s->async->cmd; - unsigned int dma_flags; unsigned int bytes; /* we use EOS, so adapt DMA buffer to one scan */ @@ -595,13 +608,8 @@ static void pcl812_ai_setup_dma(struct comedi_device *dev, devpriv->ai_eos = 0; } devpriv->cur_dma = 0; - set_dma_mode(devpriv->dma, DMA_MODE_READ); - dma_flags = claim_dma_lock(); - clear_dma_ff(devpriv->dma); - set_dma_addr(devpriv->dma, dma0->hw_addr); - set_dma_count(devpriv->dma, dma0->size); - release_dma_lock(dma_flags); - enable_dma(devpriv->dma); + + pcl812_isadma_program(devpriv->dma, dma0); } static void pcl812_ai_setup_next_dma(struct comedi_device *dev, @@ -609,26 +617,19 @@ static void pcl812_ai_setup_next_dma(struct comedi_device *dev, { struct pcl812_private *devpriv = dev->private; struct pcl812_dma_desc *dma; - unsigned long dma_flags; + + disable_dma(devpriv->dma); devpriv->cur_dma = 1 - devpriv->cur_dma; dma = &devpriv->dma_desc[devpriv->cur_dma]; - disable_dma(devpriv->dma); - set_dma_mode(devpriv->dma, DMA_MODE_READ); - dma_flags = claim_dma_lock(); - set_dma_addr(devpriv->dma, dma->hw_addr); - if (devpriv->ai_eos) { - set_dma_count(devpriv->dma, dma->size); - } else { - if (devpriv->dma_runs_to_end) { - set_dma_count(devpriv->dma, dma->size); - } else { - set_dma_count(devpriv->dma, devpriv->last_dma_run); - } - devpriv->dma_runs_to_end--; + if (!devpriv->ai_eos) { + if (devpriv->dma_runs_to_end) + devpriv->dma_runs_to_end--; + else + dma->size = devpriv->last_dma_run; } - release_dma_lock(dma_flags); - enable_dma(devpriv->dma); + + pcl812_isadma_program(devpriv->dma, dma); } static void pcl812_ai_set_chan_range(struct comedi_device *dev, -- cgit v0.10.2 From 0156b06a6b3ee8c42c7c404a2a8a5921b74c69f5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:34 -0700 Subject: staging: comedi: pcl812: introduce pcl812_isadma_disable() According to Documentation/DMA-ISA-LPC.txt, the DMA lock needs to be claimed before using any of the ISA DMA routines. Introduce a helper function to disable the ISA DMA controller and add the necessary locking calls. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 6b38147..c67c2c7 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -547,6 +547,15 @@ static void pcl812_isadma_program(unsigned int dma_chan, release_dma_lock(flags); } +static void pcl812_isadma_disable(unsigned int dma_chan) +{ + unsigned long flags; + + flags = claim_dma_lock(); + disable_dma(dma_chan); + release_dma_lock(flags); +} + static void pcl812_start_pacer(struct comedi_device *dev, bool load_timers) { struct pcl812_private *devpriv = dev->private; @@ -618,7 +627,7 @@ static void pcl812_ai_setup_next_dma(struct comedi_device *dev, struct pcl812_private *devpriv = dev->private; struct pcl812_dma_desc *dma; - disable_dma(devpriv->dma); + pcl812_isadma_disable(devpriv->dma); devpriv->cur_dma = 1 - devpriv->cur_dma; dma = &devpriv->dma_desc[devpriv->cur_dma]; @@ -980,7 +989,7 @@ static int pcl812_ai_cancel(struct comedi_device *dev, struct pcl812_private *devpriv = dev->private; if (devpriv->ai_dma) - disable_dma(devpriv->dma); + pcl812_isadma_disable(devpriv->dma); outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG, dev->iobase + PCL812_CTRL_REG); -- cgit v0.10.2 From c92b0b29819bc2b3f504b8341b26bb7c1421ad22 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:35 -0700 Subject: staging: comedi: ni_at_a2150: introduce a2150_isadma_program() Introduce a helper function to program the ISA DMA controller. Program the ISA DMA as described in Documentation/DMA-ISA-LPC.txt. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 3905097..23c59cb 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -159,6 +159,19 @@ struct a2150_private { int config_bits; /* config register bits */ }; +static void a2150_isadma_program(struct a2150_dma_desc *dma) +{ + unsigned long flags; + + flags = claim_dma_lock(); + clear_dma_ff(dma->chan); + set_dma_mode(dma->chan, DMA_MODE_READ); + set_dma_addr(dma->chan, dma->hw_addr); + set_dma_count(dma->chan, dma->size); + enable_dma(dma->chan); + release_dma_lock(flags); +} + /* interrupt service routine */ static irqreturn_t a2150_interrupt(int irq, void *d) { @@ -217,6 +230,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) * the stop_src is set to external triggering. */ residue = comedi_bytes_to_samples(s, get_dma_residue(dma->chan)); + release_dma_lock(flags); num_points = max_points - residue; if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT) num_points = devpriv->count; @@ -250,14 +264,11 @@ static irqreturn_t a2150_interrupt(int irq, void *d) } } } - /* re-enable dma */ + /* re-enable dma */ if (leftover) { - set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, - comedi_samples_to_bytes(s, leftover)); - enable_dma(dma->chan); + dma->size = comedi_samples_to_bytes(s, leftover); + a2150_isadma_program(dma); } - release_dma_lock(flags); comedi_handle_events(dev, s); @@ -549,13 +560,10 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* initialize number of samples remaining */ devpriv->count = cmd->stop_arg * cmd->chanlist_len; - /* enable computer's dma */ lock_flags = claim_dma_lock(); disable_dma(dma->chan); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(dma->chan); - set_dma_addr(dma->chan, dma->hw_addr); + release_dma_lock(lock_flags); + /* set size of transfer to fill in 1/3 second */ #define ONE_THIRD_SECOND 333333333 dma->size = comedi_bytes_per_sample(s) * cmd->chanlist_len * @@ -565,9 +573,8 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (dma->size < comedi_bytes_per_sample(s)) dma->size = comedi_bytes_per_sample(s); dma->size -= dma->size % comedi_bytes_per_sample(s); - set_dma_count(dma->chan, dma->size); - enable_dma(dma->chan); - release_dma_lock(lock_flags); + + a2150_isadma_program(dma); /* clear dma interrupt before enabling it, to try and get rid of that * one spurious interrupt that has been happening */ @@ -724,7 +731,6 @@ static void a2150_alloc_irq_dma(struct comedi_device *dev, devpriv->irq_dma_bits = IRQ_LVL_BITS(irq_num) | DMA_CHAN_BITS(dma_chan); disable_dma(dma_chan); - set_dma_mode(dma_chan, DMA_MODE_READ); } static void a2150_free_dma(struct comedi_device *dev) -- cgit v0.10.2 From 10f3a2dca81ace26daacf26c5d79c5876576e7ea Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:36 -0700 Subject: staging: comedi: ni_at_a2150: introduce a2150_isadma_disable() Introduce a helper function to disable and the ISA DMA controller and return the residue as described in Documentation/DMA-ISA-LPC.txt. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 23c59cb..73768d0 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -172,12 +172,24 @@ static void a2150_isadma_program(struct a2150_dma_desc *dma) release_dma_lock(flags); } +static unsigned int a2150_isadma_disable(struct a2150_dma_desc *dma) +{ + unsigned long flags; + unsigned int residue; + + flags = claim_dma_lock(); + disable_dma(dma->chan); + residue = get_dma_residue(dma->chan); + release_dma_lock(flags); + + return residue; +} + /* interrupt service routine */ static irqreturn_t a2150_interrupt(int irq, void *d) { int i; int status; - unsigned long flags; struct comedi_device *dev = d; struct a2150_private *devpriv = dev->private; struct a2150_dma_desc *dma = &devpriv->dma_desc; @@ -217,21 +229,16 @@ static irqreturn_t a2150_interrupt(int irq, void *d) return IRQ_HANDLED; } - flags = claim_dma_lock(); - disable_dma(dma->chan); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(dma->chan); - - /* figure out how many points to read */ - max_points = comedi_bytes_to_samples(s, dma->size); - /* residue is the number of points left to be done on the dma + /* + * residue is the number of bytes left to be done on the dma * transfer. It should always be zero at this point unless * the stop_src is set to external triggering. */ - residue = comedi_bytes_to_samples(s, get_dma_residue(dma->chan)); - release_dma_lock(flags); - num_points = max_points - residue; + residue = a2150_isadma_disable(dma); + + /* figure out how many points to read */ + max_points = comedi_bytes_to_samples(s, dma->size); + num_points = max_points - comedi_bytes_to_samples(s, residue); if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT) num_points = devpriv->count; @@ -288,7 +295,7 @@ static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s) outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); /* disable computer's dma */ - disable_dma(dma->chan); + a2150_isadma_disable(dma); /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); @@ -524,7 +531,6 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned long timer_base = dev->iobase + I8253_BASE_REG; - unsigned long lock_flags; unsigned int old_config_bits = devpriv->config_bits; unsigned int trigger_bits; @@ -560,9 +566,7 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* initialize number of samples remaining */ devpriv->count = cmd->stop_arg * cmd->chanlist_len; - lock_flags = claim_dma_lock(); - disable_dma(dma->chan); - release_dma_lock(lock_flags); + a2150_isadma_disable(dma); /* set size of transfer to fill in 1/3 second */ #define ONE_THIRD_SECOND 333333333 @@ -730,7 +734,7 @@ static void a2150_alloc_irq_dma(struct comedi_device *dev, dma->chan = dma_chan; devpriv->irq_dma_bits = IRQ_LVL_BITS(irq_num) | DMA_CHAN_BITS(dma_chan); - disable_dma(dma_chan); + a2150_isadma_disable(dma); } static void a2150_free_dma(struct comedi_device *dev) -- cgit v0.10.2 From ac525a7f724ef47cae087fc2b09978a5fdda829c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:37 -0700 Subject: staging: comedi: ni_labpc_isadma: remove hard coded samples size Use the comedi_bytes_per_sample() helper and remove the hard coded sample size. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index ecdbe11..43e4f99 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -30,12 +30,13 @@ /* size in bytes of dma buffer */ static const int dma_buffer_size = 0xff00; -/* 2 bytes per sample */ -static const int sample_size = 2; /* utility function that suggests a dma transfer size in bytes */ -static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) +static unsigned int labpc_suggest_transfer_size(struct comedi_device *dev, + struct comedi_subdevice *s) { + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int sample_size = comedi_bytes_per_sample(s); unsigned int size; unsigned int freq; @@ -62,6 +63,7 @@ void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) struct labpc_private *devpriv = dev->private; struct labpc_dma_desc *dma = &devpriv->dma_desc; struct comedi_cmd *cmd = &s->async->cmd; + unsigned int sample_size = comedi_bytes_per_sample(s); unsigned long irq_flags; irq_flags = claim_dma_lock(); @@ -71,7 +73,7 @@ void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) clear_dma_ff(dma->chan); set_dma_addr(dma->chan, dma->hw_addr); /* set appropriate size of transfer */ - dma->size = labpc_suggest_transfer_size(cmd); + dma->size = labpc_suggest_transfer_size(dev, s); if (cmd->stop_src == TRIG_COUNT && devpriv->count * sample_size < dma->size) dma->size = devpriv->count * sample_size; @@ -90,6 +92,7 @@ void labpc_drain_dma(struct comedi_device *dev) struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; + unsigned int sample_size = comedi_bytes_per_sample(s); int status; unsigned long flags; unsigned int max_points, num_points, residue, leftover; -- cgit v0.10.2 From afd8f40f6f10bb43c445458a36b873add4dd08f3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:38 -0700 Subject: staging: comedi: ni_labpc_isadma: convert 'dma_buffer_size' to a define For aesthetics, convert this statis const global variable to a define. Cleanup the maximum 'size' calc in labpc_suggest_transfer_size(). The modulo operation will always result in '0'. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 43e4f99..0ce8aad 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -29,7 +29,7 @@ #include "ni_labpc_isadma.h" /* size in bytes of dma buffer */ -static const int dma_buffer_size = 0xff00; +#define LABPC_ISADMA_BUFFER_SIZE 0xff00 /* utility function that suggests a dma transfer size in bytes */ static unsigned int labpc_suggest_transfer_size(struct comedi_device *dev, @@ -50,8 +50,8 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_device *dev, size = (freq / 3) * sample_size; /* set a minimum and maximum size allowed */ - if (size > dma_buffer_size) - size = dma_buffer_size - dma_buffer_size % sample_size; + if (size > LABPC_ISADMA_BUFFER_SIZE) + size = LABPC_ISADMA_BUFFER_SIZE; else if (size < sample_size) size = sample_size; @@ -178,7 +178,7 @@ void labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) if (request_dma(dma_chan, dev->board_name)) return; - dma->virt_addr = dma_alloc_coherent(NULL, dma_buffer_size, + dma->virt_addr = dma_alloc_coherent(NULL, LABPC_ISADMA_BUFFER_SIZE, &dma->hw_addr, GFP_KERNEL); if (!dma->virt_addr) { free_dma(dma_chan); @@ -200,7 +200,7 @@ void labpc_free_dma_chan(struct comedi_device *dev) struct labpc_dma_desc *dma = &devpriv->dma_desc; if (dma->virt_addr) - dma_free_coherent(NULL, dma_buffer_size, + dma_free_coherent(NULL, LABPC_ISADMA_BUFFER_SIZE, dma->virt_addr, dma->hw_addr); if (dma->chan) free_dma(dma->chan); -- cgit v0.10.2 From 0f02b081da44370d5c88340501e7a12ef9076a34 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:39 -0700 Subject: staging: comedi: ni_labpc_isadma: introduce labpc_isadma_disable() Introduce a helper function to disable and the ISA DMA controller and return the residue as described in Documentation/DMA-ISA-LPC.txt. The DMA will always be disabled when labpc_setup_dma() is called. Remove the unnecessary disable in that function. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 0ce8aad..862fb7e 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -31,6 +31,19 @@ /* size in bytes of dma buffer */ #define LABPC_ISADMA_BUFFER_SIZE 0xff00 +static unsigned int labpc_isadma_disable(struct labpc_dma_desc *dma) +{ + unsigned long flags; + unsigned int residue; + + flags = claim_dma_lock(); + disable_dma(dma->chan); + residue = get_dma_residue(dma->chan); + release_dma_lock(flags); + + return residue; +} + /* utility function that suggests a dma transfer size in bytes */ static unsigned int labpc_suggest_transfer_size(struct comedi_device *dev, struct comedi_subdevice *s) @@ -67,10 +80,10 @@ void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) unsigned long irq_flags; irq_flags = claim_dma_lock(); - disable_dma(dma->chan); /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ clear_dma_ff(dma->chan); + set_dma_mode(dma->chan, DMA_MODE_READ); set_dma_addr(dma->chan, dma->hw_addr); /* set appropriate size of transfer */ dma->size = labpc_suggest_transfer_size(dev, s); @@ -99,20 +112,16 @@ void labpc_drain_dma(struct comedi_device *dev) status = devpriv->stat1; - flags = claim_dma_lock(); - disable_dma(dma->chan); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(dma->chan); - - /* figure out how many points to read */ - max_points = dma->size / sample_size; - /* residue is the number of points left to be done on the dma + /* + * residue is the number of bytes left to be done on the dma * transfer. It should always be zero at this point unless * the stop_src is set to external triggering. */ - residue = get_dma_residue(dma->chan) / sample_size; - num_points = max_points - residue; + residue = labpc_isadma_disable(dma); + + /* figure out how many points to read */ + max_points = dma->size / sample_size; + num_points = max_points - comedi_bytes_to_samples(s, residue); if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_points) num_points = devpriv->count; @@ -132,6 +141,8 @@ void labpc_drain_dma(struct comedi_device *dev) devpriv->count -= num_points; /* set address and count for next transfer */ + flags = claim_dma_lock(); + set_dma_mode(dma->chan, DMA_MODE_READ); set_dma_addr(dma->chan, dma->hw_addr); set_dma_count(dma->chan, leftover * sample_size); release_dma_lock(flags); @@ -170,7 +181,6 @@ void labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) { struct labpc_private *devpriv = dev->private; struct labpc_dma_desc *dma = &devpriv->dma_desc; - unsigned long dma_flags; if (dma_chan != 1 && dma_chan != 3) return; @@ -187,10 +197,7 @@ void labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) dma->chan = dma_chan; - dma_flags = claim_dma_lock(); - disable_dma(dma->chan); - set_dma_mode(dma->chan, DMA_MODE_READ); - release_dma_lock(dma_flags); + labpc_isadma_disable(dma); } EXPORT_SYMBOL_GPL(labpc_init_dma_chan); -- cgit v0.10.2 From 72ba5c1612f5ea7f907290903e8fc24ed94aec13 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:40 -0700 Subject: staging: comedi: ni_labpc_isadma: tidy up labpc_drain_dma() Tidy up the code that determines the number of samples to read for the current DMA transfer and how many samples are needed for the next DMA, Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 862fb7e..2fb7e72 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -105,12 +105,11 @@ void labpc_drain_dma(struct comedi_device *dev) struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - unsigned int sample_size = comedi_bytes_per_sample(s); - int status; + unsigned int max_samples = comedi_bytes_to_samples(s, dma->size); + unsigned int residue; + unsigned int nsamples; + unsigned int leftover; unsigned long flags; - unsigned int max_points, num_points, residue, leftover; - - status = devpriv->stat1; /* * residue is the number of bytes left to be done on the dma @@ -119,32 +118,33 @@ void labpc_drain_dma(struct comedi_device *dev) */ residue = labpc_isadma_disable(dma); - /* figure out how many points to read */ - max_points = dma->size / sample_size; - num_points = max_points - comedi_bytes_to_samples(s, residue); - if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_points) - num_points = devpriv->count; - - /* figure out how many points will be stored next time */ - leftover = 0; - if (cmd->stop_src != TRIG_COUNT) { - leftover = dma->size / sample_size; - } else if (devpriv->count > num_points) { - leftover = devpriv->count - num_points; - if (leftover > max_points) - leftover = max_points; + /* + * Figure out how many samples to read for this transfer and + * how many will be stored for next time. + */ + nsamples = max_samples - comedi_bytes_to_samples(s, residue); + if (cmd->stop_src == TRIG_COUNT) { + if (devpriv->count <= nsamples) { + nsamples = devpriv->count; + leftover = 0; + } else { + leftover = devpriv->count - nsamples; + if (leftover > max_samples) + leftover = max_samples; + } + devpriv->count -= nsamples; + } else { + leftover = max_samples; } + dma->size = comedi_samples_to_bytes(s, leftover); - comedi_buf_write_samples(s, dma->virt_addr, num_points); - - if (cmd->stop_src == TRIG_COUNT) - devpriv->count -= num_points; + comedi_buf_write_samples(s, dma->virt_addr, nsamples); /* set address and count for next transfer */ flags = claim_dma_lock(); set_dma_mode(dma->chan, DMA_MODE_READ); set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, leftover * sample_size); + set_dma_count(dma->chan, dma->size); release_dma_lock(flags); } EXPORT_SYMBOL_GPL(labpc_drain_dma); -- cgit v0.10.2 From f2c6bbe8e02d589a02282c2a260f912ab4f12376 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:41 -0700 Subject: staging: comedi: ni_labpc_isadma: move dma programming out of labpc_drain_dma() The external caller of labpc_drain_dma() does not enable the DMA transfer. Only the call from handle_isa_dma() results in the programmed DMA operation getting enabled. For aesthetics, move the dma programming to handle_isa_dma(). Make sure the DMA operation would actually do something (dma->size != 0) before programming it to avoid enabling the DMA at the end of a stop_src == TRIG_COUNT command. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 2fb7e72..af13f4b 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -109,7 +109,6 @@ void labpc_drain_dma(struct comedi_device *dev) unsigned int residue; unsigned int nsamples; unsigned int leftover; - unsigned long flags; /* * residue is the number of bytes left to be done on the dma @@ -139,13 +138,6 @@ void labpc_drain_dma(struct comedi_device *dev) dma->size = comedi_samples_to_bytes(s, leftover); comedi_buf_write_samples(s, dma->virt_addr, nsamples); - - /* set address and count for next transfer */ - flags = claim_dma_lock(); - set_dma_mode(dma->chan, DMA_MODE_READ); - set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, dma->size); - release_dma_lock(flags); } EXPORT_SYMBOL_GPL(labpc_drain_dma); @@ -153,10 +145,18 @@ static void handle_isa_dma(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; struct labpc_dma_desc *dma = &devpriv->dma_desc; + unsigned long flags; labpc_drain_dma(dev); - enable_dma(dma->chan); + if (dma->size) { + flags = claim_dma_lock(); + set_dma_mode(dma->chan, DMA_MODE_READ); + set_dma_addr(dma->chan, dma->hw_addr); + set_dma_count(dma->chan, dma->size); + enable_dma(dma->chan); + release_dma_lock(flags); + } /* clear dma tc interrupt */ devpriv->write_byte(dev, 0x1, DMATC_CLEAR_REG); -- cgit v0.10.2 From 0afa6153fb6fd2b1865248d96058b26ae2f1bcf5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:42 -0700 Subject: staging: comedi: ni_labpc_isadma: introduce labpc_isadma_program() Introduce a helper function to program the ISA DMA controller. Program the ISA DMA as described in Documentation/DMA-ISA-LPC.txt. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index af13f4b..3100549 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -31,6 +31,19 @@ /* size in bytes of dma buffer */ #define LABPC_ISADMA_BUFFER_SIZE 0xff00 +static void labpc_isadma_program(struct labpc_dma_desc *dma) +{ + unsigned long flags; + + flags = claim_dma_lock(); + clear_dma_ff(dma->chan); + set_dma_mode(dma->chan, DMA_MODE_READ); + set_dma_addr(dma->chan, dma->hw_addr); + set_dma_count(dma->chan, dma->size); + enable_dma(dma->chan); + release_dma_lock(flags); +} + static unsigned int labpc_isadma_disable(struct labpc_dma_desc *dma) { unsigned long flags; @@ -77,22 +90,15 @@ void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) struct labpc_dma_desc *dma = &devpriv->dma_desc; struct comedi_cmd *cmd = &s->async->cmd; unsigned int sample_size = comedi_bytes_per_sample(s); - unsigned long irq_flags; - irq_flags = claim_dma_lock(); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(dma->chan); - set_dma_mode(dma->chan, DMA_MODE_READ); - set_dma_addr(dma->chan, dma->hw_addr); /* set appropriate size of transfer */ dma->size = labpc_suggest_transfer_size(dev, s); if (cmd->stop_src == TRIG_COUNT && devpriv->count * sample_size < dma->size) dma->size = devpriv->count * sample_size; - set_dma_count(dma->chan, dma->size); - enable_dma(dma->chan); - release_dma_lock(irq_flags); + + labpc_isadma_program(dma); + /* set CMD3 bits for caller to enable DMA and interrupt */ devpriv->cmd3 |= (CMD3_DMAEN | CMD3_DMATCINTEN); } @@ -145,18 +151,11 @@ static void handle_isa_dma(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; struct labpc_dma_desc *dma = &devpriv->dma_desc; - unsigned long flags; labpc_drain_dma(dev); - if (dma->size) { - flags = claim_dma_lock(); - set_dma_mode(dma->chan, DMA_MODE_READ); - set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, dma->size); - enable_dma(dma->chan); - release_dma_lock(flags); - } + if (dma->size) + labpc_isadma_program(dma); /* clear dma tc interrupt */ devpriv->write_byte(dev, 0x1, DMATC_CLEAR_REG); -- cgit v0.10.2 From 620ec185a208f5bf54af46912ae75a330697bd3f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:43 -0700 Subject: staging: comedi: das1800: remove hard coded 'sample_size' Use the comedi_bytes_per_sample() helper to remove the hard coded sample_size in suggest_transfer_size(). The helper function needs to comedi_subdevice pointer. Change the parameters passed to suggest_transfer_size() and setup_dma() so that this pointer is available. Rename these functions so they have namespace associated with the driver. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 6359fe6..c36ce0c 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -966,11 +966,12 @@ static void das1800_setup_counters(struct comedi_device *dev, } } -/* utility function that suggests a dma transfer size based on the conversion period 'ns' */ -static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd) +static unsigned int das1800_ai_transfer_size(struct comedi_device *dev, + struct comedi_subdevice *s) { + struct comedi_cmd *cmd = &s->async->cmd; unsigned int size = DMA_BUF_SIZE; - static const int sample_size = 2; /* size in bytes of one sample from board */ + unsigned int sample_size = comedi_bytes_per_sample(s); unsigned int fill_time = 300000000; /* target time in nanoseconds for filling dma buffer */ unsigned int max_size; /* maximum size we will allow for a transfer */ @@ -1004,8 +1005,8 @@ static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd) return size; } -/* sets up dma */ -static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) +static void das1800_ai_setup_dma(struct comedi_device *dev, + struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; struct das1800_dma_desc *dma = &devpriv->dma_desc[0]; @@ -1017,7 +1018,7 @@ static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) devpriv->cur_dma = 0; /* determine a reasonable dma transfer size */ - bytes = suggest_transfer_size(cmd); + bytes = das1800_ai_transfer_size(dev, s); dma->size = bytes; das1800_isadma_program(dma); @@ -1089,7 +1090,7 @@ static int das1800_ai_do_cmd(struct comedi_device *dev, /* setup card and start */ program_chanlist(dev, cmd); das1800_setup_counters(dev, cmd); - setup_dma(dev, cmd); + das1800_ai_setup_dma(dev, s); outb(control_c, dev->iobase + DAS1800_CONTROL_C); /* set conversion rate and length for burst mode */ if (control_c & BMDE) { -- cgit v0.10.2 From 5e5a21cf8e7756f668e7eb51ba99619136b79c4d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 13 Jan 2015 10:16:44 -0700 Subject: staging: comedi: das1800: tidy up das1800_ai_transfer_size() For aesthetics, pass the fill time 'ns' as a parameter to this function. Refactor this function to calculate the transfer size in 'samples' instead of 'bytes'. This removes the need to constantly multiply the values by the 'sample_size'. It also helps avoid any possible integer overflow issues. Use the comedi_nsamples_left() helper to limit the samples when cmd->stop_src is TRIG_COUNT. Use comedi_samples_to_bytes() to return the final DMA size in bytes. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index c36ce0c..5be5162 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -967,42 +967,35 @@ static void das1800_setup_counters(struct comedi_device *dev, } static unsigned int das1800_ai_transfer_size(struct comedi_device *dev, - struct comedi_subdevice *s) + struct comedi_subdevice *s, + unsigned int ns) { struct comedi_cmd *cmd = &s->async->cmd; - unsigned int size = DMA_BUF_SIZE; - unsigned int sample_size = comedi_bytes_per_sample(s); - unsigned int fill_time = 300000000; /* target time in nanoseconds for filling dma buffer */ - unsigned int max_size; /* maximum size we will allow for a transfer */ + unsigned int max_samples = comedi_bytes_to_samples(s, DMA_BUF_SIZE); + unsigned int samples; - /* make dma buffer fill in 0.3 seconds for timed modes */ + samples = max_samples; + + /* for timed modes, make dma buffer fill in 'ns' time */ switch (cmd->scan_begin_src) { - case TRIG_FOLLOW: /* not in burst mode */ + case TRIG_FOLLOW: /* not in burst mode */ if (cmd->convert_src == TRIG_TIMER) - size = (fill_time / cmd->convert_arg) * sample_size; + samples = ns / cmd->convert_arg; break; case TRIG_TIMER: - size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) * - sample_size; - break; - default: - size = DMA_BUF_SIZE; + samples = ns / (cmd->scan_begin_arg * cmd->chanlist_len); break; } - /* set a minimum and maximum size allowed */ - max_size = DMA_BUF_SIZE; - /* if we are taking limited number of conversions, limit transfer size to that */ - if (cmd->stop_src == TRIG_COUNT && - cmd->stop_arg * cmd->chanlist_len * sample_size < max_size) - max_size = cmd->stop_arg * cmd->chanlist_len * sample_size; + /* limit samples to what is remaining in the command */ + samples = comedi_nsamples_left(s, samples); - if (size > max_size) - size = max_size; - if (size < sample_size) - size = sample_size; + if (samples > max_samples) + samples = max_samples; + if (samples < 1) + samples = 1; - return size; + return comedi_samples_to_bytes(s, samples); } static void das1800_ai_setup_dma(struct comedi_device *dev, @@ -1017,8 +1010,8 @@ static void das1800_ai_setup_dma(struct comedi_device *dev, devpriv->cur_dma = 0; - /* determine a reasonable dma transfer size */ - bytes = das1800_ai_transfer_size(dev, s); + /* determine a dma transfer size to fill buffer in 0.3 sec */ + bytes = das1800_ai_transfer_size(dev, s, 300000000); dma->size = bytes; das1800_isadma_program(dma); -- cgit v0.10.2 From 20a1ea7d6ba184a1f6e25e85786738003387cada Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:02 -0700 Subject: staging: comedi: comedi_isadma: introduce helper module for ISA DMA Introduce a new helper module to consolidate all the ISA DMA code. This will allow removing the "depends on ISA_DMA_API" from the legacy drivers that can use DMA for async command support. This module is complete based on the various uses of ISA DMA in the comedi drivers. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 37f33c4..1e296b7 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -1262,6 +1262,9 @@ config COMEDI_DAS08 tristate select COMEDI_8255 +config COMEDI_ISADMA + tristate + config COMEDI_NI_LABPC tristate select COMEDI_8255 diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index 84fdf20..7d1fbd5 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile @@ -3,6 +3,7 @@ ccflags-$(CONFIG_COMEDI_DEBUG) := -DDEBUG # Comedi "helper" modules +obj-$(CONFIG_COMEDI_ISADMA) += comedi_isadma.o # Comedi misc drivers obj-$(CONFIG_COMEDI_BOND) += comedi_bond.o diff --git a/drivers/staging/comedi/drivers/comedi_isadma.c b/drivers/staging/comedi/drivers/comedi_isadma.c new file mode 100644 index 0000000..dbdea71 --- /dev/null +++ b/drivers/staging/comedi/drivers/comedi_isadma.c @@ -0,0 +1,262 @@ +/* + * COMEDI ISA DMA support functions + * Copyright (c) 2014 H Hartley Sweeten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include + +#include "../comedidev.h" + +#include "comedi_isadma.h" + +/** + * comedi_isadma_program - program and enable an ISA DMA transfer + * @desc: the ISA DMA cookie to program and enable + */ +void comedi_isadma_program(struct comedi_isadma_desc *desc) +{ + unsigned long flags; + + flags = claim_dma_lock(); + clear_dma_ff(desc->chan); + set_dma_mode(desc->chan, desc->mode); + set_dma_addr(desc->chan, desc->hw_addr); + set_dma_count(desc->chan, desc->size); + enable_dma(desc->chan); + release_dma_lock(flags); +} +EXPORT_SYMBOL_GPL(comedi_isadma_program); + +/** + * comedi_isadma_disable - disable the ISA DMA channel + * @dma_chan: the DMA channel to disable + * + * Returns the residue (remaining bytes) left in the DMA transfer. + */ +unsigned int comedi_isadma_disable(unsigned int dma_chan) +{ + unsigned long flags; + unsigned int residue; + + flags = claim_dma_lock(); + disable_dma(dma_chan); + residue = get_dma_residue(dma_chan); + release_dma_lock(flags); + + return residue; +} +EXPORT_SYMBOL_GPL(comedi_isadma_disable); + +/** + * comedi_isadma_disable_on_sample - disable the ISA DMA channel + * @dma_chan: the DMA channel to disable + * @size: the sample size (in bytes) + * + * Returns the residue (remaining bytes) left in the DMA transfer. + */ +unsigned int comedi_isadma_disable_on_sample(unsigned int dma_chan, + unsigned int size) +{ + int stalled = 0; + unsigned long flags; + unsigned int residue; + unsigned int new_residue; + + residue = comedi_isadma_disable(dma_chan); + while (residue % size) { + /* residue is a partial sample, enable DMA to allow more data */ + flags = claim_dma_lock(); + enable_dma(dma_chan); + release_dma_lock(flags); + + udelay(2); + new_residue = comedi_isadma_disable(dma_chan); + + /* is DMA stalled? */ + if (new_residue == residue) { + stalled++; + if (stalled > 10) + break; + } + residue = new_residue; + stalled = 0; + } + return residue; +} +EXPORT_SYMBOL_GPL(comedi_isadma_disable_on_sample); + +/** + * comedi_isadma_poll - poll the current DMA transfer + * @dma: the ISA DMA to poll + * + * Returns the position (in bytes) of the current DMA transfer. + */ +unsigned int comedi_isadma_poll(struct comedi_isadma *dma) +{ + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned long flags; + unsigned int result; + unsigned int result1; + + flags = claim_dma_lock(); + clear_dma_ff(desc->chan); + if (!isa_dma_bridge_buggy) + disable_dma(desc->chan); + result = get_dma_residue(desc->chan); + /* + * Read the counter again and choose higher value in order to + * avoid reading during counter lower byte roll over if the + * isa_dma_bridge_buggy is set. + */ + result1 = get_dma_residue(desc->chan); + if (!isa_dma_bridge_buggy) + enable_dma(desc->chan); + release_dma_lock(flags); + + if (result < result1) + result = result1; + if (result >= desc->size || result == 0) + return 0; + else + return desc->size - result; +} +EXPORT_SYMBOL_GPL(comedi_isadma_poll); + +/** + * comedi_isadma_set_mode - set the ISA DMA transfer direction + * @desc: the ISA DMA cookie to set + * @dma_dir: the DMA direction + */ +void comedi_isadma_set_mode(struct comedi_isadma_desc *desc, char dma_dir) +{ + desc->mode = (dma_dir == COMEDI_ISADMA_READ) ? DMA_MODE_READ + : DMA_MODE_WRITE; +} +EXPORT_SYMBOL_GPL(comedi_isadma_set_mode); + +/** + * comedi_isadma_alloc - allocate and initialize the ISA DMA + * @dev: comedi_device struct + * @n_desc: the number of cookies to allocate + * @dma_chan: DMA channel for the first cookie + * @dma_chan2: DMA channel for the second cookie + * @maxsize: the size of the buffer to allocate for each cookie + * @dma_dir: the DMA direction + * + * Returns the allocated and initialized ISA DMA or NULL if anything fails. + */ +struct comedi_isadma *comedi_isadma_alloc(struct comedi_device *dev, + int n_desc, unsigned int dma_chan1, + unsigned int dma_chan2, + unsigned int maxsize, char dma_dir) +{ + struct comedi_isadma *dma = NULL; + struct comedi_isadma_desc *desc; + unsigned int dma_chans[2]; + int i; + + if (n_desc < 1 || n_desc > 2) + goto no_dma; + + dma = kzalloc(sizeof(*dma), GFP_KERNEL); + if (!dma) + goto no_dma; + + desc = kcalloc(n_desc, sizeof(*desc), GFP_KERNEL); + if (!desc) + goto no_dma; + dma->desc = desc; + dma->n_desc = n_desc; + + dma_chans[0] = dma_chan1; + if (dma_chan2 == 0 || dma_chan2 == dma_chan1) + dma_chans[1] = dma_chan1; + else + dma_chans[1] = dma_chan2; + + if (request_dma(dma_chans[0], dev->board_name)) + goto no_dma; + dma->chan = dma_chans[0]; + if (dma_chans[1] != dma_chans[0]) { + if (request_dma(dma_chans[1], dev->board_name)) + goto no_dma; + } + dma->chan2 = dma_chans[1]; + + for (i = 0; i < n_desc; i++) { + desc = &dma->desc[i]; + desc->chan = dma_chans[i]; + desc->maxsize = maxsize; + desc->virt_addr = dma_alloc_coherent(NULL, desc->maxsize, + &desc->hw_addr, + GFP_KERNEL); + if (!desc->virt_addr) + goto no_dma; + comedi_isadma_set_mode(desc, dma_dir); + } + + return dma; + +no_dma: + comedi_isadma_free(dma); + return NULL; +} +EXPORT_SYMBOL_GPL(comedi_isadma_alloc); + +/** + * comedi_isadma_free - free the ISA DMA + * @dma: the ISA DMA to free + */ +void comedi_isadma_free(struct comedi_isadma *dma) +{ + struct comedi_isadma_desc *desc; + int i; + + if (!dma) + return; + + if (dma->desc) { + for (i = 0; i < dma->n_desc; i++) { + desc = &dma->desc[i]; + if (desc->virt_addr) + dma_free_coherent(NULL, desc->maxsize, + desc->virt_addr, desc->hw_addr); + } + kfree(dma->desc); + } + if (dma->chan2 && dma->chan2 != dma->chan) + free_dma(dma->chan2); + if (dma->chan) + free_dma(dma->chan); + kfree(dma); +} +EXPORT_SYMBOL_GPL(comedi_isadma_free); + +static int __init comedi_isadma_init(void) +{ + return 0; +} +module_init(comedi_isadma_init); + +static void __exit comedi_isadma_exit(void) +{ +} +module_exit(comedi_isadma_exit); + +MODULE_AUTHOR("H Hartley Sweeten "); +MODULE_DESCRIPTION("Comedi ISA DMA support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/comedi_isadma.h b/drivers/staging/comedi/drivers/comedi_isadma.h new file mode 100644 index 0000000..c7c524f --- /dev/null +++ b/drivers/staging/comedi/drivers/comedi_isadma.h @@ -0,0 +1,116 @@ +/* + * COMEDI ISA DMA support functions + * Copyright (c) 2014 H Hartley Sweeten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _COMEDI_ISADMA_H +#define _COMEDI_ISADMA_H + +/* + * These are used to avoid issues when and the DMA_MODE_ + * defines are not available. + */ +#define COMEDI_ISADMA_READ 0 +#define COMEDI_ISADMA_WRITE 1 + +/** + * struct comedi_isadma_desc - cookie for ISA DMA + * @virt_addr: virtual address of buffer + * @hw_addr: hardware (bus) address of buffer + * @chan: DMA channel + * @maxsize: allocated size of buffer (in bytes) + * @size: transfer size (in bytes) + * @mode: DMA_MODE_READ or DMA_MODE_WRITE + */ +struct comedi_isadma_desc { + void *virt_addr; + dma_addr_t hw_addr; + unsigned int chan; + unsigned int maxsize; + unsigned int size; + char mode; +}; + +/** + * struct comedi_isadma - ISA DMA data + * @desc: cookie for each DMA buffer + * @n_desc: the number of cookies + * @cur_dma: the current cookie in use + * @chan: the first DMA channel requested + * @chan2: the second DMA channel requested + */ +struct comedi_isadma { + struct comedi_isadma_desc *desc; + int n_desc; + int cur_dma; + unsigned int chan; + unsigned int chan2; +}; + +#if IS_ENABLED(CONFIG_ISA_DMA_API) + +void comedi_isadma_program(struct comedi_isadma_desc *); +unsigned int comedi_isadma_disable(unsigned int dma_chan); +unsigned int comedi_isadma_disable_on_sample(unsigned int dma_chan, + unsigned int size); +unsigned int comedi_isadma_poll(struct comedi_isadma *); +void comedi_isadma_set_mode(struct comedi_isadma_desc *, char dma_dir); + +struct comedi_isadma *comedi_isadma_alloc(struct comedi_device *, + int n_desc, unsigned int dma_chan1, + unsigned int dma_chan2, + unsigned int maxsize, char dma_dir); +void comedi_isadma_free(struct comedi_isadma *); + +#else /* !IS_ENABLED(CONFIG_ISA_DMA_API) */ + +static inline void comedi_isadma_program(struct comedi_isadma_desc *desc) +{ +} + +static inline unsigned int comedi_isadma_disable(unsigned int dma_chan) +{ + return 0; +} + +static inline unsigned int +comedi_isadma_disable_on_sample(unsigned int dma_chan, unsigned int size) +{ + return 0; +} + +static inline unsigned int comedi_isadma_poll(struct comedi_isadma *dma) +{ + return 0; +} + +static inline void comedi_isadma_set_mode(struct comedi_isadma_desc *desc, + char dma_dir) +{ +} + +static inline struct comedi_isadma * +comedi_isadma_alloc(struct comedi_device *dev, int n_desc, + unsigned int dma_chan1, unsigned int dma_chan2, + unsigned int maxsize, char dma_dir) +{ + return NULL; +} + +static inline void comedi_isadma_free(struct comedi_isadma *dma) +{ +} + +#endif /* !IS_ENABLED(CONFIG_ISA_DMA_API) */ + +#endif /* #ifndef _COMEDI_ISADMA_H */ -- cgit v0.10.2 From dd7c0f04168a3faedf4a5a8ef9605ef90bdeb09c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:03 -0700 Subject: staging: comedi: pcl818: remove depends on ISA_DMA_API limitation Use the new comedi_isadma module to provide the ISA DMA support. This removes all the ISA_DMA_API code from this driver and allows the driver to be used on platforms that don't support the ISA_DMA_API. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 1e296b7..4c9e2a8 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -188,7 +188,7 @@ config COMEDI_PCL816 config COMEDI_PCL818 tristate "Advantech PCL-718 and PCL-818 ISA card support" - depends on ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for Advantech PCL-818 ISA cards PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818 and PCL-718 diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index a1279c2..1c95819 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -103,10 +103,10 @@ A word or two about DMA. Driver support DMA operations at two ways: #include #include #include -#include #include "../comedidev.h" +#include "comedi_isadma.h" #include "comedi_fc.h" #include "8253.h" @@ -302,17 +302,8 @@ static const struct pcl818_board boardtypes[] = { }, }; -struct pcl818_dma_desc { - void *virt_addr; /* virtual address of DMA buffer */ - dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ - unsigned int size; /* transfer size (in bytes) */ -}; - struct pcl818_private { - unsigned int dma; /* used DMA, 0=don't use DMA */ - unsigned int hwdmasize; - struct pcl818_dma_desc dma_desc[2]; - int cur_dma; + struct comedi_isadma *dma; long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */ unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */ unsigned int ns_min; /* manimal allowed delay between samples (in us) for actual card */ @@ -328,29 +319,6 @@ struct pcl818_private { unsigned int ai_cmd_canceled:1; }; -static void pcl818_isadma_program(unsigned int dma_chan, - struct pcl818_dma_desc *dma) -{ - unsigned long flags; - - flags = claim_dma_lock(); - clear_dma_ff(dma_chan); - set_dma_mode(dma_chan, DMA_MODE_READ); - set_dma_addr(dma_chan, dma->hw_addr); - set_dma_count(dma_chan, dma->size); - enable_dma(dma_chan); - release_dma_lock(flags); -} - -static void pcl818_isadma_disable(unsigned int dma_chan) -{ - unsigned long flags; - - flags = claim_dma_lock(); - disable_dma(dma_chan); - release_dma_lock(flags); -} - static void pcl818_start_pacer(struct comedi_device *dev, bool load_counters) { struct pcl818_private *devpriv = dev->private; @@ -370,24 +338,25 @@ static void pcl818_ai_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl818_private *devpriv = dev->private; - struct pcl818_dma_desc *dma = &devpriv->dma_desc[0]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[0]; struct comedi_cmd *cmd = &s->async->cmd; - pcl818_isadma_disable(devpriv->dma); + comedi_isadma_disable(dma->chan); if (cmd->stop_src == TRIG_COUNT) { - dma->size = cmd->stop_arg * comedi_bytes_per_scan(s); - devpriv->dma_runs_to_end = dma->size / devpriv->hwdmasize; - devpriv->last_dma_run = dma->size % devpriv->hwdmasize; + desc->size = cmd->stop_arg * comedi_bytes_per_scan(s); + devpriv->dma_runs_to_end = desc->size / desc->maxsize; + devpriv->last_dma_run = desc->size % desc->maxsize; devpriv->dma_runs_to_end--; if (devpriv->dma_runs_to_end >= 0) - dma->size = devpriv->hwdmasize; + desc->size = desc->maxsize; } else { - dma->size = devpriv->hwdmasize; + desc->size = desc->maxsize; } - devpriv->cur_dma = 0; + dma->cur_dma = 0; - pcl818_isadma_program(devpriv->dma, dma); + comedi_isadma_program(desc); } static void pcl818_ai_setup_next_dma(struct comedi_device *dev, @@ -395,19 +364,21 @@ static void pcl818_ai_setup_next_dma(struct comedi_device *dev, { struct pcl818_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - struct pcl818_dma_desc *dma; + struct comedi_isadma *dma = devpriv->dma; + + comedi_isadma_disable(dma->chan); + dma->cur_dma = 1 - dma->cur_dma; - pcl818_isadma_disable(devpriv->dma); - devpriv->cur_dma = 1 - devpriv->cur_dma; + /* switch dma bufs if still running */ if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { - /* switch dma bufs */ - dma = &devpriv->dma_desc[devpriv->cur_dma]; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + if (devpriv->dma_runs_to_end || cmd->stop_src == TRIG_NONE) - dma->size = devpriv->hwdmasize; + desc->size = desc->maxsize; else - dma->size = devpriv->last_dma_run; + desc->size = devpriv->last_dma_run; - pcl818_isadma_program(devpriv->dma, dma); + comedi_isadma_program(desc); } devpriv->dma_runs_to_end--; @@ -577,9 +548,10 @@ static void pcl818_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl818_private *devpriv = dev->private; - struct pcl818_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; - unsigned short *ptr = dma->virt_addr; - unsigned int nsamples = comedi_bytes_to_samples(s, dma->size); + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned short *ptr = desc->virt_addr; + unsigned int nsamples = comedi_bytes_to_samples(s, desc->size); unsigned int chan; unsigned int val; int i; @@ -870,12 +842,13 @@ static int pcl818_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl818_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; if (!devpriv->ai_cmd_running) return 0; - if (devpriv->dma) { + if (dma) { if (cmd->stop_src == TRIG_NONE || (cmd->stop_src == TRIG_COUNT && s->async->scans_done < cmd->stop_arg)) { @@ -888,7 +861,7 @@ static int pcl818_ai_cancel(struct comedi_device *dev, return 0; } } - pcl818_isadma_disable(devpriv->dma); + comedi_isadma_disable(dma->chan); } outb(PCL818_CTRL_DISABLE_TRIG, dev->iobase + PCL818_CTRL_REG); @@ -1070,49 +1043,25 @@ static void pcl818_set_ai_range_table(struct comedi_device *dev, } } -static int pcl818_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) +static void pcl818_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) { struct pcl818_private *devpriv = dev->private; - struct pcl818_dma_desc *dma; - int i; + /* only DMA channels 3 and 1 are valid */ if (!(dma_chan == 3 || dma_chan == 1)) - return 0; - - if (request_dma(dma_chan, dev->board_name)) - return 0; - devpriv->dma = dma_chan; - - devpriv->hwdmasize = PAGE_SIZE * 4; /* we need 16KB */ - - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; + return; - dma->virt_addr = dma_alloc_coherent(NULL, devpriv->hwdmasize, - &dma->hw_addr, GFP_KERNEL); - if (!dma->virt_addr) - return -ENOMEM; - } - return 0; + /* DMA uses two 16K buffers */ + devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan, + PAGE_SIZE * 4, COMEDI_ISADMA_READ); } static void pcl818_free_dma(struct comedi_device *dev) { struct pcl818_private *devpriv = dev->private; - struct pcl818_dma_desc *dma; - int i; - if (!devpriv) - return; - - if (devpriv->dma) - free_dma(devpriv->dma); - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; - if (dma->virt_addr) - dma_free_coherent(NULL, devpriv->hwdmasize, - dma->virt_addr, dma->hw_addr); - } + if (devpriv) + comedi_isadma_free(devpriv->dma); } static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) @@ -1144,11 +1093,8 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->usefifo = 1; /* we need an IRQ to do DMA on channel 3 or 1 */ - if (dev->irq && board->has_dma) { - ret = pcl818_alloc_dma(dev, it->options[2]); - if (ret) - return ret; - } + if (dev->irq && board->has_dma) + pcl818_alloc_dma(dev, it->options[2]); ret = comedi_alloc_subdevices(dev, 4); if (ret) -- cgit v0.10.2 From bd7ea421e3f9750deecdf78af94c8191ef05788d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:04 -0700 Subject: staging: comedi: pcl816: remove depends on ISA_DMA_API limitation Use the new comedi_isadma module to provide the ISA DMA support. This removes all the ISA_DMA_API code from this driver and allows the driver to be used on platforms that don't support the ISA_DMA_API. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 4c9e2a8..1ed797b 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -179,7 +179,7 @@ config COMEDI_PCL812 config COMEDI_PCL816 tristate "Advantech PCL-814 and PCL-816 ISA card support" - depends on ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for Advantech PCL-814 and PCL-816 ISA cards diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index d2ce775..09fa409 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -33,14 +33,14 @@ Configuration Options: */ #include -#include "../comedidev.h" - #include #include #include #include -#include +#include "../comedidev.h" + +#include "comedi_isadma.h" #include "comedi_fc.h" #include "8253.h" @@ -113,17 +113,8 @@ static const struct pcl816_board boardtypes[] = { }, }; -struct pcl816_dma_desc { - void *virt_addr; /* virtual address of DMA buffer */ - dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ - unsigned int size; /* transfer size (in bytes) */ -}; - struct pcl816_private { - unsigned int dma; /* used DMA, 0=don't use DMA */ - unsigned int hwdmasize; - struct pcl816_dma_desc dma_desc[2]; - int cur_dma; + struct comedi_isadma *dma; long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */ unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */ unsigned int ai_poll_ptr; /* how many sampes transfer poll */ @@ -133,29 +124,6 @@ struct pcl816_private { unsigned int ai_cmd_canceled:1; }; -static void pcl816_isadma_program(unsigned int dma_chan, - struct pcl816_dma_desc *dma) -{ - unsigned long flags; - - flags = claim_dma_lock(); - clear_dma_ff(dma_chan); - set_dma_mode(dma_chan, DMA_MODE_READ); - set_dma_addr(dma_chan, dma->hw_addr); - set_dma_count(dma_chan, dma->size); - enable_dma(dma_chan); - release_dma_lock(flags); -} - -static void pcl816_isadma_disable(unsigned int dma_chan) -{ - unsigned long flags; - - flags = claim_dma_lock(); - disable_dma(dma_chan); - release_dma_lock(flags); -} - static void pcl816_start_pacer(struct comedi_device *dev, bool load_counters) { struct pcl816_private *devpriv = dev->private; @@ -179,29 +147,30 @@ static void pcl816_ai_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl816_private *devpriv = dev->private; - struct pcl816_dma_desc *dma = &devpriv->dma_desc[0]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[0]; struct comedi_cmd *cmd = &s->async->cmd; if (cmd->stop_src == TRIG_COUNT) { /* how many */ - dma->size = cmd->stop_arg * comedi_bytes_per_scan(s); + desc->size = cmd->stop_arg * comedi_bytes_per_scan(s); /* how many DMA pages we must fill */ - devpriv->dma_runs_to_end = dma->size / devpriv->hwdmasize; + devpriv->dma_runs_to_end = desc->size / desc->maxsize; /* on last dma transfer must be moved */ - devpriv->last_dma_run = dma->size % devpriv->hwdmasize; + devpriv->last_dma_run = desc->size % desc->maxsize; devpriv->dma_runs_to_end--; if (devpriv->dma_runs_to_end >= 0) - dma->size = devpriv->hwdmasize; + desc->size = desc->maxsize; } else { - dma->size = devpriv->hwdmasize; + desc->size = desc->maxsize; devpriv->dma_runs_to_end = -1; } - devpriv->cur_dma = 0; + dma->cur_dma = 0; - pcl816_isadma_program(devpriv->dma, dma); + comedi_isadma_program(desc); } static void pcl816_ai_setup_next_dma(struct comedi_device *dev, @@ -209,19 +178,21 @@ static void pcl816_ai_setup_next_dma(struct comedi_device *dev, { struct pcl816_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - struct pcl816_dma_desc *dma; + struct comedi_isadma *dma = devpriv->dma; + + comedi_isadma_disable(dma->chan); + dma->cur_dma = 1 - dma->cur_dma; - pcl816_isadma_disable(devpriv->dma); + /* switch dma bufs if still running */ if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { - /* switch dma bufs */ - devpriv->cur_dma = 1 - devpriv->cur_dma; - dma = &devpriv->dma_desc[devpriv->cur_dma]; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + if (devpriv->dma_runs_to_end) - dma->size = devpriv->hwdmasize; + desc->size = desc->maxsize; else - dma->size = devpriv->last_dma_run; + desc->size = devpriv->last_dma_run; - pcl816_isadma_program(devpriv->dma, dma); + comedi_isadma_program(desc); } devpriv->dma_runs_to_end--; @@ -337,7 +308,8 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) struct comedi_device *dev = d; struct comedi_subdevice *s = dev->read_subdev; struct pcl816_private *devpriv = dev->private; - struct pcl816_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; unsigned int nsamples; unsigned int bufptr; @@ -354,11 +326,12 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) pcl816_ai_setup_next_dma(dev, s); - nsamples = comedi_bytes_to_samples(s, dma->size) - devpriv->ai_poll_ptr; + nsamples = comedi_bytes_to_samples(s, desc->size) - + devpriv->ai_poll_ptr; bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; - transfer_from_dma_buf(dev, s, dma->virt_addr, bufptr, nsamples); + transfer_from_dma_buf(dev, s, desc->virt_addr, bufptr, nsamples); pcl816_ai_clear_eoc(dev); @@ -500,6 +473,7 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev, static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl816_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; unsigned int ctrl; unsigned int seglen; @@ -530,7 +504,8 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ctrl |= PCL816_CTRL_EXT_TRIG; outb(ctrl, dev->iobase + PCL816_CTRL_REG); - outb((devpriv->dma << 4) | dev->irq, dev->iobase + PCL816_STATUS_REG); + outb((dma->chan << 4) | dev->irq, + dev->iobase + PCL816_STATUS_REG); return 0; } @@ -538,41 +513,34 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl816_private *devpriv = dev->private; - struct pcl816_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc; unsigned long flags; - unsigned int top1, top2, i; + unsigned int poll; + int ret; spin_lock_irqsave(&dev->spinlock, flags); - for (i = 0; i < 20; i++) { - top1 = get_dma_residue(devpriv->dma); /* where is now DMA */ - top2 = get_dma_residue(devpriv->dma); - if (top1 == top2) - break; - } - if (top1 != top2) { - spin_unlock_irqrestore(&dev->spinlock, flags); - return 0; - } - - /* where is now DMA in buffer */ - top1 = dma->size - top1; - top1 >>= 1; /* sample position */ - top2 = top1 - devpriv->ai_poll_ptr; - if (top2 < 1) { /* no new samples */ - spin_unlock_irqrestore(&dev->spinlock, flags); - return 0; - } + poll = comedi_isadma_poll(dma); + poll = comedi_bytes_to_samples(s, poll); + if (poll > devpriv->ai_poll_ptr) { + desc = &dma->desc[dma->cur_dma]; + transfer_from_dma_buf(dev, s, desc->virt_addr, + devpriv->ai_poll_ptr, + poll - devpriv->ai_poll_ptr); + /* new buffer position */ + devpriv->ai_poll_ptr = poll; - transfer_from_dma_buf(dev, s, dma->virt_addr, - devpriv->ai_poll_ptr, top2); + comedi_handle_events(dev, s); - devpriv->ai_poll_ptr = top1; /* new buffer position */ + ret = comedi_buf_n_bytes_ready(s); + } else { + /* no new samples */ + ret = 0; + } spin_unlock_irqrestore(&dev->spinlock, flags); - comedi_handle_events(dev, s); - - return comedi_buf_n_bytes_ready(s); + return ret; } static int pcl816_ai_cancel(struct comedi_device *dev, @@ -673,68 +641,36 @@ static void pcl816_reset(struct comedi_device *dev) outb(0, dev->iobase + PCL816_DO_DI_MSB_REG); } -static int pcl816_alloc_dma(struct comedi_device *dev, - unsigned int irq_num, unsigned int dma_chan) +static void pcl816_alloc_irq_and_dma(struct comedi_device *dev, + struct comedi_devconfig *it) { struct pcl816_private *devpriv = dev->private; - struct pcl816_dma_desc *dma; - int i; + unsigned int irq_num = it->options[1]; + unsigned int dma_chan = it->options[2]; - /* - * Only IRQs 2-7 are valid. - * Only DMA channels 3 and 1 are valid. - * - * Both must be valid for async command support. - */ + /* only IRQs 2-7 and DMA channels 3 and 1 are valid */ if (!(irq_num >= 2 && irq_num <= 7) || !(dma_chan == 3 || dma_chan == 1)) - return 0; + return; - /* - * Request the IRQ and DMA channels and allocate the DMA buffers. - * If the requests or allocations fail async command supprt will - * not be available. - */ if (request_irq(irq_num, pcl816_interrupt, 0, dev->board_name, dev)) - return 0; - if (request_dma(dma_chan, dev->board_name)) { - free_irq(irq_num, dev); - return 0; - } - - dev->irq = irq_num; - devpriv->dma = dma_chan; - - devpriv->hwdmasize = PAGE_SIZE * 4; /* we need 16KB */ - - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; + return; - dma->virt_addr = dma_alloc_coherent(NULL, devpriv->hwdmasize, - &dma->hw_addr, GFP_KERNEL); - if (!dma->virt_addr) - return -ENOMEM; - } - return 0; + /* DMA uses two 16K buffers */ + devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan, + PAGE_SIZE * 4, COMEDI_ISADMA_READ); + if (!devpriv->dma) + free_irq(irq_num, dev); + else + dev->irq = irq_num; } static void pcl816_free_dma(struct comedi_device *dev) { struct pcl816_private *devpriv = dev->private; - struct pcl816_dma_desc *dma; - int i; - if (!devpriv) - return; - - if (devpriv->dma) - free_dma(devpriv->dma); - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; - if (dma->virt_addr) - dma_free_coherent(NULL, devpriv->hwdmasize, - dma->virt_addr, dma->hw_addr); - } + if (devpriv) + comedi_isadma_free(devpriv->dma); } static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) @@ -752,14 +688,8 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - /* - * An IRQ and DMA are required to support async commands. - * pcl816_alloc_dma() will only fail if the DMA buffers - * cannot be allocated. - */ - ret = pcl816_alloc_dma(dev, it->options[1], it->options[2]); - if (ret) - return ret; + /* an IRQ and DMA are required to support async commands */ + pcl816_alloc_irq_and_dma(dev, it); ret = comedi_alloc_subdevices(dev, 4); if (ret) -- cgit v0.10.2 From f3df482a0cf410a17b306f6b4437ab102c4085e0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:05 -0700 Subject: staging: comedi: pcl812: remove depends on ISA_DMA_API limitation Use the new comedi_isadma module to provide the ISA DMA support. This removes all the ISA_DMA_API code from this driver and allows the driver to be used on platforms that don't support the ISA_DMA_API. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 1ed797b..1b8c690 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -168,7 +168,7 @@ config COMEDI_PCL730 config COMEDI_PCL812 tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216" - depends on ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216, ICP DAS A-821PGH/PGL/PGL-NDA, diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index c67c2c7..134b26e 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -111,12 +111,12 @@ #include #include #include -#include "../comedidev.h" - #include #include -#include +#include "../comedidev.h" + +#include "comedi_isadma.h" #include "comedi_fc.h" #include "8253.h" @@ -506,21 +506,12 @@ static const struct pcl812_board boardtypes[] = { }, }; -struct pcl812_dma_desc { - void *virt_addr; /* virtual address of DMA buffer */ - dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ - unsigned int size; /* transfer size (in bytes) */ -}; - struct pcl812_private { - unsigned char dma; /* >0 use dma ( usedDMA channel) */ + struct comedi_isadma *dma; unsigned char range_correction; /* =1 we must add 1 to range number */ unsigned int last_ai_chanspec; unsigned char mode_reg_int; /* there is stored INT number for some card */ unsigned int ai_poll_ptr; /* how many sampes transfer poll */ - unsigned int hwdmasize; - struct pcl812_dma_desc dma_desc[2]; - int cur_dma; unsigned int dma_runs_to_end; /* how many times we must switch DMA buffers */ unsigned int last_dma_run; /* how many bytes to transfer on last DMA buffer */ unsigned int max_812_ai_mode0_rangewait; /* setling time for gain */ @@ -533,29 +524,6 @@ struct pcl812_private { unsigned int ai_eos:1; }; -static void pcl812_isadma_program(unsigned int dma_chan, - struct pcl812_dma_desc *dma) -{ - unsigned long flags; - - flags = claim_dma_lock(); - clear_dma_ff(dma_chan); - set_dma_mode(dma_chan, DMA_MODE_READ); - set_dma_addr(dma_chan, dma->hw_addr); - set_dma_count(dma_chan, dma->size); - enable_dma(dma_chan); - release_dma_lock(flags); -} - -static void pcl812_isadma_disable(unsigned int dma_chan) -{ - unsigned long flags; - - flags = claim_dma_lock(); - disable_dma(dma_chan); - release_dma_lock(flags); -} - static void pcl812_start_pacer(struct comedi_device *dev, bool load_timers) { struct pcl812_private *devpriv = dev->private; @@ -575,23 +543,24 @@ static void pcl812_ai_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; - struct pcl812_dma_desc *dma0 = &devpriv->dma_desc[0]; - struct pcl812_dma_desc *dma1 = &devpriv->dma_desc[1]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc0 = &dma->desc[0]; + struct comedi_isadma_desc *desc1 = &dma->desc[1]; struct comedi_cmd *cmd = &s->async->cmd; unsigned int bytes; /* we use EOS, so adapt DMA buffer to one scan */ if (devpriv->ai_eos) { - dma0->size = comedi_bytes_per_scan(s); - dma1->size = comedi_bytes_per_scan(s); + desc0->size = comedi_bytes_per_scan(s); + desc1->size = comedi_bytes_per_scan(s); devpriv->dma_runs_to_end = 1; } else { - dma0->size = devpriv->hwdmasize; - dma1->size = devpriv->hwdmasize; - if (s->async->prealloc_bufsz < devpriv->hwdmasize) { - dma0->size = s->async->prealloc_bufsz; - dma1->size = s->async->prealloc_bufsz; - } + desc0->size = desc0->maxsize; + desc1->size = desc1->maxsize; + if (s->async->prealloc_bufsz < desc0->maxsize) + desc0->size = s->async->prealloc_bufsz; + if (s->async->prealloc_bufsz < desc1->maxsize) + desc1->size = s->async->prealloc_bufsz; if (cmd->stop_src == TRIG_NONE) { devpriv->dma_runs_to_end = 1; } else { @@ -599,46 +568,47 @@ static void pcl812_ai_setup_dma(struct comedi_device *dev, bytes = cmd->stop_arg * comedi_bytes_per_scan(s); /* how many DMA pages we must fill */ - devpriv->dma_runs_to_end = bytes / dma0->size; + devpriv->dma_runs_to_end = bytes / desc0->size; /* on last dma transfer must be moved */ - devpriv->last_dma_run = bytes % dma0->size; + devpriv->last_dma_run = bytes % desc0->size; if (devpriv->dma_runs_to_end == 0) - dma0->size = devpriv->last_dma_run; + desc0->size = devpriv->last_dma_run; devpriv->dma_runs_to_end--; } } - if (dma0->size > devpriv->hwdmasize) { - dma0->size = devpriv->hwdmasize; + if (desc0->size > desc0->maxsize) { + desc0->size = desc0->maxsize; devpriv->ai_eos = 0; } - if (dma1->size > devpriv->hwdmasize) { - dma1->size = devpriv->hwdmasize; + if (desc1->size > desc1->maxsize) { + desc1->size = desc1->maxsize; devpriv->ai_eos = 0; } - devpriv->cur_dma = 0; + dma->cur_dma = 0; - pcl812_isadma_program(devpriv->dma, dma0); + comedi_isadma_program(desc0); } static void pcl812_ai_setup_next_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; - struct pcl812_dma_desc *dma; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc; - pcl812_isadma_disable(devpriv->dma); + comedi_isadma_disable(dma->chan); + dma->cur_dma = 1 - dma->cur_dma; - devpriv->cur_dma = 1 - devpriv->cur_dma; - dma = &devpriv->dma_desc[devpriv->cur_dma]; + desc = &dma->desc[dma->cur_dma]; if (!devpriv->ai_eos) { if (devpriv->dma_runs_to_end) devpriv->dma_runs_to_end--; else - dma->size = devpriv->last_dma_run; + desc->size = devpriv->last_dma_run; } - pcl812_isadma_program(devpriv->dma, dma); + comedi_isadma_program(desc); } static void pcl812_ai_set_chan_range(struct comedi_device *dev, @@ -904,17 +874,19 @@ static void pcl812_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; - struct pcl812_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; unsigned int nsamples; int bufptr; pcl812_ai_setup_next_dma(dev, s); - nsamples = comedi_bytes_to_samples(s, dma->size) - devpriv->ai_poll_ptr; + nsamples = comedi_bytes_to_samples(s, desc->size) - + devpriv->ai_poll_ptr; bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; - transfer_from_dma_buf(dev, s, dma->virt_addr, bufptr, nsamples); + transfer_from_dma_buf(dev, s, desc->virt_addr, bufptr, nsamples); } static irqreturn_t pcl812_interrupt(int irq, void *d) @@ -942,45 +914,37 @@ static irqreturn_t pcl812_interrupt(int irq, void *d) static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; - struct pcl812_dma_desc *dma; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc; unsigned long flags; - unsigned int top1, top2, i; + unsigned int poll; + int ret; + /* poll is valid only for DMA transfer */ if (!devpriv->ai_dma) - return 0; /* poll is valid only for DMA transfer */ + return 0; spin_lock_irqsave(&dev->spinlock, flags); - for (i = 0; i < 10; i++) { - /* where is now DMA */ - top1 = get_dma_residue(devpriv->ai_dma); - top2 = get_dma_residue(devpriv->ai_dma); - if (top1 == top2) - break; - } - - if (top1 != top2) { - spin_unlock_irqrestore(&dev->spinlock, flags); - return 0; - } - /* where is now DMA in buffer */ - dma = &devpriv->dma_desc[1 - devpriv->cur_dma]; - top1 = dma->size - top1; - top1 >>= 1; /* sample position */ - top2 = top1 - devpriv->ai_poll_ptr; - if (top2 < 1) { /* no new samples */ - spin_unlock_irqrestore(&dev->spinlock, flags); - return 0; + poll = comedi_isadma_poll(dma); + poll = comedi_bytes_to_samples(s, poll); + if (poll > devpriv->ai_poll_ptr) { + desc = &dma->desc[dma->cur_dma]; + transfer_from_dma_buf(dev, s, desc->virt_addr, + devpriv->ai_poll_ptr, + poll - devpriv->ai_poll_ptr); + /* new buffer position */ + devpriv->ai_poll_ptr = poll; + + ret = comedi_buf_n_bytes_ready(s); + } else { + /* no new samples */ + ret = 0; } - transfer_from_dma_buf(dev, s, dma->virt_addr, - devpriv->ai_poll_ptr, top2); - - devpriv->ai_poll_ptr = top1; /* new buffer position */ - spin_unlock_irqrestore(&dev->spinlock, flags); - return comedi_buf_n_bytes_ready(s); + return ret; } static int pcl812_ai_cancel(struct comedi_device *dev, @@ -989,7 +953,7 @@ static int pcl812_ai_cancel(struct comedi_device *dev, struct pcl812_private *devpriv = dev->private; if (devpriv->ai_dma) - pcl812_isadma_disable(devpriv->dma); + comedi_isadma_disable(devpriv->dma->chan); outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG, dev->iobase + PCL812_CTRL_REG); @@ -1199,49 +1163,25 @@ static void pcl812_set_ai_range_table(struct comedi_device *dev, } } -static int pcl812_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) +static void pcl812_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) { struct pcl812_private *devpriv = dev->private; - struct pcl812_dma_desc *dma; - int i; + /* only DMA channels 3 and 1 are valid */ if (!(dma_chan == 3 || dma_chan == 1)) - return 0; - - if (request_dma(dma_chan, dev->board_name)) - return 0; - devpriv->dma = dma_chan; - - devpriv->hwdmasize = PAGE_SIZE * 2; /* we want 8KB */ - - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; + return; - dma->virt_addr = dma_alloc_coherent(NULL, devpriv->hwdmasize, - &dma->hw_addr, GFP_KERNEL); - if (!dma->virt_addr) - return -ENOMEM; - } - return 0; + /* DMA uses two 8K buffers */ + devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan, + PAGE_SIZE * 2, COMEDI_ISADMA_READ); } static void pcl812_free_dma(struct comedi_device *dev) { struct pcl812_private *devpriv = dev->private; - struct pcl812_dma_desc *dma; - int i; - if (!devpriv) - return; - - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; - if (dma->virt_addr) - dma_free_coherent(NULL, devpriv->hwdmasize, - dma->virt_addr, dma->hw_addr); - } - if (devpriv->dma) - free_dma(devpriv->dma); + if (devpriv) + comedi_isadma_free(devpriv->dma); } static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) @@ -1269,11 +1209,8 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* we need an IRQ to do DMA on channel 3 or 1 */ - if (dev->irq && board->has_dma) { - ret = pcl812_alloc_dma(dev, it->options[2]); - if (ret) - return ret; - } + if (dev->irq && board->has_dma) + pcl812_alloc_dma(dev, it->options[2]); /* differential analog inputs? */ switch (board->board_type) { -- cgit v0.10.2 From 1400964a2b5c2fcf6d713148bc7ad7707935f3d6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:06 -0700 Subject: staging: comedi: das16: remove depends on ISA_DMA_API limitation Use the new comedi_isadma module to provide the ISA DMA support. This removes all the ISA_DMA_API code from this driver and allows the driver to be used on platforms that don't support the ISA_DMA_API. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 1b8c690..199c027 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -281,7 +281,7 @@ config COMEDI_DAS08_ISA config COMEDI_DAS16 tristate "DAS-16 compatible ISA and PC/104 card support" - depends on ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API select COMEDI_8255 ---help--- Enable support for Keithley Metrabyte/ComputerBoards DAS16 diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 09d65fc..466d4ef 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -71,16 +71,14 @@ #include #include -#include #include -#include - #include "../comedidev.h" +#include "comedi_isadma.h" +#include "comedi_fc.h" #include "8253.h" #include "8255.h" -#include "comedi_fc.h" #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */ @@ -438,21 +436,13 @@ static inline int timer_period(void) return HZ / 20; } -struct das16_dma_desc { - uint16_t *virt_addr; /* virtual address of DMA buffer */ - dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ - unsigned int size; /* transfer size (in bytes) */ -}; - struct das16_private_struct { + struct comedi_isadma *dma; unsigned int clockbase; unsigned int ctrl_reg; unsigned long adc_byte_count; unsigned int divisor1; unsigned int divisor2; - unsigned int dma_chan; - struct das16_dma_desc dma_desc[2]; - unsigned int cur_dma; struct comedi_lrange *user_ai_range_table; struct comedi_lrange *user_ao_range_table; struct timer_list timer; @@ -461,33 +451,6 @@ struct das16_private_struct { unsigned int can_burst:1; }; -static void das16_isadma_program(unsigned int dma_chan, - struct das16_dma_desc *dma) -{ - unsigned long flags; - - flags = claim_dma_lock(); - clear_dma_ff(dma_chan); - set_dma_mode(dma_chan, DMA_MODE_READ); - set_dma_addr(dma_chan, dma->hw_addr); - set_dma_count(dma_chan, dma->size); - enable_dma(dma_chan); - release_dma_lock(flags); -} - -static unsigned int das16_isadma_disable(unsigned int dma_chan) -{ - unsigned long flags; - unsigned int residue; - - flags = claim_dma_lock(); - disable_dma(dma_chan); - residue = get_dma_residue(dma_chan); - release_dma_lock(flags); - - return residue; -} - static void das16_ai_enable(struct comedi_device *dev, unsigned int mode, unsigned int src) { @@ -516,51 +479,14 @@ static void das16_ai_disable(struct comedi_device *dev) outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); } -/* the pc104-das16jr (at least) has problems if the dma - transfer is interrupted in the middle of transferring - a 16 bit sample, so this function takes care to get - an even transfer count after disabling dma - channel. -*/ -static int disable_dma_on_even(struct comedi_device *dev) -{ - struct das16_private_struct *devpriv = dev->private; - static const int disable_limit = 100; - static const int enable_timeout = 100; - unsigned long flags; - unsigned int residue; - int new_residue; - int i; - int j; - - residue = das16_isadma_disable(devpriv->dma_chan); - for (i = 0; i < disable_limit && (residue % 2); ++i) { - flags = claim_dma_lock(); - enable_dma(devpriv->dma_chan); - for (j = 0; j < enable_timeout; ++j) { - udelay(2); - new_residue = get_dma_residue(devpriv->dma_chan); - release_dma_lock(flags); - if (new_residue != residue) - break; - } - residue = das16_isadma_disable(devpriv->dma_chan); - } - if (i == disable_limit) { - dev_err(dev->class_dev, - "failed to get an even dma transfer, could be trouble\n"); - } - return residue; -} - static void das16_interrupt(struct comedi_device *dev) { struct das16_private_struct *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - struct das16_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; - struct das16_dma_desc *nxt_dma; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; unsigned long spin_flags; unsigned int nsamples; int num_bytes, residue; @@ -571,15 +497,21 @@ static void das16_interrupt(struct comedi_device *dev) return; } - residue = disable_dma_on_even(dev); + /* + * The pc104-das16jr (at least) has problems if the dma + * transfer is interrupted in the middle of transferring + * a 16 bit sample. + */ + residue = comedi_isadma_disable_on_sample(desc->chan, + comedi_bytes_per_sample(s)); /* figure out how many points to read */ - if (residue > dma->size) { + if (residue > desc->size) { dev_err(dev->class_dev, "residue > transfer size!\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; num_bytes = 0; } else - num_bytes = dma->size - residue; + num_bytes = desc->size - residue; if (cmd->stop_src == TRIG_COUNT && num_bytes >= devpriv->adc_byte_count) { @@ -587,20 +519,21 @@ static void das16_interrupt(struct comedi_device *dev) async->events |= COMEDI_CB_EOA; } - devpriv->cur_dma = 1 - devpriv->cur_dma; + dma->cur_dma = 1 - dma->cur_dma; devpriv->adc_byte_count -= num_bytes; /* re-enable dma */ if ((async->events & COMEDI_CB_EOA) == 0) { - nxt_dma = &devpriv->dma_desc[devpriv->cur_dma]; - nxt_dma->size = DAS16_DMA_SIZE; - das16_isadma_program(devpriv->dma_chan, nxt_dma); + struct comedi_isadma_desc *nxt_desc = &dma->desc[dma->cur_dma]; + + nxt_desc->size = nxt_desc->maxsize; + comedi_isadma_program(nxt_desc); } spin_unlock_irqrestore(&dev->spinlock, spin_flags); nsamples = comedi_bytes_to_samples(s, num_bytes); - comedi_buf_write_samples(s, dma->virt_addr, nsamples); + comedi_buf_write_samples(s, desc->virt_addr, nsamples); comedi_handle_events(dev, s); } @@ -771,7 +704,8 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) { const struct das16_board *board = dev->board_ptr; struct das16_private_struct *devpriv = dev->private; - struct das16_dma_desc *dma = &devpriv->dma_desc[0]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[0]; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned int byte; @@ -821,9 +755,9 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) outb(byte, dev->iobase + DAS16_PACER_REG); /* set up dma transfer */ - devpriv->cur_dma = 0; - dma->size = DAS16_DMA_SIZE; - das16_isadma_program(devpriv->dma_chan, dma); + dma->cur_dma = 0; + desc->size = desc->maxsize; + comedi_isadma_program(desc); /* set up timer */ spin_lock_irqsave(&dev->spinlock, flags); @@ -843,12 +777,13 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct das16_private_struct *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); das16_ai_disable(dev); - disable_dma(devpriv->dma_chan); + comedi_isadma_disable(dma->chan); /* disable SW timer */ if (devpriv->timer_running) { @@ -1007,53 +942,33 @@ static void das16_reset(struct comedi_device *dev) outb(0, dev->iobase + DAS16_TIMER_BASE_REG + i8254_control_reg); } -static int das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) +static void das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan) { struct das16_private_struct *devpriv = dev->private; - struct das16_dma_desc *dma; - int i; + /* only DMA channels 3 and 1 are valid */ if (!(dma_chan == 1 || dma_chan == 3)) - return 0; - - if (request_dma(dma_chan, dev->board_name)) - return 0; - devpriv->dma_chan = dma_chan; - - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; + return; - dma->virt_addr = dma_alloc_coherent(NULL, DAS16_DMA_SIZE, - &dma->hw_addr, GFP_KERNEL); - if (!dma->virt_addr) - return -ENOMEM; + /* DMA uses two buffers */ + devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan, + DAS16_DMA_SIZE, COMEDI_ISADMA_READ); + if (devpriv->dma) { + init_timer(&devpriv->timer); + devpriv->timer.function = das16_timer_interrupt; + devpriv->timer.data = (unsigned long)dev; } - - das16_isadma_disable(devpriv->dma_chan); - - init_timer(&devpriv->timer); - devpriv->timer.function = das16_timer_interrupt; - devpriv->timer.data = (unsigned long)dev; - - return 0; } static void das16_free_dma(struct comedi_device *dev) { struct das16_private_struct *devpriv = dev->private; - struct das16_dma_desc *dma; - int i; - if (devpriv->timer.data) - del_timer_sync(&devpriv->timer); - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; - if (dma->virt_addr) - dma_free_coherent(NULL, DAS16_DMA_SIZE, - dma->virt_addr, dma->hw_addr); + if (devpriv) { + if (devpriv->timer.data) + del_timer_sync(&devpriv->timer); + comedi_isadma_free(devpriv->dma); } - if (devpriv->dma_chan) - free_dma(devpriv->dma_chan); } static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) @@ -1117,9 +1032,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->clockbase = I8254_OSC_BASE_1MHZ; } - ret = das16_alloc_dma(dev, it->options[2]); - if (ret) - return ret; + das16_alloc_dma(dev, it->options[2]); /* get any user-defined input range */ if (board->ai_pg == das16_pg_none && @@ -1181,7 +1094,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = das16_ai_bip_lranges[board->ai_pg]; } s->insn_read = das16_ai_insn_read; - if (devpriv->dma_chan) { + if (devpriv->dma) { dev->read_subdev = s; s->subdev_flags |= SDF_CMD_READ; s->do_cmdtest = das16_cmd_test; -- cgit v0.10.2 From 99dfc3357e9889f247f052ae7c8596084faf7a81 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:07 -0700 Subject: staging: comedi: das1800: remove depends on ISA_DMA_API limitation Use the new comedi_isadma module to provide the ISA DMA support. This removes all the ISA_DMA_API code from this driver and allows the driver to be used on platforms that don't support the ISA_DMA_API. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 199c027..5fd0aa6 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -309,7 +309,7 @@ config COMEDI_DAS800 config COMEDI_DAS1800 tristate "DAS1800 and compatible ISA card support" - depends on ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for DAS1800 and compatible ISA cards Keithley Metrabyte DAS-1701ST, DAS-1701ST-DA, DAS-1701/AO, diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 5be5162..381ae94 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -98,12 +98,12 @@ TODO: #include #include #include -#include "../comedidev.h" -#include +#include "../comedidev.h" -#include "8253.h" +#include "comedi_isadma.h" #include "comedi_fc.h" +#include "8253.h" /* misc. defines */ #define DAS1800_SIZE 16 /* uses 16 io addresses */ @@ -420,22 +420,14 @@ static const struct das1800_board das1800_boards[] = { }, }; -struct das1800_dma_desc { - unsigned int chan; /* DMA channel */ - void *virt_addr; /* virtual address of DMA buffer */ - dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ - unsigned int size; /* transfer size (in bytes) */ -}; - struct das1800_private { + struct comedi_isadma *dma; unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */ unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */ int irq_dma_bits; /* bits for control register b */ /* dma bits for control register b, stored so that dma can be * turned on and off */ int dma_bits; - struct das1800_dma_desc dma_desc[2]; - int cur_dma; uint16_t *fifo_buf; /* bounce buffer for analog input FIFO */ unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */ unsigned short ao_update_bits; /* remembers the last write to the @@ -452,32 +444,6 @@ static const struct comedi_lrange range_ao_2 = { }; */ -static void das1800_isadma_program(struct das1800_dma_desc *dma) -{ - unsigned long flags; - - flags = claim_dma_lock(); - clear_dma_ff(dma->chan); - set_dma_mode(dma->chan, DMA_MODE_READ); - set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, dma->size); - enable_dma(dma->chan); - release_dma_lock(flags); -} - -static unsigned int das1800_isadma_disable(unsigned int dma_chan) -{ - unsigned long flags; - unsigned int residue; - - flags = claim_dma_lock(); - disable_dma(dma_chan); - residue = get_dma_residue(dma_chan); - release_dma_lock(flags); - - return residue; -} - static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev, uint16_t sample) { @@ -540,18 +506,18 @@ static void das1800_handle_fifo_not_empty(struct comedi_device *dev, /* Utility function used by das1800_flush_dma() and das1800_handle_dma() */ static void das1800_flush_dma_channel(struct comedi_device *dev, struct comedi_subdevice *s, - struct das1800_dma_desc *dma) + struct comedi_isadma_desc *desc) { - unsigned int residue = das1800_isadma_disable(dma->chan); - unsigned int nbytes = dma->size - residue; + unsigned int residue = comedi_isadma_disable(desc->chan); + unsigned int nbytes = desc->size - residue; unsigned int nsamples; /* figure out how many points to read */ nsamples = comedi_bytes_to_samples(s, nbytes); nsamples = comedi_nsamples_left(s, nsamples); - munge_data(dev, dma->virt_addr, nsamples); - comedi_buf_write_samples(s, dma->virt_addr, nsamples); + munge_data(dev, desc->virt_addr, nsamples); + comedi_buf_write_samples(s, desc->virt_addr, nsamples); } /* flushes remaining data from board when external trigger has stopped acquisition @@ -560,16 +526,17 @@ static void das1800_flush_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; - struct das1800_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; - das1800_flush_dma_channel(dev, s, dma); + das1800_flush_dma_channel(dev, s, desc); if (dual_dma) { /* switch to other channel and flush it */ - devpriv->cur_dma = 1 - devpriv->cur_dma; - dma = &devpriv->dma_desc[devpriv->cur_dma]; - das1800_flush_dma_channel(dev, s, dma); + dma->cur_dma = 1 - dma->cur_dma; + desc = &dma->desc[dma->cur_dma]; + das1800_flush_dma_channel(dev, s, desc); } /* get any remaining samples in fifo */ @@ -580,27 +547,29 @@ static void das1800_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int status) { struct das1800_private *devpriv = dev->private; - struct das1800_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; - das1800_flush_dma_channel(dev, s, dma); + das1800_flush_dma_channel(dev, s, desc); /* re-enable dma channel */ - das1800_isadma_program(dma); + comedi_isadma_program(desc); if (status & DMATC) { /* clear DMATC interrupt bit */ outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS); /* switch dma channels for next time, if appropriate */ if (dual_dma) - devpriv->cur_dma = 1 - devpriv->cur_dma; + dma->cur_dma = 1 - dma->cur_dma; } } static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; - struct das1800_dma_desc *dma; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc; int i; outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */ @@ -608,9 +577,9 @@ static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */ for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; - if (dma->chan) - das1800_isadma_disable(dma->chan); + desc = &dma->desc[i]; + if (desc->chan) + comedi_isadma_disable(desc->chan); } return 0; @@ -968,10 +937,11 @@ static void das1800_setup_counters(struct comedi_device *dev, static unsigned int das1800_ai_transfer_size(struct comedi_device *dev, struct comedi_subdevice *s, + unsigned int maxbytes, unsigned int ns) { struct comedi_cmd *cmd = &s->async->cmd; - unsigned int max_samples = comedi_bytes_to_samples(s, DMA_BUF_SIZE); + unsigned int max_samples = comedi_bytes_to_samples(s, maxbytes); unsigned int samples; samples = max_samples; @@ -1002,25 +972,26 @@ static void das1800_ai_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; - struct das1800_dma_desc *dma = &devpriv->dma_desc[0]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[0]; unsigned int bytes; if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0) return; - devpriv->cur_dma = 0; + dma->cur_dma = 0; /* determine a dma transfer size to fill buffer in 0.3 sec */ - bytes = das1800_ai_transfer_size(dev, s, 300000000); + bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000); - dma->size = bytes; - das1800_isadma_program(dma); + desc->size = bytes; + comedi_isadma_program(desc); /* set up dual dma if appropriate */ if (devpriv->irq_dma_bits & DMA_DUAL) { - dma = &devpriv->dma_desc[1]; - dma->size = bytes; - das1800_isadma_program(dma); + desc = &dma->desc[1]; + desc->size = bytes; + comedi_isadma_program(desc); } } @@ -1220,13 +1191,11 @@ static int das1800_do_wbits(struct comedi_device *dev, return insn->n; } -static int das1800_init_dma(struct comedi_device *dev, - struct comedi_devconfig *it) +static void das1800_init_dma(struct comedi_device *dev, + struct comedi_devconfig *it) { struct das1800_private *devpriv = dev->private; - struct das1800_dma_desc *dma; unsigned int *dma_chan; - int i; /* * it->options[2] is DMA channel 0 @@ -1238,75 +1207,41 @@ static int das1800_init_dma(struct comedi_device *dev, switch ((dma_chan[0] & 0x7) | (dma_chan[1] << 4)) { case 0x5: /* dma0 == 5 */ - devpriv->dma_bits |= DMA_CH5; + devpriv->dma_bits = DMA_CH5; break; case 0x6: /* dma0 == 6 */ - devpriv->dma_bits |= DMA_CH6; + devpriv->dma_bits = DMA_CH6; break; case 0x7: /* dma0 == 7 */ - devpriv->dma_bits |= DMA_CH7; + devpriv->dma_bits = DMA_CH7; break; case 0x65: /* dma0 == 5, dma1 == 6 */ - devpriv->dma_bits |= DMA_CH5_CH6; + devpriv->dma_bits = DMA_CH5_CH6; break; case 0x76: /* dma0 == 6, dma1 == 7 */ - devpriv->dma_bits |= DMA_CH6_CH7; + devpriv->dma_bits = DMA_CH6_CH7; break; case 0x57: /* dma0 == 7, dma1 == 5 */ - devpriv->dma_bits |= DMA_CH7_CH5; + devpriv->dma_bits = DMA_CH7_CH5; break; default: - dev_err(dev->class_dev, - "only supports dma channels 5 through 7\n"); - dev_err(dev->class_dev, - "Dual dma only allows the following combinations:\n"); - dev_err(dev->class_dev, - "dma 5,6 / 6,7 / or 7,5\n"); - return -EINVAL; - } - - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; - - if (dma_chan[i] == 0) - break; - - if (request_dma(dma_chan[i], dev->board_name)) { - dev_err(dev->class_dev, - "failed to allocate dma channel %i\n", - dma_chan[i]); - return -EINVAL; - } - dma->chan = dma_chan[i]; - - dma->virt_addr = dma_alloc_coherent(NULL, DMA_BUF_SIZE, - &dma->hw_addr, GFP_KERNEL); - if (!dma->virt_addr) - return -ENOMEM; - - das1800_isadma_disable(dma->chan); + return; } - return 0; + /* DMA can use 1 or 2 buffers, each with a separate channel */ + devpriv->dma = comedi_isadma_alloc(dev, dma_chan[1] ? 2 : 1, + dma_chan[0], dma_chan[1], + DMA_BUF_SIZE, COMEDI_ISADMA_READ); + if (!devpriv->dma) + devpriv->dma_bits = 0; } static void das1800_free_dma(struct comedi_device *dev) { struct das1800_private *devpriv = dev->private; - struct das1800_dma_desc *dma; - int i; - - if (!devpriv) - return; - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; - if (dma->chan) - free_dma(dma->chan); - if (dma->virt_addr) - dma_free_coherent(NULL, DMA_BUF_SIZE, - dma->virt_addr, dma->hw_addr); - } + if (devpriv) + comedi_isadma_free(devpriv->dma); } static int das1800_probe(struct comedi_device *dev) @@ -1436,11 +1371,8 @@ static int das1800_attach(struct comedi_device *dev, } /* an irq and one dma channel is required to use dma */ - if (dev->irq & it->options[2]) { - ret = das1800_init_dma(dev, it); - if (ret < 0) - return ret; - } + if (dev->irq & it->options[2]) + das1800_init_dma(dev, it); devpriv->fifo_buf = kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL); if (!devpriv->fifo_buf) -- cgit v0.10.2 From 860f7c0919a05a1c1cdf3247f0a905851e526c36 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:08 -0700 Subject: staging: comedi: dt282x: remove depends on ISA_DMA_API limitation Use the new comedi_isadma module to provide the ISA DMA support. This removes all the ISA_DMA_API code from this driver and allows the driver to be used on platforms that don't support the ISA_DMA_API. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 5fd0aa6..e66b72d 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -372,7 +372,7 @@ config COMEDI_DT2817 config COMEDI_DT282X tristate "Data Translation DT2821 series and DT-EZ ISA card support" - depends on ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for Data Translation DT2821 series including DT-EZ DT2821, DT2821-F-16SE, DT2821-F-8DI, DT2821-G-16SE, DT2821-G-8DI, diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 54c679a..051dfb2 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -56,15 +56,14 @@ */ #include -#include "../comedidev.h" - #include #include #include #include -#include +#include "../comedidev.h" +#include "comedi_isadma.h" #include "comedi_fc.h" /* @@ -300,72 +299,37 @@ static const struct dt282x_board boardtypes[] = { }, }; -struct dt282x_dma_desc { - unsigned int chan; /* DMA channel */ - void *virt_addr; /* virtual address of DMA buffer */ - dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ - unsigned int size; /* transfer size (in bytes) */ - char mode; /* DMA_MODE_* */ -}; - struct dt282x_private { + struct comedi_isadma *dma; unsigned int ad_2scomp:1; - unsigned int divisor; - int dacsr; /* software copies of registers */ int adcsr; int supcsr; - int ntrig; int nread; - - struct dt282x_dma_desc dma_desc[2]; - int dma_maxsize; /* max size of DMA transfer (in bytes) */ - int cur_dma; int dma_dir; }; -static void dt282x_isadma_program(struct dt282x_dma_desc *dma) -{ - unsigned long flags; - - flags = claim_dma_lock(); - clear_dma_ff(dma->chan); - set_dma_mode(dma->chan, dma->mode); - set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, dma->size); - enable_dma(dma->chan); - release_dma_lock(flags); -} - -static void dt282x_isadma_disable(struct dt282x_dma_desc *dma) -{ - unsigned long flags; - - flags = claim_dma_lock(); - disable_dma(dma->chan); - release_dma_lock(flags); -} - static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) { struct dt282x_private *devpriv = dev->private; - struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma_index]; if (!devpriv->ntrig) return 0; if (n == 0) - n = devpriv->dma_maxsize; + n = desc->maxsize; if (n > devpriv->ntrig * 2) n = devpriv->ntrig * 2; devpriv->ntrig -= n / 2; - dma->size = n; - dma->mode = DMA_MODE_READ; + desc->size = n; + comedi_isadma_set_mode(desc, devpriv->dma_dir); - dt282x_isadma_program(dma); + comedi_isadma_program(desc); return n; } @@ -373,12 +337,13 @@ static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n) static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) { struct dt282x_private *devpriv = dev->private; - struct dt282x_dma_desc *dma = &devpriv->dma_desc[dma_index]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma_index]; - dma->size = n; - dma->mode = DMA_MODE_WRITE; + desc->size = n; + comedi_isadma_set_mode(desc, devpriv->dma_dir); - dt282x_isadma_program(dma); + comedi_isadma_program(desc); return n; } @@ -386,10 +351,14 @@ static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n) static void dt282x_disable_dma(struct comedi_device *dev) { struct dt282x_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc; int i; - for (i = 0; i < 2; i++) - dt282x_isadma_disable(&devpriv->dma_desc[i]); + for (i = 0; i < 2; i++) { + desc = &dma->desc[i]; + comedi_isadma_disable(desc->chan); + } } static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags) @@ -451,11 +420,12 @@ static unsigned int dt282x_ao_setup_dma(struct comedi_device *dev, int cur_dma) { struct dt282x_private *devpriv = dev->private; - struct dt282x_dma_desc *dma = &devpriv->dma_desc[cur_dma]; - unsigned int nsamples = comedi_bytes_to_samples(s, devpriv->dma_maxsize); + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[cur_dma]; + unsigned int nsamples = comedi_bytes_to_samples(s, desc->maxsize); unsigned int nbytes; - nbytes = comedi_buf_read_samples(s, dma->virt_addr, nsamples); + nbytes = comedi_buf_read_samples(s, desc->virt_addr, nsamples); if (nbytes) dt282x_prep_ao_dma(dev, cur_dma, nbytes); else @@ -468,35 +438,37 @@ static void dt282x_ao_dma_interrupt(struct comedi_device *dev, struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; - struct dt282x_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, dev->iobase + DT2821_SUPCSR_REG); - dt282x_isadma_disable(dma); + comedi_isadma_disable(desc->chan); - if (!dt282x_ao_setup_dma(dev, s, devpriv->cur_dma)) + if (!dt282x_ao_setup_dma(dev, s, dma->cur_dma)) s->async->events |= COMEDI_CB_OVERFLOW; - devpriv->cur_dma = 1 - devpriv->cur_dma; + dma->cur_dma = 1 - dma->cur_dma; } static void dt282x_ai_dma_interrupt(struct comedi_device *dev, struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; - struct dt282x_dma_desc *dma = &devpriv->dma_desc[devpriv->cur_dma]; - unsigned int nsamples = comedi_bytes_to_samples(s, dma->size); + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned int nsamples = comedi_bytes_to_samples(s, desc->size); int ret; outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE, dev->iobase + DT2821_SUPCSR_REG); - dt282x_isadma_disable(dma); + comedi_isadma_disable(desc->chan); - dt282x_munge(dev, s, dma->virt_addr, dma->size); - ret = comedi_buf_write_samples(s, dma->virt_addr, nsamples); - if (ret != dma->size) + dt282x_munge(dev, s, desc->virt_addr, desc->size); + ret = comedi_buf_write_samples(s, desc->virt_addr, nsamples); + if (ret != desc->size) return; devpriv->nread -= nsamples; @@ -517,9 +489,9 @@ static void dt282x_ai_dma_interrupt(struct comedi_device *dev, } #endif /* restart the channel */ - dt282x_prep_ai_dma(dev, devpriv->cur_dma, 0); + dt282x_prep_ai_dma(dev, dma->cur_dma, 0); - devpriv->cur_dma = 1 - devpriv->cur_dma; + dma->cur_dma = 1 - dma->cur_dma; } static irqreturn_t dt282x_interrupt(int irq, void *d) @@ -540,7 +512,7 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) dacsr = inw(dev->iobase + DT2821_DACSR_REG); supcsr = inw(dev->iobase + DT2821_SUPCSR_REG); if (supcsr & DT2821_SUPCSR_DMAD) { - if (devpriv->dma_dir == DMA_MODE_READ) + if (devpriv->dma_dir == COMEDI_ISADMA_READ) dt282x_ai_dma_interrupt(dev, s); else dt282x_ao_dma_interrupt(dev, s_ao); @@ -752,6 +724,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; int ret; @@ -773,8 +746,8 @@ static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg; devpriv->nread = devpriv->ntrig; - devpriv->dma_dir = DMA_MODE_READ; - devpriv->cur_dma = 0; + devpriv->dma_dir = COMEDI_ISADMA_READ; + dma->cur_dma = 0; dt282x_prep_ai_dma(dev, 0, 0); if (devpriv->ntrig) { dt282x_prep_ai_dma(dev, 1, 0); @@ -937,6 +910,7 @@ static int dt282x_ao_inttrig(struct comedi_device *dev, static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct dt282x_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; dt282x_disable_dma(dev); @@ -953,8 +927,8 @@ static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len; devpriv->nread = devpriv->ntrig; - devpriv->dma_dir = DMA_MODE_WRITE; - devpriv->cur_dma = 0; + devpriv->dma_dir = COMEDI_ISADMA_WRITE; + dma->cur_dma = 0; outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG); @@ -1058,13 +1032,12 @@ static const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x) return ai_range_table[x]; } -static int dt282x_alloc_dma(struct comedi_device *dev, - struct comedi_devconfig *it) +static void dt282x_alloc_dma(struct comedi_device *dev, + struct comedi_devconfig *it) { struct dt282x_private *devpriv = dev->private; unsigned int irq_num = it->options[1]; unsigned int dma_chan[2]; - int i; if (it->options[2] < it->options[3]) { dma_chan[0] = it->options[2]; @@ -1077,53 +1050,24 @@ static int dt282x_alloc_dma(struct comedi_device *dev, if (!irq_num || dma_chan[0] == dma_chan[1] || dma_chan[0] < 5 || dma_chan[0] > 7 || dma_chan[1] < 5 || dma_chan[1] > 7) - return 0; + return; if (request_irq(irq_num, dt282x_interrupt, 0, dev->board_name, dev)) - return 0; - if (request_dma(dma_chan[0], dev->board_name)) { - free_irq(irq_num, dev); - return 0; - } - if (request_dma(dma_chan[1], dev->board_name)) { - free_dma(dma_chan[0]); - free_irq(irq_num, dev); - return 0; - } - - dev->irq = irq_num; - - devpriv->dma_maxsize = PAGE_SIZE; - for (i = 0; i < 2; i++) { - struct dt282x_dma_desc *dma = &devpriv->dma_desc[i]; - - dma->chan = dma_chan[i]; - dma->virt_addr = dma_alloc_coherent(NULL, devpriv->dma_maxsize, - &dma->hw_addr, GFP_KERNEL); - if (!dma->virt_addr) - return -ENOMEM; - } + return; - return 0; + /* DMA uses two 4K buffers with separate DMA channels */ + devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan[0], dma_chan[1], + PAGE_SIZE, 0); + if (!devpriv->dma) + free_irq(irq_num, dev); } static void dt282x_free_dma(struct comedi_device *dev) { struct dt282x_private *devpriv = dev->private; - struct dt282x_dma_desc *dma; - int i; - if (!devpriv) - return; - - for (i = 0; i < 2; i++) { - dma = &devpriv->dma_desc[i]; - if (dma->chan) - free_dma(dma->chan); - if (dma->virt_addr) - dma_free_coherent(NULL, devpriv->dma_maxsize, - dma->virt_addr, dma->hw_addr); - } + if (devpriv) + comedi_isadma_free(devpriv->dma); } static int dt282x_initialize(struct comedi_device *dev) @@ -1181,9 +1125,7 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -ENOMEM; /* an IRQ and 2 DMA channels are required for async command support */ - ret = dt282x_alloc_dma(dev, it); - if (ret) - return ret; + dt282x_alloc_dma(dev, it); ret = comedi_alloc_subdevices(dev, 3); if (ret) -- cgit v0.10.2 From 1a97f144e3d3e9d7efc5c0837bed016da9ae43c7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:09 -0700 Subject: staging: comedi: ni_at_a2150: remove depends on ISA_DMA_API limitation Use the new comedi_isadma module to provide the ISA DMA support. This removes all the ISA_DMA_API code from this driver and allows the driver to be used on platforms that don't support the ISA_DMA_API. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index e66b72d..8cbebac 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -462,7 +462,7 @@ config COMEDI_ADQ12B config COMEDI_NI_AT_A2150 tristate "NI AT-A2150 ISA card support" - depends on ISA_DMA_API + select COMEDI_ISADMA if ISA_DMA_API ---help--- Enable support for National Instruments AT-A2150 cards diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 73768d0..2500148 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -62,14 +62,13 @@ TRIG_WAKE_EOS #include #include #include -#include "../comedidev.h" - #include -#include +#include "../comedidev.h" -#include "8253.h" +#include "comedi_isadma.h" #include "comedi_fc.h" +#include "8253.h" #define A2150_DMA_BUFFER_SIZE 0xff00 /* size in bytes of dma buffer */ @@ -145,85 +144,42 @@ static const struct a2150_board a2150_boards[] = { }, }; -struct a2150_dma_desc { - unsigned int chan; /* DMA channel */ - void *virt_addr; /* virtual address of DMA buffer */ - dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ - unsigned int size; /* size of DMA transfer (in bytes) */ -}; - struct a2150_private { - struct a2150_dma_desc dma_desc; + struct comedi_isadma *dma; unsigned int count; /* number of data points left to be taken */ int irq_dma_bits; /* irq/dma register bits */ int config_bits; /* config register bits */ }; -static void a2150_isadma_program(struct a2150_dma_desc *dma) -{ - unsigned long flags; - - flags = claim_dma_lock(); - clear_dma_ff(dma->chan); - set_dma_mode(dma->chan, DMA_MODE_READ); - set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, dma->size); - enable_dma(dma->chan); - release_dma_lock(flags); -} - -static unsigned int a2150_isadma_disable(struct a2150_dma_desc *dma) -{ - unsigned long flags; - unsigned int residue; - - flags = claim_dma_lock(); - disable_dma(dma->chan); - residue = get_dma_residue(dma->chan); - release_dma_lock(flags); - - return residue; -} - /* interrupt service routine */ static irqreturn_t a2150_interrupt(int irq, void *d) { - int i; - int status; struct comedi_device *dev = d; struct a2150_private *devpriv = dev->private; - struct a2150_dma_desc *dma = &devpriv->dma_desc; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[0]; struct comedi_subdevice *s = dev->read_subdev; - struct comedi_async *async; - struct comedi_cmd *cmd; - unsigned short *buf = dma->virt_addr; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned short *buf = desc->virt_addr; unsigned int max_points, num_points, residue, leftover; unsigned short dpnt; + int status; + int i; - if (!dev->attached) { - dev_err(dev->class_dev, "premature interrupt\n"); + if (!dev->attached) return IRQ_HANDLED; - } - /* initialize async here to make sure s is not NULL */ - async = s->async; - cmd = &async->cmd; status = inw(dev->iobase + STATUS_REG); - - if ((status & INTR_BIT) == 0) { - dev_err(dev->class_dev, "spurious interrupt\n"); + if ((status & INTR_BIT) == 0) return IRQ_NONE; - } if (status & OVFL_BIT) { - dev_err(dev->class_dev, "fifo overflow\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; comedi_handle_events(dev, s); } if ((status & DMA_TC_BIT) == 0) { - dev_err(dev->class_dev, - "caught non-dma interrupt? Aborting.\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; comedi_handle_events(dev, s); return IRQ_HANDLED; @@ -234,10 +190,10 @@ static irqreturn_t a2150_interrupt(int irq, void *d) * transfer. It should always be zero at this point unless * the stop_src is set to external triggering. */ - residue = a2150_isadma_disable(dma); + residue = comedi_isadma_disable(desc->chan); /* figure out how many points to read */ - max_points = comedi_bytes_to_samples(s, dma->size); + max_points = comedi_bytes_to_samples(s, desc->size); num_points = max_points - comedi_bytes_to_samples(s, residue); if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT) num_points = devpriv->count; @@ -245,7 +201,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) /* figure out how many points will be stored next time */ leftover = 0; if (cmd->stop_src == TRIG_NONE) { - leftover = comedi_bytes_to_samples(s, dma->size); + leftover = comedi_bytes_to_samples(s, desc->size); } else if (devpriv->count > max_points) { leftover = devpriv->count - max_points; if (leftover > max_points) @@ -273,8 +229,8 @@ static irqreturn_t a2150_interrupt(int irq, void *d) } /* re-enable dma */ if (leftover) { - dma->size = comedi_samples_to_bytes(s, leftover); - a2150_isadma_program(dma); + desc->size = comedi_samples_to_bytes(s, leftover); + comedi_isadma_program(desc); } comedi_handle_events(dev, s); @@ -288,14 +244,15 @@ static irqreturn_t a2150_interrupt(int irq, void *d) static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct a2150_private *devpriv = dev->private; - struct a2150_dma_desc *dma = &devpriv->dma_desc; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[0]; /* disable dma on card */ devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT; outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG); /* disable computer's dma */ - a2150_isadma_disable(dma); + comedi_isadma_disable(desc->chan); /* clear fifo and reset triggering circuitry */ outw(0, dev->iobase + FIFO_RESET_REG); @@ -527,7 +484,8 @@ static int a2150_ai_cmdtest(struct comedi_device *dev, static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct a2150_private *devpriv = dev->private; - struct a2150_dma_desc *dma = &devpriv->dma_desc; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[0]; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned long timer_base = dev->iobase + I8253_BASE_REG; @@ -566,19 +524,19 @@ static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* initialize number of samples remaining */ devpriv->count = cmd->stop_arg * cmd->chanlist_len; - a2150_isadma_disable(dma); + comedi_isadma_disable(desc->chan); /* set size of transfer to fill in 1/3 second */ #define ONE_THIRD_SECOND 333333333 - dma->size = comedi_bytes_per_sample(s) * cmd->chanlist_len * + desc->size = comedi_bytes_per_sample(s) * cmd->chanlist_len * ONE_THIRD_SECOND / cmd->scan_begin_arg; - if (dma->size > A2150_DMA_BUFFER_SIZE) - dma->size = A2150_DMA_BUFFER_SIZE; - if (dma->size < comedi_bytes_per_sample(s)) - dma->size = comedi_bytes_per_sample(s); - dma->size -= dma->size % comedi_bytes_per_sample(s); + if (desc->size > desc->maxsize) + desc->size = desc->maxsize; + if (desc->size < comedi_bytes_per_sample(s)) + desc->size = comedi_bytes_per_sample(s); + desc->size -= desc->size % comedi_bytes_per_sample(s); - a2150_isadma_program(dma); + comedi_isadma_program(desc); /* clear dma interrupt before enabling it, to try and get rid of that * one spurious interrupt that has been happening */ @@ -693,64 +651,43 @@ static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return n; } -static void a2150_alloc_irq_dma(struct comedi_device *dev, - struct comedi_devconfig *it) +static void a2150_alloc_irq_and_dma(struct comedi_device *dev, + struct comedi_devconfig *it) { struct a2150_private *devpriv = dev->private; - struct a2150_dma_desc *dma = &devpriv->dma_desc; unsigned int irq_num = it->options[1]; unsigned int dma_chan = it->options[2]; /* * Only IRQs 15, 14, 12-9, and 7-3 are valid. * Only DMA channels 7-5 and 3-0 are valid. - * - * Both must be valid for async command support. */ if (irq_num > 15 || dma_chan > 7 || !((1 << irq_num) & 0xdef8) || !((1 << dma_chan) & 0xef)) return; - /* - * Request the IRQ and DMA channels and allocate the DMA buffer. - * If the requests or allocation fail async command supprt will - * not be available. - */ if (request_irq(irq_num, a2150_interrupt, 0, dev->board_name, dev)) return; - if (request_dma(dma_chan, dev->board_name)) { - free_irq(irq_num, dev); - return; - } - dma->virt_addr = dma_alloc_coherent(NULL, A2150_DMA_BUFFER_SIZE, - &dma->hw_addr, GFP_KERNEL); - if (!dma->virt_addr) { - free_dma(dma_chan); + + /* DMA uses 1 buffer */ + devpriv->dma = comedi_isadma_alloc(dev, 1, dma_chan, dma_chan, + A2150_DMA_BUFFER_SIZE, + COMEDI_ISADMA_READ); + if (!devpriv->dma) { free_irq(irq_num, dev); - return; + } else { + dev->irq = irq_num; + devpriv->irq_dma_bits = IRQ_LVL_BITS(irq_num) | + DMA_CHAN_BITS(dma_chan); } - - dev->irq = irq_num; - dma->chan = dma_chan; - devpriv->irq_dma_bits = IRQ_LVL_BITS(irq_num) | DMA_CHAN_BITS(dma_chan); - - a2150_isadma_disable(dma); } static void a2150_free_dma(struct comedi_device *dev) { struct a2150_private *devpriv = dev->private; - struct a2150_dma_desc *dma; - - if (!devpriv) - return; - dma = &devpriv->dma_desc; - if (dma->chan) - free_dma(dma->chan); - if (dma->virt_addr) - dma_free_coherent(NULL, A2150_DMA_BUFFER_SIZE, - dma->virt_addr, dma->hw_addr); + if (devpriv) + comedi_isadma_free(devpriv->dma); } /* probes board type, returns offset */ @@ -786,7 +723,8 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) thisboard = dev->board_ptr; dev->board_name = thisboard->name; - a2150_alloc_irq_dma(dev, it); + /* an IRQ and DMA are required to support async commands */ + a2150_alloc_irq_and_dma(dev, it); ret = comedi_alloc_subdevices(dev, 1); if (ret) -- cgit v0.10.2 From cf0438c9c3da2f243961561d1e3742519b2eeb3d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:10 -0700 Subject: staging: comedi: ni_labpc_isadma: use comedi_isdma module The labpc driver has already had the depends on ISA_DMA_API limitation removed by moving all the DMA support code into the labpc_isadma module. For aesthetics, use the comedi_isadma module to provide the actual ISA DMA support. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 8cbebac..593fcb1 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -1271,6 +1271,7 @@ config COMEDI_NI_LABPC config COMEDI_NI_LABPC_ISADMA tristate + select COMEDI_ISADMA config COMEDI_NI_TIO tristate diff --git a/drivers/staging/comedi/drivers/ni_labpc.h b/drivers/staging/comedi/drivers/ni_labpc.h index c26d7ee..be89ae4 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.h +++ b/drivers/staging/comedi/drivers/ni_labpc.h @@ -34,14 +34,9 @@ struct labpc_boardinfo { unsigned is_labpc1200:1; /* has extra regs compared to pc+ */ }; -struct labpc_dma_desc { - unsigned int chan; /* DMA channel */ - void *virt_addr; /* virtual address of DMA buffer */ - dma_addr_t hw_addr; /* hardware (bus) address of DMA buffer */ - unsigned int size; /* size of DMA transfer (in bytes) */ -}; - struct labpc_private { + struct comedi_isadma *dma; + /* number of data points left to be taken */ unsigned long long count; /* software copys of bits written to command registers */ @@ -69,8 +64,6 @@ struct labpc_private { */ unsigned int divisor_b1; - struct labpc_dma_desc dma_desc; - /* we are using dma/fifo-half-full/etc. */ enum transfer_type current_transfer; /* diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index d89d585..eea7f94 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -687,7 +687,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } /* figure out what method we will use to transfer data */ - if (labpc_have_dma_chan(dev) && + if (devpriv->dma && /* dma unsafe at RT priority, * and too much setup time for CMDF_WAKE_EOS */ (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY)) == 0) diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 3100549..6b4ccd8 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -19,10 +19,10 @@ #include #include -#include "../comedidev.h" -#include +#include "../comedidev.h" +#include "comedi_isadma.h" #include "comedi_fc.h" #include "ni_labpc.h" #include "ni_labpc_regs.h" @@ -31,35 +31,10 @@ /* size in bytes of dma buffer */ #define LABPC_ISADMA_BUFFER_SIZE 0xff00 -static void labpc_isadma_program(struct labpc_dma_desc *dma) -{ - unsigned long flags; - - flags = claim_dma_lock(); - clear_dma_ff(dma->chan); - set_dma_mode(dma->chan, DMA_MODE_READ); - set_dma_addr(dma->chan, dma->hw_addr); - set_dma_count(dma->chan, dma->size); - enable_dma(dma->chan); - release_dma_lock(flags); -} - -static unsigned int labpc_isadma_disable(struct labpc_dma_desc *dma) -{ - unsigned long flags; - unsigned int residue; - - flags = claim_dma_lock(); - disable_dma(dma->chan); - residue = get_dma_residue(dma->chan); - release_dma_lock(flags); - - return residue; -} - /* utility function that suggests a dma transfer size in bytes */ static unsigned int labpc_suggest_transfer_size(struct comedi_device *dev, - struct comedi_subdevice *s) + struct comedi_subdevice *s, + unsigned int maxbytes) { struct comedi_cmd *cmd = &s->async->cmd; unsigned int sample_size = comedi_bytes_per_sample(s); @@ -76,8 +51,8 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_device *dev, size = (freq / 3) * sample_size; /* set a minimum and maximum size allowed */ - if (size > LABPC_ISADMA_BUFFER_SIZE) - size = LABPC_ISADMA_BUFFER_SIZE; + if (size > maxbytes) + size = maxbytes; else if (size < sample_size) size = sample_size; @@ -87,17 +62,17 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_device *dev, void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) { struct labpc_private *devpriv = dev->private; - struct labpc_dma_desc *dma = &devpriv->dma_desc; + struct comedi_isadma_desc *desc = &devpriv->dma->desc[0]; struct comedi_cmd *cmd = &s->async->cmd; unsigned int sample_size = comedi_bytes_per_sample(s); /* set appropriate size of transfer */ - dma->size = labpc_suggest_transfer_size(dev, s); + desc->size = labpc_suggest_transfer_size(dev, s, desc->maxsize); if (cmd->stop_src == TRIG_COUNT && - devpriv->count * sample_size < dma->size) - dma->size = devpriv->count * sample_size; + devpriv->count * sample_size < desc->size) + desc->size = devpriv->count * sample_size; - labpc_isadma_program(dma); + comedi_isadma_program(desc); /* set CMD3 bits for caller to enable DMA and interrupt */ devpriv->cmd3 |= (CMD3_DMAEN | CMD3_DMATCINTEN); @@ -107,11 +82,11 @@ EXPORT_SYMBOL_GPL(labpc_setup_dma); void labpc_drain_dma(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; - struct labpc_dma_desc *dma = &devpriv->dma_desc; + struct comedi_isadma_desc *desc = &devpriv->dma->desc[0]; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - unsigned int max_samples = comedi_bytes_to_samples(s, dma->size); + unsigned int max_samples = comedi_bytes_to_samples(s, desc->size); unsigned int residue; unsigned int nsamples; unsigned int leftover; @@ -121,7 +96,7 @@ void labpc_drain_dma(struct comedi_device *dev) * transfer. It should always be zero at this point unless * the stop_src is set to external triggering. */ - residue = labpc_isadma_disable(dma); + residue = comedi_isadma_disable(desc->chan); /* * Figure out how many samples to read for this transfer and @@ -141,21 +116,21 @@ void labpc_drain_dma(struct comedi_device *dev) } else { leftover = max_samples; } - dma->size = comedi_samples_to_bytes(s, leftover); + desc->size = comedi_samples_to_bytes(s, leftover); - comedi_buf_write_samples(s, dma->virt_addr, nsamples); + comedi_buf_write_samples(s, desc->virt_addr, nsamples); } EXPORT_SYMBOL_GPL(labpc_drain_dma); static void handle_isa_dma(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; - struct labpc_dma_desc *dma = &devpriv->dma_desc; + struct comedi_isadma_desc *desc = &devpriv->dma->desc[0]; labpc_drain_dma(dev); - if (dma->size) - labpc_isadma_program(dma); + if (desc->size) + comedi_isadma_program(desc); /* clear dma tc interrupt */ devpriv->write_byte(dev, 0x1, DMATC_CLEAR_REG); @@ -179,37 +154,24 @@ EXPORT_SYMBOL_GPL(labpc_handle_dma_status); void labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) { struct labpc_private *devpriv = dev->private; - struct labpc_dma_desc *dma = &devpriv->dma_desc; + /* only DMA channels 3 and 1 are valid */ if (dma_chan != 1 && dma_chan != 3) return; - if (request_dma(dma_chan, dev->board_name)) - return; - - dma->virt_addr = dma_alloc_coherent(NULL, LABPC_ISADMA_BUFFER_SIZE, - &dma->hw_addr, GFP_KERNEL); - if (!dma->virt_addr) { - free_dma(dma_chan); - return; - } - - dma->chan = dma_chan; - - labpc_isadma_disable(dma); + /* DMA uses 1 buffer */ + devpriv->dma = comedi_isadma_alloc(dev, 1, dma_chan, dma_chan, + LABPC_ISADMA_BUFFER_SIZE, + COMEDI_ISADMA_READ); } EXPORT_SYMBOL_GPL(labpc_init_dma_chan); void labpc_free_dma_chan(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; - struct labpc_dma_desc *dma = &devpriv->dma_desc; - if (dma->virt_addr) - dma_free_coherent(NULL, LABPC_ISADMA_BUFFER_SIZE, - dma->virt_addr, dma->hw_addr); - if (dma->chan) - free_dma(dma->chan); + if (devpriv) + comedi_isadma_free(devpriv->dma); } EXPORT_SYMBOL_GPL(labpc_free_dma_chan); diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h index 8f062f7..b8a1b0e 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.h +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h @@ -5,16 +5,7 @@ #ifndef _NI_LABPC_ISADMA_H #define _NI_LABPC_ISADMA_H -#define NI_LABPC_HAVE_ISA_DMA IS_ENABLED(CONFIG_COMEDI_NI_LABPC_ISADMA) - -#if NI_LABPC_HAVE_ISA_DMA - -static inline bool labpc_have_dma_chan(struct comedi_device *dev) -{ - struct labpc_private *devpriv = dev->private; - - return (bool)devpriv->dma_desc.chan; -} +#if IS_ENABLED(CONFIG_COMEDI_NI_LABPC_ISADMA) void labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan); void labpc_free_dma_chan(struct comedi_device *dev); @@ -24,11 +15,6 @@ void labpc_handle_dma_status(struct comedi_device *dev); #else -static inline bool labpc_have_dma_chan(struct comedi_device *dev) -{ - return false; -} - static inline void labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) { -- cgit v0.10.2 From 296e3f1816dbdb5f1c3213386756e362263b17b5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:11 -0700 Subject: staging: comedi: pcl818: simplify the dma->size calculations Currently this driver determines the number of DMA "runs" needed and the size of the "last" DMA transfer in order to perform a command. As long as there are more "runs" required, the dma->size is set to the buffer maxsize. On the last "run" the buffer is set to the "last" size. Refactor the driver to use the comedi core helpers to determine the DMA size based on the buffer maxsize and the number of samples remaining in the command. This allows removing the 'dma_runs_to_end' and 'last_dma_run' mamebers from the private data. Also remove the 'ai_data_len' member which is set but never used. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 1c95819..fa7b4e2 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -304,14 +304,11 @@ static const struct pcl818_board boardtypes[] = { struct pcl818_private { struct comedi_isadma *dma; - long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */ - unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */ unsigned int ns_min; /* manimal allowed delay between samples (in us) for actual card */ int i8253_osc_base; /* 1/frequency of on board oscilator in ns */ unsigned int act_chanlist[16]; /* MUX setting for actual AI operations */ unsigned int act_chanlist_len; /* how long is actual MUX list */ unsigned int act_chanlist_pos; /* actual position in MUX list */ - unsigned int ai_data_len; /* len of data buffer */ unsigned int divisor1; unsigned int divisor2; unsigned int usefifo:1; @@ -340,48 +337,49 @@ static void pcl818_ai_setup_dma(struct comedi_device *dev, struct pcl818_private *devpriv = dev->private; struct comedi_isadma *dma = devpriv->dma; struct comedi_isadma_desc *desc = &dma->desc[0]; - struct comedi_cmd *cmd = &s->async->cmd; + unsigned int nsamples; comedi_isadma_disable(dma->chan); - if (cmd->stop_src == TRIG_COUNT) { - desc->size = cmd->stop_arg * comedi_bytes_per_scan(s); - devpriv->dma_runs_to_end = desc->size / desc->maxsize; - devpriv->last_dma_run = desc->size % desc->maxsize; - devpriv->dma_runs_to_end--; - if (devpriv->dma_runs_to_end >= 0) - desc->size = desc->maxsize; - } else { - desc->size = desc->maxsize; - } dma->cur_dma = 0; + /* + * Determine dma size based on the buffer maxsize and the number of + * samples remaining in the command. + */ + nsamples = comedi_bytes_to_samples(s, desc->maxsize); + nsamples = comedi_nsamples_left(s, nsamples); + desc->size = comedi_samples_to_bytes(s, nsamples); comedi_isadma_program(desc); } static void pcl818_ai_setup_next_dma(struct comedi_device *dev, - struct comedi_subdevice *s) + struct comedi_subdevice *s, + unsigned int unread_samples) { struct pcl818_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc; + unsigned int max_samples; + unsigned int nsamples; comedi_isadma_disable(dma->chan); - dma->cur_dma = 1 - dma->cur_dma; - - /* switch dma bufs if still running */ - if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { - struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; - - if (devpriv->dma_runs_to_end || cmd->stop_src == TRIG_NONE) - desc->size = desc->maxsize; - else - desc->size = devpriv->last_dma_run; + dma->cur_dma = 1 - dma->cur_dma; + desc = &dma->desc[dma->cur_dma]; + + /* + * Determine dma size based on the buffer maxsize plus the number of + * unread samples and the number of samples remaining in the command. + */ + max_samples = comedi_bytes_to_samples(s, desc->maxsize); + nsamples = max_samples + unread_samples; + nsamples = comedi_nsamples_left(s, nsamples); + if (nsamples > unread_samples) { + nsamples -= unread_samples; + desc->size = comedi_samples_to_bytes(s, nsamples); comedi_isadma_program(desc); } - - devpriv->dma_runs_to_end--; } static void pcl818_ai_set_chan_range(struct comedi_device *dev, @@ -556,7 +554,7 @@ static void pcl818_handle_dma(struct comedi_device *dev, unsigned int val; int i; - pcl818_ai_setup_next_dma(dev, s); + pcl818_ai_setup_next_dma(dev, s, nsamples); for (i = 0; i < nsamples; i++) { val = ptr[i]; @@ -806,11 +804,9 @@ static int pcl818_ai_cmd(struct comedi_device *dev, return -EINVAL; pcl818_ai_setup_chanlist(dev, cmd->chanlist, seglen); - devpriv->ai_data_len = s->async->prealloc_bufsz; devpriv->ai_cmd_running = 1; devpriv->ai_cmd_canceled = 0; devpriv->act_chanlist_pos = 0; - devpriv->dma_runs_to_end = 0; if (cmd->convert_src == TRIG_TIMER) ctrl |= PCL818_CTRL_PACER_TRIG; -- cgit v0.10.2 From 421f1b6832efd618c5ce3e639642a49d38ba5a37 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:12 -0700 Subject: staging: comedi: pcl818: use common function to setup dma THe pcl818_ai_setup_dma() and pcl818_ai_setup_next_dma() functions are similar other than the buffer switch and the inclusion of the "unread_samples" in pcl818_ai_setup_next_dma() when calculating the dma size. Merge these two functions by initializing the 'dma->cur_dma' in the callers and passing '0' for the "unread_samples" when first starting the DMA. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index fa7b4e2..ba2e137 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -332,49 +332,22 @@ static void pcl818_start_pacer(struct comedi_device *dev, bool load_counters) } static void pcl818_ai_setup_dma(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pcl818_private *devpriv = dev->private; - struct comedi_isadma *dma = devpriv->dma; - struct comedi_isadma_desc *desc = &dma->desc[0]; - unsigned int nsamples; - - comedi_isadma_disable(dma->chan); - - dma->cur_dma = 0; - - /* - * Determine dma size based on the buffer maxsize and the number of - * samples remaining in the command. - */ - nsamples = comedi_bytes_to_samples(s, desc->maxsize); - nsamples = comedi_nsamples_left(s, nsamples); - desc->size = comedi_samples_to_bytes(s, nsamples); - comedi_isadma_program(desc); -} - -static void pcl818_ai_setup_next_dma(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int unread_samples) + struct comedi_subdevice *s, + unsigned int unread_samples) { struct pcl818_private *devpriv = dev->private; struct comedi_isadma *dma = devpriv->dma; - struct comedi_isadma_desc *desc; - unsigned int max_samples; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned int max_samples = comedi_bytes_to_samples(s, desc->maxsize); unsigned int nsamples; comedi_isadma_disable(dma->chan); - dma->cur_dma = 1 - dma->cur_dma; - desc = &dma->desc[dma->cur_dma]; - /* * Determine dma size based on the buffer maxsize plus the number of * unread samples and the number of samples remaining in the command. */ - max_samples = comedi_bytes_to_samples(s, desc->maxsize); - nsamples = max_samples + unread_samples; - nsamples = comedi_nsamples_left(s, nsamples); + nsamples = comedi_nsamples_left(s, max_samples + unread_samples); if (nsamples > unread_samples) { nsamples -= unread_samples; desc->size = comedi_samples_to_bytes(s, nsamples); @@ -554,7 +527,9 @@ static void pcl818_handle_dma(struct comedi_device *dev, unsigned int val; int i; - pcl818_ai_setup_next_dma(dev, s, nsamples); + /* restart dma with the next buffer */ + dma->cur_dma = 1 - dma->cur_dma; + pcl818_ai_setup_dma(dev, s, nsamples); for (i = 0; i < nsamples; i++) { val = ptr[i]; @@ -790,6 +765,7 @@ static int pcl818_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl818_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; unsigned int ctrl = 0; unsigned int seglen; @@ -815,8 +791,10 @@ static int pcl818_ai_cmd(struct comedi_device *dev, outb(PCL818_CNTENABLE_PACER_ENA, dev->iobase + PCL818_CNTENABLE_REG); - if (devpriv->dma) { - pcl818_ai_setup_dma(dev, s); + if (dma) { + /* setup and enable dma for the first buffer */ + dma->cur_dma = 0; + pcl818_ai_setup_dma(dev, s, 0); ctrl |= PCL818_CTRL_INTE | PCL818_CTRL_IRQ(dev->irq) | PCL818_CTRL_DMAE; -- cgit v0.10.2 From fe4a22a009982442ba8b37f4f499f708d956d16d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:13 -0700 Subject: staging: comedi: pcl816: simplify the dma->size calculations Currently this driver determines the number of DMA "runs" needed and the size of the "last" DMA transfer in order to perform a command. As long as there are more "runs" required, the dma->size is set to the buffer maxsize. On the last "run" the buffer is set to the "last" size. Refactor the driver to use the comedi core helpers to determine the DMA size based on the buffer maxsize and the number of samples remaining in the command. This allows removing the 'dma_runs_to_end' and 'last_dma_run' mamebers from the private data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 09fa409..88c89df 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -115,8 +115,6 @@ static const struct pcl816_board boardtypes[] = { struct pcl816_private { struct comedi_isadma *dma; - long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */ - unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */ unsigned int ai_poll_ptr; /* how many sampes transfer poll */ unsigned int divisor1; unsigned int divisor2; @@ -149,53 +147,47 @@ static void pcl816_ai_setup_dma(struct comedi_device *dev, struct pcl816_private *devpriv = dev->private; struct comedi_isadma *dma = devpriv->dma; struct comedi_isadma_desc *desc = &dma->desc[0]; - struct comedi_cmd *cmd = &s->async->cmd; - - if (cmd->stop_src == TRIG_COUNT) { - /* how many */ - desc->size = cmd->stop_arg * comedi_bytes_per_scan(s); - - /* how many DMA pages we must fill */ - devpriv->dma_runs_to_end = desc->size / desc->maxsize; - - /* on last dma transfer must be moved */ - devpriv->last_dma_run = desc->size % desc->maxsize; - devpriv->dma_runs_to_end--; - if (devpriv->dma_runs_to_end >= 0) - desc->size = desc->maxsize; - } else { - desc->size = desc->maxsize; - devpriv->dma_runs_to_end = -1; - } + unsigned int nsamples; dma->cur_dma = 0; + /* + * Determine dma size based on the buffer maxsize and the number of + * samples remaining in the command. + */ + nsamples = comedi_bytes_to_samples(s, desc->maxsize); + nsamples = comedi_nsamples_left(s, nsamples); + desc->size = comedi_samples_to_bytes(s, nsamples); comedi_isadma_program(desc); } static void pcl816_ai_setup_next_dma(struct comedi_device *dev, - struct comedi_subdevice *s) + struct comedi_subdevice *s, + unsigned int unread_samples) { struct pcl816_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc; + unsigned int max_samples; + unsigned int nsamples; comedi_isadma_disable(dma->chan); - dma->cur_dma = 1 - dma->cur_dma; - - /* switch dma bufs if still running */ - if (devpriv->dma_runs_to_end > -1 || cmd->stop_src == TRIG_NONE) { - struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; - - if (devpriv->dma_runs_to_end) - desc->size = desc->maxsize; - else - desc->size = devpriv->last_dma_run; + dma->cur_dma = 1 - dma->cur_dma; + desc = &dma->desc[dma->cur_dma]; + + /* + * Determine dma size based on the buffer maxsize plus the number of + * unread samples and the number of samples remaining in the command. + */ + max_samples = comedi_bytes_to_samples(s, desc->maxsize); + nsamples = max_samples + unread_samples; + nsamples = comedi_nsamples_left(s, nsamples); + if (nsamples > unread_samples) { + nsamples -= unread_samples; + desc->size = comedi_samples_to_bytes(s, nsamples); comedi_isadma_program(desc); } - - devpriv->dma_runs_to_end--; } static void pcl816_ai_set_chan_range(struct comedi_device *dev, @@ -324,13 +316,13 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) return IRQ_HANDLED; } - pcl816_ai_setup_next_dma(dev, s); - nsamples = comedi_bytes_to_samples(s, desc->size) - devpriv->ai_poll_ptr; bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; + pcl816_ai_setup_next_dma(dev, s, nsamples); + transfer_from_dma_buf(dev, s, desc->virt_addr, bufptr, nsamples); pcl816_ai_clear_eoc(dev); -- cgit v0.10.2 From 93e604523619d32a88e0afbdfef65ec83582c209 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:14 -0700 Subject: staging: comedi: pcl816: use common function to setup dma THe pcl816_ai_setup_dma() and pcl816_ai_setup_next_dma() functions are similar other than the buffer switch and the inclusion of the "unread_samples" in pcl818_ai_setup_next_dma() when calculating the dma size. Merge these two functions by initializing the 'dma->cur_dma' in the callers and passing '0' for the "unread_samples" when first starting the DMA. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 88c89df..da35edf 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -142,47 +142,22 @@ static void pcl816_start_pacer(struct comedi_device *dev, bool load_counters) } static void pcl816_ai_setup_dma(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pcl816_private *devpriv = dev->private; - struct comedi_isadma *dma = devpriv->dma; - struct comedi_isadma_desc *desc = &dma->desc[0]; - unsigned int nsamples; - - dma->cur_dma = 0; - - /* - * Determine dma size based on the buffer maxsize and the number of - * samples remaining in the command. - */ - nsamples = comedi_bytes_to_samples(s, desc->maxsize); - nsamples = comedi_nsamples_left(s, nsamples); - desc->size = comedi_samples_to_bytes(s, nsamples); - comedi_isadma_program(desc); -} - -static void pcl816_ai_setup_next_dma(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int unread_samples) + struct comedi_subdevice *s, + unsigned int unread_samples) { struct pcl816_private *devpriv = dev->private; struct comedi_isadma *dma = devpriv->dma; - struct comedi_isadma_desc *desc; - unsigned int max_samples; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned int max_samples = comedi_bytes_to_samples(s, desc->maxsize); unsigned int nsamples; comedi_isadma_disable(dma->chan); - dma->cur_dma = 1 - dma->cur_dma; - desc = &dma->desc[dma->cur_dma]; - /* * Determine dma size based on the buffer maxsize plus the number of * unread samples and the number of samples remaining in the command. */ - max_samples = comedi_bytes_to_samples(s, desc->maxsize); - nsamples = max_samples + unread_samples; - nsamples = comedi_nsamples_left(s, nsamples); + nsamples = comedi_nsamples_left(s, max_samples + unread_samples); if (nsamples > unread_samples) { nsamples -= unread_samples; desc->size = comedi_samples_to_bytes(s, nsamples); @@ -321,7 +296,9 @@ static irqreturn_t pcl816_interrupt(int irq, void *d) bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; - pcl816_ai_setup_next_dma(dev, s, nsamples); + /* restart dma with the next buffer */ + dma->cur_dma = 1 - dma->cur_dma; + pcl816_ai_setup_dma(dev, s, nsamples); transfer_from_dma_buf(dev, s, desc->virt_addr, bufptr, nsamples); @@ -485,7 +462,9 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_poll_ptr = 0; devpriv->ai_cmd_canceled = 0; - pcl816_ai_setup_dma(dev, s); + /* setup and enable dma for the first buffer */ + dma->cur_dma = 0; + pcl816_ai_setup_dma(dev, s, 0); pcl816_start_pacer(dev, true); -- cgit v0.10.2 From 92afc2b229038d7b962ae69de5b07bc6c1cf51bf Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:15 -0700 Subject: staging: comedi: pcl812: simplify the dma->size calculations The dma->size calculations are overly complicated in this driver and the 'prealloc_bufsz' sanity checks are unnecessary. Currently this driver determines the number of DMA "runs" needed and the size of the "last" DMA transfer in order to perform a command. As long as there are more "runs" required, the dma->size is set to the buffer maxsize. On the last "run" the buffer is set to the "last" size. Refactor the driver to use the comedi core helpers to determine the DMA size based on the buffer maxsize and the number of samples remaining in the command. This allows removing the 'dma_runs_to_end' and 'last_dma_run' mamebers from the private data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 134b26e..f6fe7d3 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -512,8 +512,6 @@ struct pcl812_private { unsigned int last_ai_chanspec; unsigned char mode_reg_int; /* there is stored INT number for some card */ unsigned int ai_poll_ptr; /* how many sampes transfer poll */ - unsigned int dma_runs_to_end; /* how many times we must switch DMA buffers */ - unsigned int last_dma_run; /* how many bytes to transfer on last DMA buffer */ unsigned int max_812_ai_mode0_rangewait; /* setling time for gain */ unsigned int divisor1; unsigned int divisor2; @@ -544,71 +542,48 @@ static void pcl812_ai_setup_dma(struct comedi_device *dev, { struct pcl812_private *devpriv = dev->private; struct comedi_isadma *dma = devpriv->dma; - struct comedi_isadma_desc *desc0 = &dma->desc[0]; - struct comedi_isadma_desc *desc1 = &dma->desc[1]; - struct comedi_cmd *cmd = &s->async->cmd; + struct comedi_isadma_desc *desc = &dma->desc[0]; unsigned int bytes; + unsigned int nsamples; - /* we use EOS, so adapt DMA buffer to one scan */ - if (devpriv->ai_eos) { - desc0->size = comedi_bytes_per_scan(s); - desc1->size = comedi_bytes_per_scan(s); - devpriv->dma_runs_to_end = 1; - } else { - desc0->size = desc0->maxsize; - desc1->size = desc1->maxsize; - if (s->async->prealloc_bufsz < desc0->maxsize) - desc0->size = s->async->prealloc_bufsz; - if (s->async->prealloc_bufsz < desc1->maxsize) - desc1->size = s->async->prealloc_bufsz; - if (cmd->stop_src == TRIG_NONE) { - devpriv->dma_runs_to_end = 1; - } else { - /* how many samples we must transfer? */ - bytes = cmd->stop_arg * comedi_bytes_per_scan(s); - - /* how many DMA pages we must fill */ - devpriv->dma_runs_to_end = bytes / desc0->size; - - /* on last dma transfer must be moved */ - devpriv->last_dma_run = bytes % desc0->size; - if (devpriv->dma_runs_to_end == 0) - desc0->size = devpriv->last_dma_run; - devpriv->dma_runs_to_end--; - } - } - if (desc0->size > desc0->maxsize) { - desc0->size = desc0->maxsize; - devpriv->ai_eos = 0; - } - if (desc1->size > desc1->maxsize) { - desc1->size = desc1->maxsize; - devpriv->ai_eos = 0; - } dma->cur_dma = 0; - comedi_isadma_program(desc0); + /* if using EOS, adapt DMA buffer to one scan */ + bytes = devpriv->ai_eos ? comedi_bytes_per_scan(s) : desc->maxsize; + + nsamples = comedi_bytes_to_samples(s, bytes); + nsamples = comedi_nsamples_left(s, nsamples); + desc->size = comedi_samples_to_bytes(s, nsamples); + comedi_isadma_program(desc); } static void pcl812_ai_setup_next_dma(struct comedi_device *dev, - struct comedi_subdevice *s) + struct comedi_subdevice *s, + unsigned int unread_samples) { struct pcl812_private *devpriv = dev->private; struct comedi_isadma *dma = devpriv->dma; struct comedi_isadma_desc *desc; + unsigned int bytes; + unsigned int max_samples; + unsigned int nsamples; comedi_isadma_disable(dma->chan); - dma->cur_dma = 1 - dma->cur_dma; + dma->cur_dma = 1 - dma->cur_dma; desc = &dma->desc[dma->cur_dma]; - if (!devpriv->ai_eos) { - if (devpriv->dma_runs_to_end) - devpriv->dma_runs_to_end--; - else - desc->size = devpriv->last_dma_run; - } - comedi_isadma_program(desc); + /* if using EOS, adapt DMA buffer to one scan */ + bytes = devpriv->ai_eos ? comedi_bytes_per_scan(s) : desc->maxsize; + + max_samples = comedi_bytes_to_samples(s, bytes); + nsamples = max_samples + unread_samples; + nsamples = comedi_nsamples_left(s, nsamples); + if (nsamples > max_samples) { + nsamples -= max_samples; + desc->size = comedi_samples_to_bytes(s, nsamples); + comedi_isadma_program(desc); + } } static void pcl812_ai_set_chan_range(struct comedi_device *dev, @@ -879,13 +854,13 @@ static void pcl812_handle_dma(struct comedi_device *dev, unsigned int nsamples; int bufptr; - pcl812_ai_setup_next_dma(dev, s); - nsamples = comedi_bytes_to_samples(s, desc->size) - devpriv->ai_poll_ptr; bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; + pcl812_ai_setup_next_dma(dev, s, nsamples); + transfer_from_dma_buf(dev, s, desc->virt_addr, bufptr, nsamples); } -- cgit v0.10.2 From a7f0ce8e5d84f2d14ca77d3c539af16cfef1981e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 14 Jan 2015 10:05:16 -0700 Subject: staging: comedi: pcl812: use common function to setup dma The pcl812_ai_setup_dma() and pcl812_ai_setup_next_dma() functions are similar other than the buffer switch and the inclusion of the "unread_samples" in pcl818_ai_setup_next_dma() when calculating the dma size. Merge these two functions by initializing the 'dma->cur_dma' in the callers and passing '0' for the "unread_samples" when first starting the DMA. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index f6fe7d3..f76601a 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -538,47 +538,27 @@ static void pcl812_start_pacer(struct comedi_device *dev, bool load_timers) } static void pcl812_ai_setup_dma(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pcl812_private *devpriv = dev->private; - struct comedi_isadma *dma = devpriv->dma; - struct comedi_isadma_desc *desc = &dma->desc[0]; - unsigned int bytes; - unsigned int nsamples; - - dma->cur_dma = 0; - - /* if using EOS, adapt DMA buffer to one scan */ - bytes = devpriv->ai_eos ? comedi_bytes_per_scan(s) : desc->maxsize; - - nsamples = comedi_bytes_to_samples(s, bytes); - nsamples = comedi_nsamples_left(s, nsamples); - desc->size = comedi_samples_to_bytes(s, nsamples); - comedi_isadma_program(desc); -} - -static void pcl812_ai_setup_next_dma(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int unread_samples) + struct comedi_subdevice *s, + unsigned int unread_samples) { struct pcl812_private *devpriv = dev->private; struct comedi_isadma *dma = devpriv->dma; - struct comedi_isadma_desc *desc; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; unsigned int bytes; unsigned int max_samples; unsigned int nsamples; comedi_isadma_disable(dma->chan); - dma->cur_dma = 1 - dma->cur_dma; - desc = &dma->desc[dma->cur_dma]; - /* if using EOS, adapt DMA buffer to one scan */ bytes = devpriv->ai_eos ? comedi_bytes_per_scan(s) : desc->maxsize; - max_samples = comedi_bytes_to_samples(s, bytes); - nsamples = max_samples + unread_samples; - nsamples = comedi_nsamples_left(s, nsamples); + + /* + * Determine dma size based on the buffer size plus the number of + * unread samples and the number of samples remaining in the command. + */ + nsamples = comedi_nsamples_left(s, max_samples + unread_samples); if (nsamples > max_samples) { nsamples -= max_samples; desc->size = comedi_samples_to_bytes(s, nsamples); @@ -740,6 +720,7 @@ static int pcl812_ai_cmdtest(struct comedi_device *dev, static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pcl812_private *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; struct comedi_cmd *cmd = &s->async->cmd; unsigned int ctrl = 0; unsigned int i; @@ -748,7 +729,7 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) pcl812_ai_set_chan_range(dev, cmd->chanlist[0], 1); - if (devpriv->dma) { /* check if we can use DMA transfer */ + if (dma) { /* check if we can use DMA transfer */ devpriv->ai_dma = 1; for (i = 1; i < cmd->chanlist_len; i++) if (cmd->chanlist[0] != cmd->chanlist[i]) { @@ -771,8 +752,11 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->ai_dma = 0; } - if (devpriv->ai_dma) - pcl812_ai_setup_dma(dev, s); + if (devpriv->ai_dma) { + /* setup and enable dma for the first buffer */ + dma->cur_dma = 0; + pcl812_ai_setup_dma(dev, s, 0); + } switch (cmd->convert_src) { case TRIG_TIMER: @@ -859,7 +843,9 @@ static void pcl812_handle_dma(struct comedi_device *dev, bufptr = devpriv->ai_poll_ptr; devpriv->ai_poll_ptr = 0; - pcl812_ai_setup_next_dma(dev, s, nsamples); + /* restart dma with the next buffer */ + dma->cur_dma = 1 - dma->cur_dma; + pcl812_ai_setup_dma(dev, s, nsamples); transfer_from_dma_buf(dev, s, desc->virt_addr, bufptr, nsamples); } -- cgit v0.10.2 From 53d484b18f1444eba3836ea0d162460fab3edc55 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 11 Jan 2015 15:46:26 -0600 Subject: Staging: comedi: kcomedilib: Fixed a typo Fixed a typo in kcomedilib_main.c file. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index 8777f95..973f544 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -95,7 +95,7 @@ static int comedi_do_insn(struct comedi_device *dev, if (s->type == COMEDI_SUBD_UNUSED) { dev_err(dev->class_dev, - "%d not useable subdevice\n", insn->subdev); + "%d not usable subdevice\n", insn->subdev); ret = -EIO; goto error; } -- cgit v0.10.2 From b5aa3f17ef456aba93263c8cdc9f4026bf24f946 Mon Sep 17 00:00:00 2001 From: Emrys Bayliss Date: Fri, 16 Jan 2015 03:29:21 +1100 Subject: Staging: vt6655: Checkpatch fix: unnecessary whitespace This patch fixes the following checkpatch.pl errors in mac.h: ERROR: space prohibited before that ',' (ctx:WxW) Signed-off-by: Emrys Bayliss Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index e1e7e10..0f1d4a5 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -888,7 +888,7 @@ do { \ VNSvOutPortB(dwIoBase + MAC_REG_PAGE1SEL, 1) #define MACvReadMIBCounter(dwIoBase, pdwCounter) \ - VNSvInPortD(dwIoBase + MAC_REG_MIBCNTR , pdwCounter) + VNSvInPortD(dwIoBase + MAC_REG_MIBCNTR, pdwCounter) #define MACvPwrEvntDisable(dwIoBase) \ VNSvOutPortW(dwIoBase + MAC_REG_WAKEUPEN0, 0x0000) @@ -896,7 +896,7 @@ do { \ #define MACvEnableProtectMD(dwIoBase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue | EnCFG_ProtectMd; \ VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) @@ -904,7 +904,7 @@ do { \ #define MACvDisableProtectMD(dwIoBase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue & ~EnCFG_ProtectMd; \ VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) @@ -912,7 +912,7 @@ do { \ #define MACvEnableBarkerPreambleMd(dwIoBase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue | EnCFG_BarkerPream; \ VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) @@ -920,7 +920,7 @@ do { \ #define MACvDisableBarkerPreambleMd(dwIoBase) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue & ~EnCFG_BarkerPream; \ VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ } while (0) @@ -928,7 +928,7 @@ do { \ #define MACvSetBBType(dwIoBase, byTyp) \ do { \ unsigned long dwOrgValue; \ - VNSvInPortD(dwIoBase + MAC_REG_ENCFG , &dwOrgValue); \ + VNSvInPortD(dwIoBase + MAC_REG_ENCFG, &dwOrgValue); \ dwOrgValue = dwOrgValue & ~EnCFG_BBType_MASK; \ dwOrgValue = dwOrgValue | (unsigned long)byTyp; \ VNSvOutPortD(dwIoBase + MAC_REG_ENCFG, dwOrgValue); \ -- cgit v0.10.2 From 818b55576001a239efd356c39a462bd346dc760c Mon Sep 17 00:00:00 2001 From: Emrys Bayliss Date: Fri, 16 Jan 2015 03:29:22 +1100 Subject: Staging: vt6655: Checkpatch fix: empty c99 comments This patch fixes some of the following checkpatch.pl errors in mac.h: ERROR: do not use C99 // comments This patch truncates statements which are followed by empty c99 comments. Signed-off-by: Emrys Bayliss Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index 0f1d4a5..359e3f2 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -70,14 +70,14 @@ #define MAC_REG_TMCTL1 0x19 #define MAC_REG_TMDATA0 0x1C // MAC Parameter related -#define MAC_REG_LRT 0x20 // -#define MAC_REG_SRT 0x21 // -#define MAC_REG_SIFS 0x22 // -#define MAC_REG_DIFS 0x23 // -#define MAC_REG_EIFS 0x24 // -#define MAC_REG_SLOT 0x25 // -#define MAC_REG_BI 0x26 // -#define MAC_REG_CWMAXMIN0 0x28 // +#define MAC_REG_LRT 0x20 +#define MAC_REG_SRT 0x21 +#define MAC_REG_SIFS 0x22 +#define MAC_REG_DIFS 0x23 +#define MAC_REG_EIFS 0x24 +#define MAC_REG_SLOT 0x25 +#define MAC_REG_BI 0x26 +#define MAC_REG_CWMAXMIN0 0x28 #define MAC_REG_LINKOFFTOTM 0x2A #define MAC_REG_SWTMOT 0x2B #define MAC_REG_MIBCNTR 0x2C @@ -86,25 +86,25 @@ #define MAC_REG_ACKFAILCNT 0x2E #define MAC_REG_FCSERRCNT 0x2F // TSF Related -#define MAC_REG_TSFCNTR 0x30 // -#define MAC_REG_NEXTTBTT 0x38 // -#define MAC_REG_TSFOFST 0x40 // -#define MAC_REG_TFTCTL 0x48 // +#define MAC_REG_TSFCNTR 0x30 +#define MAC_REG_NEXTTBTT 0x38 +#define MAC_REG_TSFOFST 0x40 +#define MAC_REG_TFTCTL 0x48 // WMAC Control/Status Related -#define MAC_REG_ENCFG 0x4C // -#define MAC_REG_PAGE1SEL 0x4F // -#define MAC_REG_CFG 0x50 // -#define MAC_REG_TEST 0x52 // -#define MAC_REG_HOSTCR 0x54 // -#define MAC_REG_MACCR 0x55 // -#define MAC_REG_RCR 0x56 // -#define MAC_REG_TCR 0x57 // -#define MAC_REG_IMR 0x58 // +#define MAC_REG_ENCFG 0x4C +#define MAC_REG_PAGE1SEL 0x4F +#define MAC_REG_CFG 0x50 +#define MAC_REG_TEST 0x52 +#define MAC_REG_HOSTCR 0x54 +#define MAC_REG_MACCR 0x55 +#define MAC_REG_RCR 0x56 +#define MAC_REG_TCR 0x57 +#define MAC_REG_IMR 0x58 #define MAC_REG_ISR 0x5C // Power Saving Related -#define MAC_REG_PSCFG 0x60 // -#define MAC_REG_PSCTL 0x61 // -#define MAC_REG_PSPWRSIG 0x62 // +#define MAC_REG_PSCFG 0x60 +#define MAC_REG_PSCTL 0x61 +#define MAC_REG_PSPWRSIG 0x62 #define MAC_REG_BBCR13 0x63 #define MAC_REG_AIDATIM 0x64 #define MAC_REG_PWBT 0x66 @@ -113,30 +113,30 @@ #define MAC_REG_SYNSPACCNT 0x6A #define MAC_REG_WAKSYNOPT 0x6B // Baseband/IF Control Group -#define MAC_REG_BBREGCTL 0x6C // +#define MAC_REG_BBREGCTL 0x6C #define MAC_REG_CHANNEL 0x6D #define MAC_REG_BBREGADR 0x6E #define MAC_REG_BBREGDATA 0x6F -#define MAC_REG_IFREGCTL 0x70 // -#define MAC_REG_IFDATA 0x71 // -#define MAC_REG_ITRTMSET 0x74 // +#define MAC_REG_IFREGCTL 0x70 +#define MAC_REG_IFDATA 0x71 +#define MAC_REG_ITRTMSET 0x74 #define MAC_REG_PAPEDELAY 0x77 -#define MAC_REG_SOFTPWRCTL 0x78 // -#define MAC_REG_GPIOCTL0 0x7A // -#define MAC_REG_GPIOCTL1 0x7B // +#define MAC_REG_SOFTPWRCTL 0x78 +#define MAC_REG_GPIOCTL0 0x7A +#define MAC_REG_GPIOCTL1 0x7B // MAC DMA Related Group -#define MAC_REG_TXDMACTL0 0x7C // -#define MAC_REG_TXDMAPTR0 0x80 // -#define MAC_REG_AC0DMACTL 0x84 // -#define MAC_REG_AC0DMAPTR 0x88 // -#define MAC_REG_BCNDMACTL 0x8C // -#define MAC_REG_BCNDMAPTR 0x90 // -#define MAC_REG_RXDMACTL0 0x94 // -#define MAC_REG_RXDMAPTR0 0x98 // -#define MAC_REG_RXDMACTL1 0x9C // -#define MAC_REG_RXDMAPTR1 0xA0 // -#define MAC_REG_SYNCDMACTL 0xA4 // +#define MAC_REG_TXDMACTL0 0x7C +#define MAC_REG_TXDMAPTR0 0x80 +#define MAC_REG_AC0DMACTL 0x84 +#define MAC_REG_AC0DMAPTR 0x88 +#define MAC_REG_BCNDMACTL 0x8C +#define MAC_REG_BCNDMAPTR 0x90 +#define MAC_REG_RXDMACTL0 0x94 +#define MAC_REG_RXDMAPTR0 0x98 +#define MAC_REG_RXDMACTL1 0x9C +#define MAC_REG_RXDMAPTR1 0xA0 +#define MAC_REG_SYNCDMACTL 0xA4 #define MAC_REG_SYNCDMAPTR 0xA8 #define MAC_REG_ATIMDMACTL 0xAC #define MAC_REG_ATIMDMAPTR 0xB0 @@ -217,20 +217,20 @@ #define BCFG1_CISDLYEN 0x01 // Bits in RAMBIST registers -#define BISTCMD_TSTPAT5 0x00 // -#define BISTCMD_TSTPATA 0x80 // -#define BISTCMD_TSTERR 0x20 // -#define BISTCMD_TSTPATF 0x18 // -#define BISTCMD_TSTPAT0 0x10 // -#define BISTCMD_TSTMODE 0x04 // -#define BISTCMD_TSTITTX 0x03 // -#define BISTCMD_TSTATRX 0x02 // -#define BISTCMD_TSTATTX 0x01 // -#define BISTCMD_TSTRX 0x00 // -#define BISTSR0_BISTGO 0x01 // -#define BISTSR1_TSTSR 0x01 // -#define BISTSR2_CMDPRTEN 0x02 // -#define BISTSR2_RAMTSTEN 0x01 // +#define BISTCMD_TSTPAT5 0x00 +#define BISTCMD_TSTPATA 0x80 +#define BISTCMD_TSTERR 0x20 +#define BISTCMD_TSTPATF 0x18 +#define BISTCMD_TSTPAT0 0x10 +#define BISTCMD_TSTMODE 0x04 +#define BISTCMD_TSTITTX 0x03 +#define BISTCMD_TSTATRX 0x02 +#define BISTCMD_TSTATTX 0x01 +#define BISTCMD_TSTRX 0x00 +#define BISTSR0_BISTGO 0x01 +#define BISTSR1_TSTSR 0x01 +#define BISTSR2_CMDPRTEN 0x02 +#define BISTSR2_RAMTSTEN 0x01 // // Bits in the I2MCFG EEPROM register @@ -275,14 +275,14 @@ // // Bits in the TFTCTL register // -#define TFTCTL_HWUTSF 0x80 // +#define TFTCTL_HWUTSF 0x80 #define TFTCTL_TBTTSYNC 0x40 #define TFTCTL_HWUTSFEN 0x20 -#define TFTCTL_TSFCNTRRD 0x10 // -#define TFTCTL_TBTTSYNCEN 0x08 // -#define TFTCTL_TSFSYNCEN 0x04 // -#define TFTCTL_TSFCNTRST 0x02 // -#define TFTCTL_TSFCNTREN 0x01 // +#define TFTCTL_TSFCNTRRD 0x10 +#define TFTCTL_TBTTSYNCEN 0x08 +#define TFTCTL_TSFSYNCEN 0x04 +#define TFTCTL_TSFCNTRST 0x02 +#define TFTCTL_TSFCNTREN 0x01 // // Bits in the EnhanceCFG register @@ -321,21 +321,21 @@ // // Bits in the TEST register // -#define TEST_LBEXT 0x80 // -#define TEST_LBINT 0x40 // -#define TEST_LBNONE 0x00 // -#define TEST_SOFTINT 0x20 // -#define TEST_CONTTX 0x10 // -#define TEST_TXPE 0x08 // -#define TEST_NAVDIS 0x04 // -#define TEST_NOCTS 0x02 // -#define TEST_NOACK 0x01 // +#define TEST_LBEXT 0x80 +#define TEST_LBINT 0x40 +#define TEST_LBNONE 0x00 +#define TEST_SOFTINT 0x20 +#define TEST_CONTTX 0x10 +#define TEST_TXPE 0x08 +#define TEST_NAVDIS 0x04 +#define TEST_NOCTS 0x02 +#define TEST_NOACK 0x01 // // Bits in the HOSTCR register // -#define HOSTCR_TXONST 0x80 // -#define HOSTCR_RXONST 0x40 // +#define HOSTCR_TXONST 0x80 +#define HOSTCR_RXONST 0x40 #define HOSTCR_ADHOC 0x20 // Network Type 1 = Ad-hoc #define HOSTCR_AP 0x10 // Port Type 1 = AP #define HOSTCR_TXON 0x08 //0000 1000 @@ -346,167 +346,167 @@ // // Bits in the MACCR register // -#define MACCR_SYNCFLUSHOK 0x04 // -#define MACCR_SYNCFLUSH 0x02 // -#define MACCR_CLRNAV 0x01 // +#define MACCR_SYNCFLUSHOK 0x04 +#define MACCR_SYNCFLUSH 0x02 +#define MACCR_CLRNAV 0x01 // Bits in the MAC_REG_GPIOCTL0 register // -#define LED_ACTSET 0x01 // -#define LED_RFOFF 0x02 // -#define LED_NOCONNECT 0x04 // +#define LED_ACTSET 0x01 +#define LED_RFOFF 0x02 +#define LED_NOCONNECT 0x04 // // Bits in the RCR register // #define RCR_SSID 0x80 -#define RCR_RXALLTYPE 0x40 // -#define RCR_UNICAST 0x20 // -#define RCR_BROADCAST 0x10 // -#define RCR_MULTICAST 0x08 // -#define RCR_WPAERR 0x04 // -#define RCR_ERRCRC 0x02 // -#define RCR_BSSID 0x01 // +#define RCR_RXALLTYPE 0x40 +#define RCR_UNICAST 0x20 +#define RCR_BROADCAST 0x10 +#define RCR_MULTICAST 0x08 +#define RCR_WPAERR 0x04 +#define RCR_ERRCRC 0x02 +#define RCR_BSSID 0x01 // // Bits in the TCR register // -#define TCR_SYNCDCFOPT 0x02 // +#define TCR_SYNCDCFOPT 0x02 #define TCR_AUTOBCNTX 0x01 // Beacon automatically transmit enable // // Bits in the IMR register // -#define IMR_MEASURESTART 0x80000000 // -#define IMR_QUIETSTART 0x20000000 // -#define IMR_RADARDETECT 0x10000000 // -#define IMR_MEASUREEND 0x08000000 // -#define IMR_SOFTTIMER1 0x00200000 // +#define IMR_MEASURESTART 0x80000000 +#define IMR_QUIETSTART 0x20000000 +#define IMR_RADARDETECT 0x10000000 +#define IMR_MEASUREEND 0x08000000 +#define IMR_SOFTTIMER1 0x00200000 #define IMR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 -#define IMR_RXNOBUF 0x00000800 // -#define IMR_MIBNEARFULL 0x00000400 // -#define IMR_SOFTINT 0x00000200 // -#define IMR_FETALERR 0x00000100 // -#define IMR_WATCHDOG 0x00000080 // -#define IMR_SOFTTIMER 0x00000040 // -#define IMR_GPIO 0x00000020 // -#define IMR_TBTT 0x00000010 // -#define IMR_RXDMA0 0x00000008 // -#define IMR_BNTX 0x00000004 // -#define IMR_AC0DMA 0x00000002 // -#define IMR_TXDMA0 0x00000001 // +#define IMR_RXNOBUF 0x00000800 +#define IMR_MIBNEARFULL 0x00000400 +#define IMR_SOFTINT 0x00000200 +#define IMR_FETALERR 0x00000100 +#define IMR_WATCHDOG 0x00000080 +#define IMR_SOFTTIMER 0x00000040 +#define IMR_GPIO 0x00000020 +#define IMR_TBTT 0x00000010 +#define IMR_RXDMA0 0x00000008 +#define IMR_BNTX 0x00000004 +#define IMR_AC0DMA 0x00000002 +#define IMR_TXDMA0 0x00000001 // // Bits in the ISR register // -#define ISR_MEASURESTART 0x80000000 // -#define ISR_QUIETSTART 0x20000000 // -#define ISR_RADARDETECT 0x10000000 // -#define ISR_MEASUREEND 0x08000000 // -#define ISR_SOFTTIMER1 0x00200000 // +#define ISR_MEASURESTART 0x80000000 +#define ISR_QUIETSTART 0x20000000 +#define ISR_RADARDETECT 0x10000000 +#define ISR_MEASUREEND 0x08000000 +#define ISR_SOFTTIMER1 0x00200000 #define ISR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 #define ISR_RXNOBUF 0x00000800 //0000 0000 0000 1000 0000 0000 #define ISR_MIBNEARFULL 0x00000400 //0000 0000 0000 0100 0000 0000 -#define ISR_SOFTINT 0x00000200 // -#define ISR_FETALERR 0x00000100 // -#define ISR_WATCHDOG 0x00000080 // -#define ISR_SOFTTIMER 0x00000040 // -#define ISR_GPIO 0x00000020 // -#define ISR_TBTT 0x00000010 // -#define ISR_RXDMA0 0x00000008 // -#define ISR_BNTX 0x00000004 // -#define ISR_AC0DMA 0x00000002 // -#define ISR_TXDMA0 0x00000001 // +#define ISR_SOFTINT 0x00000200 +#define ISR_FETALERR 0x00000100 +#define ISR_WATCHDOG 0x00000080 +#define ISR_SOFTTIMER 0x00000040 +#define ISR_GPIO 0x00000020 +#define ISR_TBTT 0x00000010 +#define ISR_RXDMA0 0x00000008 +#define ISR_BNTX 0x00000004 +#define ISR_AC0DMA 0x00000002 +#define ISR_TXDMA0 0x00000001 // // Bits in the PSCFG register // -#define PSCFG_PHILIPMD 0x40 // -#define PSCFG_WAKECALEN 0x20 // -#define PSCFG_WAKETMREN 0x10 // -#define PSCFG_BBPSPROG 0x08 // -#define PSCFG_WAKESYN 0x04 // -#define PSCFG_SLEEPSYN 0x02 // -#define PSCFG_AUTOSLEEP 0x01 // +#define PSCFG_PHILIPMD 0x40 +#define PSCFG_WAKECALEN 0x20 +#define PSCFG_WAKETMREN 0x10 +#define PSCFG_BBPSPROG 0x08 +#define PSCFG_WAKESYN 0x04 +#define PSCFG_SLEEPSYN 0x02 +#define PSCFG_AUTOSLEEP 0x01 // // Bits in the PSCTL register // -#define PSCTL_WAKEDONE 0x20 // -#define PSCTL_PS 0x10 // -#define PSCTL_GO2DOZE 0x08 // -#define PSCTL_LNBCN 0x04 // -#define PSCTL_ALBCN 0x02 // -#define PSCTL_PSEN 0x01 // +#define PSCTL_WAKEDONE 0x20 +#define PSCTL_PS 0x10 +#define PSCTL_GO2DOZE 0x08 +#define PSCTL_LNBCN 0x04 +#define PSCTL_ALBCN 0x02 +#define PSCTL_PSEN 0x01 // // Bits in the PSPWSIG register // -#define PSSIG_WPE3 0x80 // -#define PSSIG_WPE2 0x40 // -#define PSSIG_WPE1 0x20 // -#define PSSIG_WRADIOPE 0x10 // -#define PSSIG_SPE3 0x08 // -#define PSSIG_SPE2 0x04 // -#define PSSIG_SPE1 0x02 // -#define PSSIG_SRADIOPE 0x01 // +#define PSSIG_WPE3 0x80 +#define PSSIG_WPE2 0x40 +#define PSSIG_WPE1 0x20 +#define PSSIG_WRADIOPE 0x10 +#define PSSIG_SPE3 0x08 +#define PSSIG_SPE2 0x04 +#define PSSIG_SPE1 0x02 +#define PSSIG_SRADIOPE 0x01 // // Bits in the BBREGCTL register // -#define BBREGCTL_DONE 0x04 // -#define BBREGCTL_REGR 0x02 // -#define BBREGCTL_REGW 0x01 // +#define BBREGCTL_DONE 0x04 +#define BBREGCTL_REGR 0x02 +#define BBREGCTL_REGW 0x01 // // Bits in the IFREGCTL register // -#define IFREGCTL_DONE 0x04 // -#define IFREGCTL_IFRF 0x02 // -#define IFREGCTL_REGW 0x01 // +#define IFREGCTL_DONE 0x04 +#define IFREGCTL_IFRF 0x02 +#define IFREGCTL_REGW 0x01 // // Bits in the SOFTPWRCTL register // -#define SOFTPWRCTL_RFLEOPT 0x0800 // -#define SOFTPWRCTL_TXPEINV 0x0200 // -#define SOFTPWRCTL_SWPECTI 0x0100 // -#define SOFTPWRCTL_SWPAPE 0x0020 // -#define SOFTPWRCTL_SWCALEN 0x0010 // -#define SOFTPWRCTL_SWRADIO_PE 0x0008 // -#define SOFTPWRCTL_SWPE2 0x0004 // -#define SOFTPWRCTL_SWPE1 0x0002 // -#define SOFTPWRCTL_SWPE3 0x0001 // +#define SOFTPWRCTL_RFLEOPT 0x0800 +#define SOFTPWRCTL_TXPEINV 0x0200 +#define SOFTPWRCTL_SWPECTI 0x0100 +#define SOFTPWRCTL_SWPAPE 0x0020 +#define SOFTPWRCTL_SWCALEN 0x0010 +#define SOFTPWRCTL_SWRADIO_PE 0x0008 +#define SOFTPWRCTL_SWPE2 0x0004 +#define SOFTPWRCTL_SWPE1 0x0002 +#define SOFTPWRCTL_SWPE3 0x0001 // // Bits in the GPIOCTL1 register // -#define GPIO1_DATA1 0x20 // -#define GPIO1_MD1 0x10 // -#define GPIO1_DATA0 0x02 // -#define GPIO1_MD0 0x01 // +#define GPIO1_DATA1 0x20 +#define GPIO1_MD1 0x10 +#define GPIO1_DATA0 0x02 +#define GPIO1_MD0 0x01 // // Bits in the DMACTL register // -#define DMACTL_CLRRUN 0x00080000 // -#define DMACTL_RUN 0x00000008 // -#define DMACTL_WAKE 0x00000004 // -#define DMACTL_DEAD 0x00000002 // -#define DMACTL_ACTIVE 0x00000001 // +#define DMACTL_CLRRUN 0x00080000 +#define DMACTL_RUN 0x00000008 +#define DMACTL_WAKE 0x00000004 +#define DMACTL_DEAD 0x00000002 +#define DMACTL_ACTIVE 0x00000001 // // Bits in the RXDMACTL0 register // -#define RX_PERPKT 0x00000100 // -#define RX_PERPKTCLR 0x01000000 // +#define RX_PERPKT 0x00000100 +#define RX_PERPKTCLR 0x01000000 // // Bits in the BCNDMACTL register // -#define BEACON_READY 0x01 // +#define BEACON_READY 0x01 // // Bits in the MISCFFCTL register // -#define MISCFFCTL_WRITE 0x0001 // +#define MISCFFCTL_WRITE 0x0001 // // Bits in WAKEUPEN0 @@ -545,11 +545,11 @@ // // Bits in the MAC_REG_GPIOCTL register // -#define GPIO0_MD 0x01 // -#define GPIO0_DATA 0x02 // -#define GPIO0_INTMD 0x04 // -#define GPIO1_MD 0x10 // -#define GPIO1_DATA 0x20 // +#define GPIO0_MD 0x01 +#define GPIO0_DATA 0x02 +#define GPIO0_INTMD 0x04 +#define GPIO1_MD 0x10 +#define GPIO1_DATA 0x20 // // Bits in the MSRCTL register @@ -570,9 +570,9 @@ #define MSRCTL1_TXPAUSE 0x01 // Loopback mode -#define MAC_LB_EXT 0x02 // -#define MAC_LB_INTERNAL 0x01 // -#define MAC_LB_NONE 0x00 // +#define MAC_LB_EXT 0x02 +#define MAC_LB_INTERNAL 0x01 +#define MAC_LB_NONE 0x00 #define Default_BI 0x200 @@ -600,7 +600,7 @@ IMR_TXDMA0) // max time out delay time -#define W_MAX_TIMEOUT 0xFFF0U // +#define W_MAX_TIMEOUT 0xFFF0U // wait time within loop #define CB_DELAY_LOOP_WAIT 10 // 10ms -- cgit v0.10.2 From 644848af96846adc3c81fdbb1cb7da2836316ec2 Mon Sep 17 00:00:00 2001 From: Emrys Bayliss Date: Fri, 16 Jan 2015 03:29:23 +1100 Subject: Staging: vt6655: comment after statement formatting This patch makes the formatting of the comments in mac.h more consistent. * Where a comment follows a statement, it is separated by a single space. Signed-off-by: Emrys Bayliss Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index 359e3f2..f29fe30 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -336,12 +336,12 @@ // #define HOSTCR_TXONST 0x80 #define HOSTCR_RXONST 0x40 -#define HOSTCR_ADHOC 0x20 // Network Type 1 = Ad-hoc -#define HOSTCR_AP 0x10 // Port Type 1 = AP -#define HOSTCR_TXON 0x08 //0000 1000 -#define HOSTCR_RXON 0x04 //0000 0100 -#define HOSTCR_MACEN 0x02 //0000 0010 -#define HOSTCR_SOFTRST 0x01 //0000 0001 +#define HOSTCR_ADHOC 0x20 // Network Type 1 = Ad-hoc +#define HOSTCR_AP 0x10 // Port Type 1 = AP +#define HOSTCR_TXON 0x08 //0000 1000 +#define HOSTCR_RXON 0x04 //0000 0100 +#define HOSTCR_MACEN 0x02 //0000 0010 +#define HOSTCR_SOFTRST 0x01 //0000 0001 // // Bits in the MACCR register @@ -371,7 +371,7 @@ // Bits in the TCR register // #define TCR_SYNCDCFOPT 0x02 -#define TCR_AUTOBCNTX 0x01 // Beacon automatically transmit enable +#define TCR_AUTOBCNTX 0x01 // Beacon automatically transmit enable // // Bits in the IMR register @@ -381,7 +381,7 @@ #define IMR_RADARDETECT 0x10000000 #define IMR_MEASUREEND 0x08000000 #define IMR_SOFTTIMER1 0x00200000 -#define IMR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 +#define IMR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 #define IMR_RXNOBUF 0x00000800 #define IMR_MIBNEARFULL 0x00000400 #define IMR_SOFTINT 0x00000200 @@ -404,9 +404,9 @@ #define ISR_RADARDETECT 0x10000000 #define ISR_MEASUREEND 0x08000000 #define ISR_SOFTTIMER1 0x00200000 -#define ISR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 -#define ISR_RXNOBUF 0x00000800 //0000 0000 0000 1000 0000 0000 -#define ISR_MIBNEARFULL 0x00000400 //0000 0000 0000 0100 0000 0000 +#define ISR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 +#define ISR_RXNOBUF 0x00000800 //0000 0000 0000 1000 0000 0000 +#define ISR_MIBNEARFULL 0x00000400 //0000 0000 0000 0100 0000 0000 #define ISR_SOFTINT 0x00000200 #define ISR_FETALERR 0x00000100 #define ISR_WATCHDOG 0x00000080 @@ -603,7 +603,7 @@ #define W_MAX_TIMEOUT 0xFFF0U // wait time within loop -#define CB_DELAY_LOOP_WAIT 10 // 10ms +#define CB_DELAY_LOOP_WAIT 10 // 10ms // // revision id -- cgit v0.10.2 From 060b505b8309a4ffc8d8a43d7d833229d83e0005 Mon Sep 17 00:00:00 2001 From: Emrys Bayliss Date: Fri, 16 Jan 2015 03:29:24 +1100 Subject: Staging: vt6655: Checkpatch fix: c99 comments after statements This patch fixes some c99 errors in mac.h: ERROR: do not use C99 // comments All instances where the c99 comment occurs after a statement. Signed-off-by: Emrys Bayliss Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index f29fe30..fcd1f3c 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -336,12 +336,12 @@ // #define HOSTCR_TXONST 0x80 #define HOSTCR_RXONST 0x40 -#define HOSTCR_ADHOC 0x20 // Network Type 1 = Ad-hoc -#define HOSTCR_AP 0x10 // Port Type 1 = AP -#define HOSTCR_TXON 0x08 //0000 1000 -#define HOSTCR_RXON 0x04 //0000 0100 -#define HOSTCR_MACEN 0x02 //0000 0010 -#define HOSTCR_SOFTRST 0x01 //0000 0001 +#define HOSTCR_ADHOC 0x20 /* Network Type 1 = Ad-hoc */ +#define HOSTCR_AP 0x10 /* Port Type 1 = AP */ +#define HOSTCR_TXON 0x08 /* 0000 1000 */ +#define HOSTCR_RXON 0x04 /* 0000 0100 */ +#define HOSTCR_MACEN 0x02 /* 0000 0010 */ +#define HOSTCR_SOFTRST 0x01 /* 0000 0001 */ // // Bits in the MACCR register @@ -371,7 +371,7 @@ // Bits in the TCR register // #define TCR_SYNCDCFOPT 0x02 -#define TCR_AUTOBCNTX 0x01 // Beacon automatically transmit enable +#define TCR_AUTOBCNTX 0x01 /* Beacon automatically transmit enable */ // // Bits in the IMR register @@ -381,7 +381,7 @@ #define IMR_RADARDETECT 0x10000000 #define IMR_MEASUREEND 0x08000000 #define IMR_SOFTTIMER1 0x00200000 -#define IMR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 +#define IMR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */ #define IMR_RXNOBUF 0x00000800 #define IMR_MIBNEARFULL 0x00000400 #define IMR_SOFTINT 0x00000200 @@ -404,9 +404,9 @@ #define ISR_RADARDETECT 0x10000000 #define ISR_MEASUREEND 0x08000000 #define ISR_SOFTTIMER1 0x00200000 -#define ISR_RXDMA1 0x00001000 //0000 0000 0001 0000 0000 0000 -#define ISR_RXNOBUF 0x00000800 //0000 0000 0000 1000 0000 0000 -#define ISR_MIBNEARFULL 0x00000400 //0000 0000 0000 0100 0000 0000 +#define ISR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */ +#define ISR_RXNOBUF 0x00000800 /* 0000 0000 0000 1000 0000 0000 */ +#define ISR_MIBNEARFULL 0x00000400 /* 0000 0000 0000 0100 0000 0000 */ #define ISR_SOFTINT 0x00000200 #define ISR_FETALERR 0x00000100 #define ISR_WATCHDOG 0x00000080 @@ -603,7 +603,7 @@ #define W_MAX_TIMEOUT 0xFFF0U // wait time within loop -#define CB_DELAY_LOOP_WAIT 10 // 10ms +#define CB_DELAY_LOOP_WAIT 10 /* 10ms */ // // revision id @@ -993,4 +993,4 @@ void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, unsigned in unsigned int uKeyIdx, unsigned char *pbyAddr, u32 *pdwKey, unsigned char byLocalID); void MACvDisableKeyEntry(void __iomem *dwIoBase, unsigned int uEntryIdx); -#endif // __MAC_H__ +#endif /* __MAC_H__ */ -- cgit v0.10.2 From 19bf265eae80845a81a3918208c86416ce239b6c Mon Sep 17 00:00:00 2001 From: Emrys Bayliss Date: Fri, 16 Jan 2015 03:29:25 +1100 Subject: Staging: vt6655: Checkpatch fix: lines longer than 80 columns This patch fixes the following checkpatch.pl errors in mac.h: WARNING: line over 80 characters Signed-off-by: Emrys Bayliss Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index fcd1f3c..d1a56cb 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -953,15 +953,18 @@ do { \ #define MACvSetRFLE_LatchBase(dwIoBase) \ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT) -bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs, unsigned char byTestBits); -bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs, unsigned char byTestBits); +bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs, + unsigned char byTestBits); +bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs, + unsigned char byTestBits); bool MACbIsIntDisable(void __iomem *dwIoBase); void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit); void MACvSetLongRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit); -void MACvGetLongRetryLimit(void __iomem *dwIoBase, unsigned char *pbyRetryLimit); +void MACvGetLongRetryLimit(void __iomem *dwIoBase, + unsigned char *pbyRetryLimit); void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode); @@ -975,22 +978,32 @@ bool MACbSafeTxOff(void __iomem *dwIoBase); bool MACbSafeStop(void __iomem *dwIoBase); bool MACbShutdown(void __iomem *dwIoBase); void MACvInitialize(void __iomem *dwIoBase); -void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrSyncDescAddrEx(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); -void MACvSetCurrATIMDescAddrEx(void __iomem *dwIoBase, unsigned long dwCurrDescAddr); +void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrSyncDescAddrEx(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); +void MACvSetCurrATIMDescAddrEx(void __iomem *dwIoBase, + unsigned long dwCurrDescAddr); void MACvTimer0MicroSDelay(void __iomem *dwIoBase, unsigned int uDelay); void MACvOneShotTimer1MicroSec(void __iomem *dwIoBase, unsigned int uDelayTime); -void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset, unsigned long dwData); +void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset, + unsigned long dwData); bool MACbPSWakeup(void __iomem *dwIoBase); -void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, unsigned int uEntryIdx, - unsigned int uKeyIdx, unsigned char *pbyAddr, u32 *pdwKey, unsigned char byLocalID); +void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, + unsigned int uEntryIdx, unsigned int uKeyIdx, + unsigned char *pbyAddr, u32 *pdwKey, + unsigned char byLocalID); void MACvDisableKeyEntry(void __iomem *dwIoBase, unsigned int uEntryIdx); #endif /* __MAC_H__ */ -- cgit v0.10.2 From 0d12e05799e91465f6a0a9c0a983d06d40efdaf6 Mon Sep 17 00:00:00 2001 From: Emrys Bayliss Date: Fri, 16 Jan 2015 03:29:26 +1100 Subject: Staging: vt6655: comment headings formatting This patch makes the formatting of the comments in mac.h more consistent. * Where a heading takes up three comment lines it is reduced to one. * A newline always separates column headings Signed-off-by: Emrys Bayliss Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index d1a56cb..9be9bf8 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -38,9 +38,7 @@ #include "upc.h" /*--------------------- Export Definitions -------------------------*/ -// // Registers in the MAC -// #define MAC_MAX_CONTEXT_SIZE_PAGE0 256 #define MAC_MAX_CONTEXT_SIZE_PAGE1 128 @@ -69,6 +67,7 @@ #define MAC_REG_TMCTL0 0x18 #define MAC_REG_TMCTL1 0x19 #define MAC_REG_TMDATA0 0x1C + // MAC Parameter related #define MAC_REG_LRT 0x20 #define MAC_REG_SRT 0x21 @@ -85,11 +84,13 @@ #define MAC_REG_RTSFAILCNT 0x2D #define MAC_REG_ACKFAILCNT 0x2E #define MAC_REG_FCSERRCNT 0x2F + // TSF Related #define MAC_REG_TSFCNTR 0x30 #define MAC_REG_NEXTTBTT 0x38 #define MAC_REG_TSFOFST 0x40 #define MAC_REG_TFTCTL 0x48 + // WMAC Control/Status Related #define MAC_REG_ENCFG 0x4C #define MAC_REG_PAGE1SEL 0x4F @@ -101,6 +102,7 @@ #define MAC_REG_TCR 0x57 #define MAC_REG_IMR 0x58 #define MAC_REG_ISR 0x5C + // Power Saving Related #define MAC_REG_PSCFG 0x60 #define MAC_REG_PSCTL 0x61 @@ -112,6 +114,7 @@ #define MAC_REG_CALTMR 0x69 #define MAC_REG_SYNSPACCNT 0x6A #define MAC_REG_WAKSYNOPT 0x6B + // Baseband/IF Control Group #define MAC_REG_BBREGCTL 0x6C #define MAC_REG_CHANNEL 0x6D @@ -140,12 +143,15 @@ #define MAC_REG_SYNCDMAPTR 0xA8 #define MAC_REG_ATIMDMACTL 0xAC #define MAC_REG_ATIMDMAPTR 0xB0 + // MiscFF PIO related #define MAC_REG_MISCFFNDEX 0xB4 #define MAC_REG_MISCFFCTL 0xB6 #define MAC_REG_MISCFFDATA 0xB8 + // Extend SW Timer #define MAC_REG_TMDATA1 0xBC + // WOW Related Group #define MAC_REG_WAKEUPEN0 0xC0 #define MAC_REG_WAKEUPEN1 0xC1 @@ -161,6 +167,7 @@ #define MAC_REG_CRC_128_1 0x06 #define MAC_REG_CRC_128_2 0x08 #define MAC_REG_CRC_128_3 0x0A + // MAC Configuration Group #define MAC_REG_PAR0 0x0C #define MAC_REG_PAR4 0x10 @@ -168,6 +175,7 @@ #define MAC_REG_BSSID4 0x18 #define MAC_REG_MAR0 0x1C #define MAC_REG_MAR4 0x20 + // MAC RSPPKT INFO Group #define MAC_REG_RSPINF_B_1 0x24 #define MAC_REG_RSPINF_B_2 0x28 @@ -195,9 +203,7 @@ #define MAC_REG_PWRCCK 0x73 #define MAC_REG_PWROFDM 0x7C -// // Bits in the BCFG0 register -// #define BCFG0_PERROFF 0x40 #define BCFG0_MRDMDIS 0x20 #define BCFG0_MRDLDIS 0x10 @@ -205,9 +211,7 @@ #define BCFG0_VSERREN 0x02 #define BCFG0_LATMEN 0x01 -// // Bits in the BCFG1 register -// #define BCFG1_CFUNOPT 0x80 #define BCFG1_CREQOPT 0x40 #define BCFG1_DMA8 0x10 @@ -232,9 +236,7 @@ #define BISTSR2_CMDPRTEN 0x02 #define BISTSR2_RAMTSTEN 0x01 -// // Bits in the I2MCFG EEPROM register -// #define I2MCFG_BOUNDCTL 0x80 #define I2MCFG_WAITCTL 0x20 #define I2MCFG_SCLOECTL 0x10 @@ -243,38 +245,28 @@ #define I2MCFG_I2MLDSEQ 0x02 #define I2MCFG_I2CMFAST 0x01 -// // Bits in the I2MCSR EEPROM register -// #define I2MCSR_EEMW 0x80 #define I2MCSR_EEMR 0x40 #define I2MCSR_AUTOLD 0x08 #define I2MCSR_NACK 0x02 #define I2MCSR_DONE 0x01 -// // Bits in the PMC1 register -// #define SPS_RST 0x80 #define PCISTIKY 0x40 #define PME_OVR 0x02 -// // Bits in the STICKYHW register -// #define STICKHW_DS1_SHADOW 0x02 #define STICKHW_DS0_SHADOW 0x01 -// // Bits in the TMCTL register -// #define TMCTL_TSUSP 0x04 #define TMCTL_TMD 0x02 #define TMCTL_TE 0x01 -// // Bits in the TFTCTL register -// #define TFTCTL_HWUTSF 0x80 #define TFTCTL_TBTTSYNC 0x40 #define TFTCTL_HWUTSFEN 0x20 @@ -284,9 +276,7 @@ #define TFTCTL_TSFCNTRST 0x02 #define TFTCTL_TSFCNTREN 0x01 -// // Bits in the EnhanceCFG register -// #define EnCFG_BarkerPream 0x00020000 #define EnCFG_NXTBTTCFPSTR 0x00010000 #define EnCFG_BcnSusClr 0x00000200 @@ -300,14 +290,10 @@ #define EnCFG_BBType_b 0x00000001 #define EnCFG_BBType_a 0x00000000 -// // Bits in the Page1Sel register -// #define PAGE1_SEL 0x01 -// // Bits in the CFG register -// #define CFG_TKIPOPT 0x80 #define CFG_RXDMAOPT 0x40 #define CFG_TMOT_SW 0x20 @@ -318,9 +304,7 @@ #define CFG_NOTXTIMEOUT 0x02 #define CFG_NOBUFOPT 0x01 -// // Bits in the TEST register -// #define TEST_LBEXT 0x80 #define TEST_LBINT 0x40 #define TEST_LBNONE 0x00 @@ -331,9 +315,7 @@ #define TEST_NOCTS 0x02 #define TEST_NOACK 0x01 -// // Bits in the HOSTCR register -// #define HOSTCR_TXONST 0x80 #define HOSTCR_RXONST 0x40 #define HOSTCR_ADHOC 0x20 /* Network Type 1 = Ad-hoc */ @@ -343,21 +325,17 @@ #define HOSTCR_MACEN 0x02 /* 0000 0010 */ #define HOSTCR_SOFTRST 0x01 /* 0000 0001 */ -// // Bits in the MACCR register -// #define MACCR_SYNCFLUSHOK 0x04 #define MACCR_SYNCFLUSH 0x02 #define MACCR_CLRNAV 0x01 // Bits in the MAC_REG_GPIOCTL0 register -// #define LED_ACTSET 0x01 #define LED_RFOFF 0x02 #define LED_NOCONNECT 0x04 -// + // Bits in the RCR register -// #define RCR_SSID 0x80 #define RCR_RXALLTYPE 0x40 #define RCR_UNICAST 0x20 @@ -367,15 +345,11 @@ #define RCR_ERRCRC 0x02 #define RCR_BSSID 0x01 -// // Bits in the TCR register -// #define TCR_SYNCDCFOPT 0x02 #define TCR_AUTOBCNTX 0x01 /* Beacon automatically transmit enable */ -// // Bits in the IMR register -// #define IMR_MEASURESTART 0x80000000 #define IMR_QUIETSTART 0x20000000 #define IMR_RADARDETECT 0x10000000 @@ -395,10 +369,7 @@ #define IMR_AC0DMA 0x00000002 #define IMR_TXDMA0 0x00000001 -// // Bits in the ISR register -// - #define ISR_MEASURESTART 0x80000000 #define ISR_QUIETSTART 0x20000000 #define ISR_RADARDETECT 0x10000000 @@ -418,9 +389,7 @@ #define ISR_AC0DMA 0x00000002 #define ISR_TXDMA0 0x00000001 -// // Bits in the PSCFG register -// #define PSCFG_PHILIPMD 0x40 #define PSCFG_WAKECALEN 0x20 #define PSCFG_WAKETMREN 0x10 @@ -429,9 +398,7 @@ #define PSCFG_SLEEPSYN 0x02 #define PSCFG_AUTOSLEEP 0x01 -// // Bits in the PSCTL register -// #define PSCTL_WAKEDONE 0x20 #define PSCTL_PS 0x10 #define PSCTL_GO2DOZE 0x08 @@ -439,9 +406,7 @@ #define PSCTL_ALBCN 0x02 #define PSCTL_PSEN 0x01 -// // Bits in the PSPWSIG register -// #define PSSIG_WPE3 0x80 #define PSSIG_WPE2 0x40 #define PSSIG_WPE1 0x20 @@ -451,23 +416,17 @@ #define PSSIG_SPE1 0x02 #define PSSIG_SRADIOPE 0x01 -// // Bits in the BBREGCTL register -// #define BBREGCTL_DONE 0x04 #define BBREGCTL_REGR 0x02 #define BBREGCTL_REGW 0x01 -// // Bits in the IFREGCTL register -// #define IFREGCTL_DONE 0x04 #define IFREGCTL_IFRF 0x02 #define IFREGCTL_REGW 0x01 -// // Bits in the SOFTPWRCTL register -// #define SOFTPWRCTL_RFLEOPT 0x0800 #define SOFTPWRCTL_TXPEINV 0x0200 #define SOFTPWRCTL_SWPECTI 0x0100 @@ -478,82 +437,63 @@ #define SOFTPWRCTL_SWPE1 0x0002 #define SOFTPWRCTL_SWPE3 0x0001 -// // Bits in the GPIOCTL1 register -// #define GPIO1_DATA1 0x20 #define GPIO1_MD1 0x10 #define GPIO1_DATA0 0x02 #define GPIO1_MD0 0x01 -// // Bits in the DMACTL register -// #define DMACTL_CLRRUN 0x00080000 #define DMACTL_RUN 0x00000008 #define DMACTL_WAKE 0x00000004 #define DMACTL_DEAD 0x00000002 #define DMACTL_ACTIVE 0x00000001 -// + // Bits in the RXDMACTL0 register -// #define RX_PERPKT 0x00000100 #define RX_PERPKTCLR 0x01000000 -// + // Bits in the BCNDMACTL register -// #define BEACON_READY 0x01 -// + // Bits in the MISCFFCTL register -// #define MISCFFCTL_WRITE 0x0001 -// // Bits in WAKEUPEN0 -// #define WAKEUPEN0_DIRPKT 0x10 #define WAKEUPEN0_LINKOFF 0x08 #define WAKEUPEN0_ATIMEN 0x04 #define WAKEUPEN0_TIMEN 0x02 #define WAKEUPEN0_MAGICEN 0x01 -// // Bits in WAKEUPEN1 -// #define WAKEUPEN1_128_3 0x08 #define WAKEUPEN1_128_2 0x04 #define WAKEUPEN1_128_1 0x02 #define WAKEUPEN1_128_0 0x01 -// // Bits in WAKEUPSR0 -// #define WAKEUPSR0_DIRPKT 0x10 #define WAKEUPSR0_LINKOFF 0x08 #define WAKEUPSR0_ATIMEN 0x04 #define WAKEUPSR0_TIMEN 0x02 #define WAKEUPSR0_MAGICEN 0x01 -// // Bits in WAKEUPSR1 -// #define WAKEUPSR1_128_3 0x08 #define WAKEUPSR1_128_2 0x04 #define WAKEUPSR1_128_1 0x02 #define WAKEUPSR1_128_0 0x01 -// // Bits in the MAC_REG_GPIOCTL register -// #define GPIO0_MD 0x01 #define GPIO0_DATA 0x02 #define GPIO0_INTMD 0x04 #define GPIO1_MD 0x10 #define GPIO1_DATA 0x20 -// // Bits in the MSRCTL register -// #define MSRCTL_FINISH 0x80 #define MSRCTL_READY 0x40 #define MSRCTL_RADARDETECT 0x20 @@ -562,9 +502,8 @@ #define MSRCTL_QUIETRPT 0x04 #define MSRCTL_QUIETINT 0x02 #define MSRCTL_QUIETEN 0x01 -// + // Bits in the MSRCTL1 register -// #define MSRCTL1_TXPWR 0x08 #define MSRCTL1_CSAPAREN 0x04 #define MSRCTL1_TXPAUSE 0x01 @@ -605,9 +544,7 @@ // wait time within loop #define CB_DELAY_LOOP_WAIT 10 /* 10ms */ -// // revision id -// #define REV_ID_VT3253_A0 0x00 #define REV_ID_VT3253_A1 0x01 #define REV_ID_VT3253_B0 0x08 -- cgit v0.10.2 From 12b79518fb67f22a8d4b93213e3dd0caf7c6697f Mon Sep 17 00:00:00 2001 From: Emrys Bayliss Date: Fri, 16 Jan 2015 03:29:27 +1100 Subject: Staging: vt6655: Checkpatch fix: c99 comment headings This patch fixes some of the following checkpatch.pl errors in mac.h ERROR: do not use C99 // comments This patch reformats all single line c99 style comments to the preferred style. Signed-off-by: Emrys Bayliss Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index 9be9bf8..8e0200a 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -38,11 +38,11 @@ #include "upc.h" /*--------------------- Export Definitions -------------------------*/ -// Registers in the MAC +/* Registers in the MAC */ #define MAC_MAX_CONTEXT_SIZE_PAGE0 256 #define MAC_MAX_CONTEXT_SIZE_PAGE1 128 -// Registers not related to 802.11b +/* Registers not related to 802.11b */ #define MAC_REG_BCFG0 0x00 #define MAC_REG_BCFG1 0x01 #define MAC_REG_FCR0 0x02 @@ -68,7 +68,7 @@ #define MAC_REG_TMCTL1 0x19 #define MAC_REG_TMDATA0 0x1C -// MAC Parameter related +/* MAC Parameter related */ #define MAC_REG_LRT 0x20 #define MAC_REG_SRT 0x21 #define MAC_REG_SIFS 0x22 @@ -85,13 +85,13 @@ #define MAC_REG_ACKFAILCNT 0x2E #define MAC_REG_FCSERRCNT 0x2F -// TSF Related +/* TSF Related */ #define MAC_REG_TSFCNTR 0x30 #define MAC_REG_NEXTTBTT 0x38 #define MAC_REG_TSFOFST 0x40 #define MAC_REG_TFTCTL 0x48 -// WMAC Control/Status Related +/* WMAC Control/Status Related */ #define MAC_REG_ENCFG 0x4C #define MAC_REG_PAGE1SEL 0x4F #define MAC_REG_CFG 0x50 @@ -103,7 +103,7 @@ #define MAC_REG_IMR 0x58 #define MAC_REG_ISR 0x5C -// Power Saving Related +/* Power Saving Related */ #define MAC_REG_PSCFG 0x60 #define MAC_REG_PSCTL 0x61 #define MAC_REG_PSPWRSIG 0x62 @@ -115,7 +115,7 @@ #define MAC_REG_SYNSPACCNT 0x6A #define MAC_REG_WAKSYNOPT 0x6B -// Baseband/IF Control Group +/* Baseband/IF Control Group */ #define MAC_REG_BBREGCTL 0x6C #define MAC_REG_CHANNEL 0x6D #define MAC_REG_BBREGADR 0x6E @@ -128,7 +128,7 @@ #define MAC_REG_GPIOCTL0 0x7A #define MAC_REG_GPIOCTL1 0x7B -// MAC DMA Related Group +/* MAC DMA Related Group */ #define MAC_REG_TXDMACTL0 0x7C #define MAC_REG_TXDMAPTR0 0x80 #define MAC_REG_AC0DMACTL 0x84 @@ -144,15 +144,15 @@ #define MAC_REG_ATIMDMACTL 0xAC #define MAC_REG_ATIMDMAPTR 0xB0 -// MiscFF PIO related +/* MiscFF PIO related */ #define MAC_REG_MISCFFNDEX 0xB4 #define MAC_REG_MISCFFCTL 0xB6 #define MAC_REG_MISCFFDATA 0xB8 -// Extend SW Timer +/* Extend SW Timer */ #define MAC_REG_TMDATA1 0xBC -// WOW Related Group +/* WOW Related Group */ #define MAC_REG_WAKEUPEN0 0xC0 #define MAC_REG_WAKEUPEN1 0xC1 #define MAC_REG_WAKEUPSR0 0xC2 @@ -162,13 +162,13 @@ #define MAC_REG_WAKE128_2 0xE4 #define MAC_REG_WAKE128_3 0xF4 -/////////////// Page 1 /////////////////// +/************** Page 1 ******************/ #define MAC_REG_CRC_128_0 0x04 #define MAC_REG_CRC_128_1 0x06 #define MAC_REG_CRC_128_2 0x08 #define MAC_REG_CRC_128_3 0x0A -// MAC Configuration Group +/* MAC Configuration Group */ #define MAC_REG_PAR0 0x0C #define MAC_REG_PAR4 0x10 #define MAC_REG_BSSID0 0x14 @@ -176,7 +176,7 @@ #define MAC_REG_MAR0 0x1C #define MAC_REG_MAR4 0x20 -// MAC RSPPKT INFO Group +/* MAC RSPPKT INFO Group */ #define MAC_REG_RSPINF_B_1 0x24 #define MAC_REG_RSPINF_B_2 0x28 #define MAC_REG_RSPINF_B_5 0x2C @@ -191,7 +191,7 @@ #define MAC_REG_RSPINF_A_54 0x42 #define MAC_REG_RSPINF_A_72 0x44 -// 802.11h relative +/* 802.11h relative */ #define MAC_REG_QUIETINIT 0x60 #define MAC_REG_QUIETGAP 0x62 #define MAC_REG_QUIETDUR 0x64 @@ -203,7 +203,7 @@ #define MAC_REG_PWRCCK 0x73 #define MAC_REG_PWROFDM 0x7C -// Bits in the BCFG0 register +/* Bits in the BCFG0 register */ #define BCFG0_PERROFF 0x40 #define BCFG0_MRDMDIS 0x20 #define BCFG0_MRDLDIS 0x10 @@ -211,7 +211,7 @@ #define BCFG0_VSERREN 0x02 #define BCFG0_LATMEN 0x01 -// Bits in the BCFG1 register +/* Bits in the BCFG1 register */ #define BCFG1_CFUNOPT 0x80 #define BCFG1_CREQOPT 0x40 #define BCFG1_DMA8 0x10 @@ -220,7 +220,7 @@ #define BCFG1_MIOEN 0x02 #define BCFG1_CISDLYEN 0x01 -// Bits in RAMBIST registers +/* Bits in RAMBIST registers */ #define BISTCMD_TSTPAT5 0x00 #define BISTCMD_TSTPATA 0x80 #define BISTCMD_TSTERR 0x20 @@ -236,7 +236,7 @@ #define BISTSR2_CMDPRTEN 0x02 #define BISTSR2_RAMTSTEN 0x01 -// Bits in the I2MCFG EEPROM register +/* Bits in the I2MCFG EEPROM register */ #define I2MCFG_BOUNDCTL 0x80 #define I2MCFG_WAITCTL 0x20 #define I2MCFG_SCLOECTL 0x10 @@ -245,28 +245,28 @@ #define I2MCFG_I2MLDSEQ 0x02 #define I2MCFG_I2CMFAST 0x01 -// Bits in the I2MCSR EEPROM register +/* Bits in the I2MCSR EEPROM register */ #define I2MCSR_EEMW 0x80 #define I2MCSR_EEMR 0x40 #define I2MCSR_AUTOLD 0x08 #define I2MCSR_NACK 0x02 #define I2MCSR_DONE 0x01 -// Bits in the PMC1 register +/* Bits in the PMC1 register */ #define SPS_RST 0x80 #define PCISTIKY 0x40 #define PME_OVR 0x02 -// Bits in the STICKYHW register +/* Bits in the STICKYHW register */ #define STICKHW_DS1_SHADOW 0x02 #define STICKHW_DS0_SHADOW 0x01 -// Bits in the TMCTL register +/* Bits in the TMCTL register */ #define TMCTL_TSUSP 0x04 #define TMCTL_TMD 0x02 #define TMCTL_TE 0x01 -// Bits in the TFTCTL register +/* Bits in the TFTCTL register */ #define TFTCTL_HWUTSF 0x80 #define TFTCTL_TBTTSYNC 0x40 #define TFTCTL_HWUTSFEN 0x20 @@ -276,7 +276,7 @@ #define TFTCTL_TSFCNTRST 0x02 #define TFTCTL_TSFCNTREN 0x01 -// Bits in the EnhanceCFG register +/* Bits in the EnhanceCFG register */ #define EnCFG_BarkerPream 0x00020000 #define EnCFG_NXTBTTCFPSTR 0x00010000 #define EnCFG_BcnSusClr 0x00000200 @@ -290,10 +290,10 @@ #define EnCFG_BBType_b 0x00000001 #define EnCFG_BBType_a 0x00000000 -// Bits in the Page1Sel register +/* Bits in the Page1Sel register */ #define PAGE1_SEL 0x01 -// Bits in the CFG register +/* Bits in the CFG register */ #define CFG_TKIPOPT 0x80 #define CFG_RXDMAOPT 0x40 #define CFG_TMOT_SW 0x20 @@ -304,7 +304,7 @@ #define CFG_NOTXTIMEOUT 0x02 #define CFG_NOBUFOPT 0x01 -// Bits in the TEST register +/* Bits in the TEST register */ #define TEST_LBEXT 0x80 #define TEST_LBINT 0x40 #define TEST_LBNONE 0x00 @@ -315,7 +315,7 @@ #define TEST_NOCTS 0x02 #define TEST_NOACK 0x01 -// Bits in the HOSTCR register +/* Bits in the HOSTCR register */ #define HOSTCR_TXONST 0x80 #define HOSTCR_RXONST 0x40 #define HOSTCR_ADHOC 0x20 /* Network Type 1 = Ad-hoc */ @@ -325,17 +325,17 @@ #define HOSTCR_MACEN 0x02 /* 0000 0010 */ #define HOSTCR_SOFTRST 0x01 /* 0000 0001 */ -// Bits in the MACCR register +/* Bits in the MACCR register */ #define MACCR_SYNCFLUSHOK 0x04 #define MACCR_SYNCFLUSH 0x02 #define MACCR_CLRNAV 0x01 -// Bits in the MAC_REG_GPIOCTL0 register +/* Bits in the MAC_REG_GPIOCTL0 register */ #define LED_ACTSET 0x01 #define LED_RFOFF 0x02 #define LED_NOCONNECT 0x04 -// Bits in the RCR register +/* Bits in the RCR register */ #define RCR_SSID 0x80 #define RCR_RXALLTYPE 0x40 #define RCR_UNICAST 0x20 @@ -345,11 +345,11 @@ #define RCR_ERRCRC 0x02 #define RCR_BSSID 0x01 -// Bits in the TCR register +/* Bits in the TCR register */ #define TCR_SYNCDCFOPT 0x02 #define TCR_AUTOBCNTX 0x01 /* Beacon automatically transmit enable */ -// Bits in the IMR register +/* Bits in the IMR register */ #define IMR_MEASURESTART 0x80000000 #define IMR_QUIETSTART 0x20000000 #define IMR_RADARDETECT 0x10000000 @@ -369,7 +369,7 @@ #define IMR_AC0DMA 0x00000002 #define IMR_TXDMA0 0x00000001 -// Bits in the ISR register +/* Bits in the ISR register */ #define ISR_MEASURESTART 0x80000000 #define ISR_QUIETSTART 0x20000000 #define ISR_RADARDETECT 0x10000000 @@ -389,7 +389,7 @@ #define ISR_AC0DMA 0x00000002 #define ISR_TXDMA0 0x00000001 -// Bits in the PSCFG register +/* Bits in the PSCFG register */ #define PSCFG_PHILIPMD 0x40 #define PSCFG_WAKECALEN 0x20 #define PSCFG_WAKETMREN 0x10 @@ -398,7 +398,7 @@ #define PSCFG_SLEEPSYN 0x02 #define PSCFG_AUTOSLEEP 0x01 -// Bits in the PSCTL register +/* Bits in the PSCTL register */ #define PSCTL_WAKEDONE 0x20 #define PSCTL_PS 0x10 #define PSCTL_GO2DOZE 0x08 @@ -406,7 +406,7 @@ #define PSCTL_ALBCN 0x02 #define PSCTL_PSEN 0x01 -// Bits in the PSPWSIG register +/* Bits in the PSPWSIG register */ #define PSSIG_WPE3 0x80 #define PSSIG_WPE2 0x40 #define PSSIG_WPE1 0x20 @@ -416,17 +416,17 @@ #define PSSIG_SPE1 0x02 #define PSSIG_SRADIOPE 0x01 -// Bits in the BBREGCTL register +/* Bits in the BBREGCTL register */ #define BBREGCTL_DONE 0x04 #define BBREGCTL_REGR 0x02 #define BBREGCTL_REGW 0x01 -// Bits in the IFREGCTL register +/* Bits in the IFREGCTL register */ #define IFREGCTL_DONE 0x04 #define IFREGCTL_IFRF 0x02 #define IFREGCTL_REGW 0x01 -// Bits in the SOFTPWRCTL register +/* Bits in the SOFTPWRCTL register */ #define SOFTPWRCTL_RFLEOPT 0x0800 #define SOFTPWRCTL_TXPEINV 0x0200 #define SOFTPWRCTL_SWPECTI 0x0100 @@ -437,63 +437,63 @@ #define SOFTPWRCTL_SWPE1 0x0002 #define SOFTPWRCTL_SWPE3 0x0001 -// Bits in the GPIOCTL1 register +/* Bits in the GPIOCTL1 register */ #define GPIO1_DATA1 0x20 #define GPIO1_MD1 0x10 #define GPIO1_DATA0 0x02 #define GPIO1_MD0 0x01 -// Bits in the DMACTL register +/* Bits in the DMACTL register */ #define DMACTL_CLRRUN 0x00080000 #define DMACTL_RUN 0x00000008 #define DMACTL_WAKE 0x00000004 #define DMACTL_DEAD 0x00000002 #define DMACTL_ACTIVE 0x00000001 -// Bits in the RXDMACTL0 register +/* Bits in the RXDMACTL0 register */ #define RX_PERPKT 0x00000100 #define RX_PERPKTCLR 0x01000000 -// Bits in the BCNDMACTL register +/* Bits in the BCNDMACTL register */ #define BEACON_READY 0x01 -// Bits in the MISCFFCTL register +/* Bits in the MISCFFCTL register */ #define MISCFFCTL_WRITE 0x0001 -// Bits in WAKEUPEN0 +/* Bits in WAKEUPEN0 */ #define WAKEUPEN0_DIRPKT 0x10 #define WAKEUPEN0_LINKOFF 0x08 #define WAKEUPEN0_ATIMEN 0x04 #define WAKEUPEN0_TIMEN 0x02 #define WAKEUPEN0_MAGICEN 0x01 -// Bits in WAKEUPEN1 +/* Bits in WAKEUPEN1 */ #define WAKEUPEN1_128_3 0x08 #define WAKEUPEN1_128_2 0x04 #define WAKEUPEN1_128_1 0x02 #define WAKEUPEN1_128_0 0x01 -// Bits in WAKEUPSR0 +/* Bits in WAKEUPSR0 */ #define WAKEUPSR0_DIRPKT 0x10 #define WAKEUPSR0_LINKOFF 0x08 #define WAKEUPSR0_ATIMEN 0x04 #define WAKEUPSR0_TIMEN 0x02 #define WAKEUPSR0_MAGICEN 0x01 -// Bits in WAKEUPSR1 +/* Bits in WAKEUPSR1 */ #define WAKEUPSR1_128_3 0x08 #define WAKEUPSR1_128_2 0x04 #define WAKEUPSR1_128_1 0x02 #define WAKEUPSR1_128_0 0x01 -// Bits in the MAC_REG_GPIOCTL register +/* Bits in the MAC_REG_GPIOCTL register */ #define GPIO0_MD 0x01 #define GPIO0_DATA 0x02 #define GPIO0_INTMD 0x04 #define GPIO1_MD 0x10 #define GPIO1_DATA 0x20 -// Bits in the MSRCTL register +/* Bits in the MSRCTL register */ #define MSRCTL_FINISH 0x80 #define MSRCTL_READY 0x40 #define MSRCTL_RADARDETECT 0x20 @@ -503,26 +503,26 @@ #define MSRCTL_QUIETINT 0x02 #define MSRCTL_QUIETEN 0x01 -// Bits in the MSRCTL1 register +/* Bits in the MSRCTL1 register */ #define MSRCTL1_TXPWR 0x08 #define MSRCTL1_CSAPAREN 0x04 #define MSRCTL1_TXPAUSE 0x01 -// Loopback mode +/* Loopback mode */ #define MAC_LB_EXT 0x02 #define MAC_LB_INTERNAL 0x01 #define MAC_LB_NONE 0x00 #define Default_BI 0x200 -// MiscFIFO Offset +/* MiscFIFO Offset */ #define MISCFIFO_KEYETRY0 32 #define MISCFIFO_KEYENTRYSIZE 22 #define MISCFIFO_SYNINFO_IDX 10 #define MISCFIFO_SYNDATA_IDX 11 #define MISCFIFO_SYNDATASIZE 21 -// enabled mask value of irq +/* enabled mask value of irq */ #define IMR_MASK_VALUE (IMR_SOFTTIMER1 | \ IMR_RXDMA1 | \ IMR_RXNOBUF | \ @@ -538,13 +538,13 @@ IMR_AC0DMA | \ IMR_TXDMA0) -// max time out delay time +/* max time out delay time */ #define W_MAX_TIMEOUT 0xFFF0U -// wait time within loop +/* wait time within loop */ #define CB_DELAY_LOOP_WAIT 10 /* 10ms */ -// revision id +/* revision id */ #define REV_ID_VT3253_A0 0x00 #define REV_ID_VT3253_A1 0x01 #define REV_ID_VT3253_B0 0x08 @@ -628,12 +628,12 @@ do { \ VNSvInPortD(dwIoBase + MAC_REG_ATIMDMAPTR, \ (unsigned long *)pdwCurrDescAddr) -// set the chip with current BCN tx descriptor address +/* set the chip with current BCN tx descriptor address */ #define MACvSetCurrBCNTxDescAddr(dwIoBase, dwCurrDescAddr) \ VNSvOutPortD(dwIoBase + MAC_REG_BCNDMAPTR, \ dwCurrDescAddr) -// set the chip with current BCN length +/* set the chip with current BCN length */ #define MACvSetCurrBCNLength(dwIoBase, wCurrBCNLength) \ VNSvOutPortW(dwIoBase + MAC_REG_BCNDMACTL+2, \ wCurrBCNLength) -- cgit v0.10.2 From 2fc6aa5d745477b995708b3edc601525367edbd4 Mon Sep 17 00:00:00 2001 From: Robert Nachlinger Date: Thu, 18 Dec 2014 17:57:06 +0100 Subject: Staging: gdm724x: fix space before comma coding style issue in gdm_mux.c This is a patch to the gdm_mux.c file that fixes a space before comma coding style issue found by the checkpatch.pl tool. Signed-off-by: Robert Nachlinger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c index b5b063a..d1ab996 100644 --- a/drivers/staging/gdm724x/gdm_mux.c +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -220,7 +220,7 @@ static int up_to_host(struct mux_rx *r) static void do_rx(struct work_struct *work) { struct mux_dev *mux_dev = - container_of(work, struct mux_dev , work_rx.work); + container_of(work, struct mux_dev, work_rx.work); struct mux_rx *r; struct rx_cxt *rx = (struct rx_cxt *)&mux_dev->rx; unsigned long flags; -- cgit v0.10.2 From 59215e694f217dcd45169f4670cffe8fbb553303 Mon Sep 17 00:00:00 2001 From: Ning Zhou Date: Sun, 4 Jan 2015 10:06:17 +0100 Subject: staging: gdm724x: fix line limit coding style issue in gdm_lte.c This is a patch to fix "WARNING: line over 80 characters" found by checkpatch.pl in gdm_lte.c. Signed-off-by: Ning Zhou Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index 73eede1..7c4a77b 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -281,7 +281,8 @@ static int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type) icmp6_out.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; icmp6_out.icmp6_code = 0; icmp6_out.icmp6_cksum = 0; - icmp6_out.icmp6_dataun.un_data32[0] = htonl(0x60000000); /* R=0, S=1, O=1 */ + /* R=0, S=1, O=1 */ + icmp6_out.icmp6_dataun.un_data32[0] = htonl(0x60000000); ns = (struct neighbour_solicitation *) (skb_in->data + mac_header_len + -- cgit v0.10.2 From 85fdebc3ed5e5670dcc549fe68d99c0ffb2e595e Mon Sep 17 00:00:00 2001 From: Jamie Lawler Date: Thu, 4 Dec 2014 13:02:23 +0000 Subject: Staging: octeon: Add blank lines after declarations There are 2 missing blank lines after variable declarations in octeon/ethernet-rx.c. They have been added per the coding style. Signed-off-by: Jamie Lawler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index fcbe836..22667db 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -109,6 +109,7 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work) int interface = cvmx_helper_get_interface_num(work->ipprt); int index = cvmx_helper_get_interface_index_num(work->ipprt); union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; + gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface)); if (gmxx_rxx_frm_ctl.s.pre_chk == 0) { @@ -214,6 +215,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) did_work_request = 0; if (work == NULL) { union cvmx_pow_wq_int wq_int; + wq_int.u64 = 0; wq_int.s.iq_dis = 1 << pow_receive_group; wq_int.s.wq_int = 1 << pow_receive_group; -- cgit v0.10.2 From f5801a81762336909c02e8c2ffef48a9084a258f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 11 Jan 2015 15:44:39 -0600 Subject: Staging: octeon: Fixed a typo Fixed a typo in ethernet.c file. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index ee32149..460e854 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -798,7 +798,7 @@ static int cvm_oct_probe(struct platform_device *pdev) cvm_oct_rx_initialize(); /* - * 150 uS: about 10 1500-byte packtes at 1GE. + * 150 uS: about 10 1500-byte packets at 1GE. */ cvm_oct_tx_poll_interval = 150 * (octeon_get_clock_rate() / 1000000); -- cgit v0.10.2 From 1cf3273dfbd7918fd43e0c70c65795a89f8e88d7 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 11 Jan 2015 15:50:37 -0600 Subject: Staging: octeon-usb: Fixed a typo Fixed a typo in octeon-hcd.c file Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 6b8b108..1daeb31 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -2687,7 +2687,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) /* * Read the channel config info so we can figure out how much data - * transfered + * transferred */ usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); -- cgit v0.10.2 From d7312aab230f975b8ec41c0055a17f0d395b7fb5 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 20 Dec 2014 00:51:26 +0300 Subject: staging: dgnc: implement proper error handling in dgnc_start() dgnc_start() ignores errors in class_create() and device_create() and it does not deallocate resources if dgnc_tty_preinit() fails. The patch implements proper error handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index ba98ff3..f610ae1 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -238,6 +238,7 @@ static int dgnc_start(void) { int rc = 0; unsigned long flags; + struct device *dev; /* make sure that the globals are init'd before we do anything else */ dgnc_init_globals(); @@ -257,9 +258,20 @@ static int dgnc_start(void) dgnc_Major = rc; dgnc_class = class_create(THIS_MODULE, "dgnc_mgmt"); - device_create(dgnc_class, NULL, - MKDEV(dgnc_Major, 0), - NULL, "dgnc_mgmt"); + if (IS_ERR(dgnc_class)) { + rc = PTR_ERR(dgnc_class); + pr_err(DRVSTR ": Can't create dgnc_mgmt class (%d)\n", rc); + goto failed_class; + } + + dev = device_create(dgnc_class, NULL, + MKDEV(dgnc_Major, 0), + NULL, "dgnc_mgmt"); + if (IS_ERR(dev)) { + rc = PTR_ERR(dev); + pr_err(DRVSTR ": Can't create device (%d)\n", rc); + goto failed_device; + } /* * Init any global tty stuff. @@ -268,7 +280,7 @@ static int dgnc_start(void) if (rc < 0) { pr_err(DRVSTR ": tty preinit - not enough memory (%d)\n", rc); - return rc; + goto failed_tty; } /* Start the poller */ @@ -282,6 +294,14 @@ static int dgnc_start(void) add_timer(&dgnc_poll_timer); + return 0; + +failed_tty: + device_destroy(dgnc_class, MKDEV(dgnc_Major, 0)); +failed_device: + class_destroy(dgnc_class); +failed_class: + unregister_chrdev(dgnc_Major, "dgnc"); return rc; } -- cgit v0.10.2 From 1fab3fde75dc1d783d0fe1602325766f7e0decf3 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Mon, 22 Dec 2014 08:20:38 -0700 Subject: staging: skein: Fixing trailing whitespace error Signed-off-by: Mathieu Poirier Acked-by: Jason Cooper Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/skein/skein_generic.c b/drivers/staging/skein/skein_generic.c index 85bd7d0..899078f 100644 --- a/drivers/staging/skein/skein_generic.c +++ b/drivers/staging/skein/skein_generic.c @@ -191,7 +191,6 @@ static int __init skein_generic_init(void) return 0; - unreg512: crypto_unregister_shash(&alg512); unreg256: -- cgit v0.10.2 From b6fe6e06080df175d011a5ececa4a7559fe5fd95 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Mon, 22 Dec 2014 08:20:39 -0700 Subject: staging: skein: Fixing single statement macro checkpatch warning WARNING: Single statement macros should not use a do {} while (0) loop Signed-off-by: Mathieu Poirier Acked-by: Jason Cooper Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/skein/skein_block.c b/drivers/staging/skein/skein_block.c index 66261ab..9bd69ce 100644 --- a/drivers/staging/skein/skein_block.c +++ b/drivers/staging/skein/skein_block.c @@ -82,10 +82,7 @@ do { \ } while (0) #else /* looping version */ -#define R256(p0, p1, p2, p3, ROT, r_num) \ -do { \ - ROUND256(p0, p1, p2, p3, ROT, r_num); \ -} while (0) +#define R256(p0, p1, p2, p3, ROT, r_num) ROUND256(p0, p1, p2, p3, ROT, r_num) #define I256(R) \ do { \ @@ -174,9 +171,7 @@ do { \ #else /* looping version */ #define R512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num) \ -do { \ - ROUND512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num); \ -} while (0) + ROUND512(p0, p1, p2, p3, p4, p5, p6, p7, ROT, r_num) \ #define I512(R) \ do { \ @@ -263,10 +258,8 @@ do { \ #if SKEIN_UNROLL_1024 == 0 #define R1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, pF, \ ROT, rn) \ -do { \ ROUND1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, \ - pF, ROT, rn); \ -} while (0) + pF, ROT, rn) \ #define I1024(R) \ do { \ @@ -291,10 +284,8 @@ do { \ #else /* looping version */ #define R1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, pF, \ ROT, rn) \ -do { \ ROUND1024(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pA, pB, pC, pD, pE, \ - pF, ROT, rn); \ -} while (0) + pF, ROT, rn) \ #define I1024(R) \ do { \ -- cgit v0.10.2 From 22b9c2a89fb3297007a5d81d4cab5ffd547e2642 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 11 Jan 2015 16:00:33 -0600 Subject: Staging: olpc_dcon: Fixed a typo Fixed a typo in olpc_dcon_xo_1.c file. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c index 77e8eb5..0c5a10c 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c +++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c @@ -52,7 +52,7 @@ static int dcon_init_xo_1(struct dcon_priv *dcon) * Determine the current state by reading the GPIO bit; earlier * stages of the boot process have established the state. * - * Note that we read GPIO_OUPUT_VAL rather than GPIO_READ_BACK here; + * Note that we read GPIO_OUTPUT_VAL rather than GPIO_READ_BACK here; * this is because OFW will disable input for the pin and set a value.. * READ_BACK will only contain a valid value if input is enabled and * then a value is set. So, future readings of the pin can use -- cgit v0.10.2 From 88789fabd76566f9e70a7023b296694fdd4748c8 Mon Sep 17 00:00:00 2001 From: tolga ceylan Date: Fri, 16 Jan 2015 22:16:13 -0800 Subject: Staging: NetLogic: Coding style correction Misspelled comment corrected Signed-off-by: tolga ceylan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index 5ecb3e6..e8aae09 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -788,7 +788,7 @@ void xlr_set_gmac_speed(struct xlr_net_priv *priv) xlr_nae_wreg(priv->base_addr, R_MAC_CONFIG_2, 0x7117); priv->phy_speed = speed; } - /* Set SGMII speed in Interface controll reg */ + /* Set SGMII speed in Interface control reg */ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { if (speed == SPEED_10) xlr_nae_wreg(priv->base_addr, -- cgit v0.10.2 From 4e8e87162e839286fbce2d68e8341a1e53066630 Mon Sep 17 00:00:00 2001 From: Murilo Opsfelder Araujo Date: Thu, 15 Jan 2015 23:55:00 -0200 Subject: staging: olpc_dcon: fix sparse symbol not declared warning This patch gets rid of the following sparse warning: drivers/staging/olpc_dcon/olpc_dcon.c:787:19: warning: symbol 'dcon_driver' was not declared. Should it be static? Signed-off-by: Murilo Opsfelder Araujo Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c index 6a9a881..bc7e664 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ b/drivers/staging/olpc_dcon/olpc_dcon.c @@ -780,7 +780,7 @@ static const struct i2c_device_id dcon_idtable[] = { }; MODULE_DEVICE_TABLE(i2c, dcon_idtable); -struct i2c_driver dcon_driver = { +static struct i2c_driver dcon_driver = { .driver = { .name = "olpc_dcon", .pm = &dcon_pm_ops, -- cgit v0.10.2 From 9b872a74b8d15d388065ac7919555a5e036046dc Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 11 Jan 2015 15:49:13 -0600 Subject: Staging: nvec: Fixed a typo Fixed a typo in nvec.c file Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 093535c..2637059 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -259,7 +259,7 @@ static void nvec_gpio_set_value(struct nvec_chip *nvec, int value) * and return immediately. * * Returns: 0 on success, a negative error code on failure. If a failure - * occured, the nvec driver may print an error. + * occurred, the nvec driver may print an error. */ int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data, short size) -- cgit v0.10.2 From f37e90e9a15e03a4987790d192c4e7fceba2bdef Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 1 Jan 2015 17:23:13 +0100 Subject: staging: gs_fpgaboot: io.c: Remove unused function Remove the function bitswap() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Reviewed-by: Insop Song Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/gs_fpgaboot/io.c b/drivers/staging/gs_fpgaboot/io.c index b260e45..819db53 100644 --- a/drivers/staging/gs_fpgaboot/io.c +++ b/drivers/staging/gs_fpgaboot/io.c @@ -79,15 +79,6 @@ void xl_shift_bytes_out(enum wbus bus_byte, unsigned char *pdata) /* * generic bit swap for xilinx SYSTEMMAP FPGA programming */ -static inline unsigned char bitswap(unsigned char s) -{ - unsigned char d; - - d = (((s&0x80)>>7) | ((s&0x40)>>5) | ((s&0x20)>>3) | ((s&0x10)>>1) | - ((s&0x08)<<1) | ((s&0x04)<<3) | ((s&0x02)<<5) | ((s&0x01)<<7)); - return d; -} - void xl_program_b(int32_t i) { } -- cgit v0.10.2 From 0a5470f80ce7731160bbf8173e9df1ebeeb7e9e6 Mon Sep 17 00:00:00 2001 From: Dean Michael Ancajas Date: Mon, 8 Dec 2014 14:23:01 -0700 Subject: Staging: ft1000: ft1000-pcmcia: Fixed a coding style issue Fixed a coding style issue for braces. Signed-off-by: Dean Michael Ancajas Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index d5475b7..755beb7 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -172,11 +172,11 @@ u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index) spin_lock_irqsave(&info->dpram_lock, flags); ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); /* check if we want to read upper or lower 32-bit word */ - if (Index) { + if (Index) data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAL); - } else { + else data = ft1000_read_reg(dev, FT1000_REG_MAG_DPDATAH); - } + spin_unlock_irqrestore(&info->dpram_lock, flags); return data; -- cgit v0.10.2 From 64ed8f51f97304f811f34e89afdccf7bf9836a93 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Mon, 29 Dec 2014 13:41:33 +0100 Subject: staging: ft1000: ft1000-usb: ft1000_hw.c: Fix a potential memory leak. Avoid allocate memory if we will exit the function. Was found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c index d12cfc9..f0ac438 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c @@ -332,15 +332,15 @@ int card_send_command(struct ft1000_usb *ft1000dev, void *ptempbuffer, pr_debug("enter card_send_command... size=%d\n", size); + ret = ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL); + if (ret) + return ret; + commandbuf = kmalloc(size + 2, GFP_KERNEL); if (!commandbuf) return -ENOMEM; memcpy((void *)commandbuf + 2, (void *)ptempbuffer, size); - ret = ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL); - if (ret) - return ret; - if (temp & 0x0100) usleep_range(900, 1100); -- cgit v0.10.2 From fa2592cdc526ceef39a5176267ef040abeafd14c Mon Sep 17 00:00:00 2001 From: Austin Kerbow Date: Thu, 1 Jan 2015 20:29:56 -0800 Subject: Staging: ft1000-pcmcia: fix else close brace style Fix the following checkpatch.pl errors ERROR: else should follow close brace '}' + } + else { ERROR: else should follow close brace '}' + } + else { ERROR: else should follow close brace '}' + } + else { ERROR: else should follow close brace '}' + } + else { ERROR: else should follow close brace '}' + } + else { Signed-off-by: Austin Kerbow Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index 755beb7..5e0cdcf 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -570,12 +570,12 @@ static void ft1000_hbchk(u_long data) pr_debug("hi_ho value = 0x%x\n", tempword); /* Let's perform another check if ho is not detected */ if (tempword != ho) { - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) tempword = ft1000_read_dpram(dev, FT1000_HI_HO); - } - else { - tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX)); - } + else + tempword = ntohs(ft1000_read_dpram_mag_16(dev, + FT1000_MAG_HI_HO, + FT1000_MAG_HI_HO_INDX)); } if (tempword != ho) { pr_info("heartbeat failed - no ho detected\n"); @@ -686,19 +686,15 @@ static void ft1000_hbchk(u_long data) } /* Let's write hi again if fail */ if (tempword != hi) { - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) ft1000_write_dpram(dev, FT1000_HI_HO, hi); - } - else { + else ft1000_write_dpram_mag_16(dev, FT1000_MAG_HI_HO, hi_mag, FT1000_MAG_HI_HO_INDX); - } - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) tempword = ft1000_read_dpram(dev, FT1000_HI_HO); - } - else { + else tempword = ntohs(ft1000_read_dpram_mag_16(dev, FT1000_MAG_HI_HO, FT1000_MAG_HI_HO_INDX)); - } } @@ -957,12 +953,11 @@ static void ft1000_proc_drvmsg(struct net_device *dev) u16 wrd; } convert; - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) tempword = FT1000_DPRAM_RX_BASE+2; - } - else { + else tempword = FT1000_DPRAM_MAG_RX_BASE; - } + if (ft1000_receive_cmd(dev, &cmdbuffer[0], MAX_CMD_SQSIZE, &tempword)) { /* Get the message type which is total_len + PSEUDO header + msgtype + message body */ @@ -1039,8 +1034,7 @@ static void ft1000_proc_drvmsg(struct net_device *dev) info->ConTm = 0; } } - } - else { + } else { pr_debug("Media is down\n"); if (info->mediastate == 1) { info->mediastate = 0; -- cgit v0.10.2 From 41f53d5739bd4d9b41688bd5532be4c489bd485e Mon Sep 17 00:00:00 2001 From: Brian Vandre Date: Wed, 3 Dec 2014 22:06:55 -0600 Subject: staging: lustre: fld: fixed symbol was not declared Fixes the sparse warning: "warning: symbol 'fld_type_proc_dir' was not declared. Should it be static?" Also removes initialization to NULL. Signed-off-by: Brian Vandre Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index 0d361ff..7801db0 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -269,7 +269,7 @@ int fld_client_del_target(struct lu_client_fld *fld, __u64 idx) } EXPORT_SYMBOL(fld_client_del_target); -struct proc_dir_entry *fld_type_proc_dir = NULL; +static struct proc_dir_entry *fld_type_proc_dir; #if defined (CONFIG_PROC_FS) static int fld_client_proc_init(struct lu_client_fld *fld) -- cgit v0.10.2 From e84962e3afc1665756bd4854c63da662696fb687 Mon Sep 17 00:00:00 2001 From: Tristan Lelong Date: Fri, 5 Dec 2014 22:43:20 -0800 Subject: staging: lustre: fix sparse warning on LPROC_SEQ_FOPS macros This patch fix a sparse warning in lustre sources warning: incorrect type in argument 1 (different address spaces) expected void [noderef] *to got char * This is done by adding the missing __user attribute on userland pointers inside the LPROC_SEQ_FOPS like macros: - LPROC_SEQ_FOPS - LPROC_SEQ_FOPS_RW_TYPE - LPROC_SEQ_FOPS_WR_ONLY - LDLM_POOL_PROC_WRITER The patch also updates all the functions that are used by this macro: - lprocfs_wr_* - *_seq_write as well as some helpers used by the previously modified functions (otherwise fixing the sparse warning add some new ones): - lprocfs_write_frac_helper - lprocfs_write_helper - lprocfs_write_u64_helper The patch also fixes one __user pointer direct dereference by strncmp in function fld_proc_hash_seq_write. Signed-off-by: Tristan Lelong Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/fld/lproc_fld.c b/drivers/staging/lustre/lustre/fld/lproc_fld.c index 95e7de1..74b4db9 100644 --- a/drivers/staging/lustre/lustre/fld/lproc_fld.c +++ b/drivers/staging/lustre/lustre/fld/lproc_fld.c @@ -87,13 +87,25 @@ fld_proc_hash_seq_show(struct seq_file *m, void *unused) } static ssize_t -fld_proc_hash_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +fld_proc_hash_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct lu_client_fld *fld; struct lu_fld_hash *hash = NULL; + char *name; int i; + if (count > 80) + return -ENAMETOOLONG; + + name = kmalloc(count, GFP_KERNEL); + if (!name) + return -ENOMEM; + + if (copy_from_user(name, buffer, count) != 0) + return -EFAULT; + fld = ((struct seq_file *)file->private_data)->private; LASSERT(fld != NULL); @@ -101,7 +113,7 @@ fld_proc_hash_seq_write(struct file *file, const char *buffer, if (count != strlen(fld_hash[i].fh_name)) continue; - if (!strncmp(fld_hash[i].fh_name, buffer, count)) { + if (!strncmp(fld_hash[i].fh_name, name, count)) { hash = &fld_hash[i]; break; } @@ -116,6 +128,7 @@ fld_proc_hash_seq_write(struct file *file, const char *buffer, fld->lcf_name, hash->fh_name); } + kfree(name); return count; } diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index cfe503b..8a25cf6 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -627,16 +627,16 @@ struct adaptive_timeout; extern int lprocfs_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at); extern int lprocfs_rd_timeouts(struct seq_file *m, void *data); -extern int lprocfs_wr_timeouts(struct file *file, const char *buffer, +extern int lprocfs_wr_timeouts(struct file *file, const char __user *buffer, unsigned long count, void *data); -extern int lprocfs_wr_evict_client(struct file *file, const char *buffer, +extern int lprocfs_wr_evict_client(struct file *file, const char __user *buffer, size_t count, loff_t *off); -extern int lprocfs_wr_ping(struct file *file, const char *buffer, +extern int lprocfs_wr_ping(struct file *file, const char __user *buffer, size_t count, loff_t *off); -extern int lprocfs_wr_import(struct file *file, const char *buffer, +extern int lprocfs_wr_import(struct file *file, const char __user *buffer, size_t count, loff_t *off); extern int lprocfs_rd_pinger_recov(struct seq_file *m, void *n); -extern int lprocfs_wr_pinger_recov(struct file *file, const char *buffer, +extern int lprocfs_wr_pinger_recov(struct file *file, const char __user *buffer, size_t count, loff_t *off); /* Statfs helpers */ @@ -650,8 +650,8 @@ extern int lprocfs_rd_filesfree(struct seq_file *m, void *data); extern int lprocfs_write_helper(const char __user *buffer, unsigned long count, int *val); extern int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult); -extern int lprocfs_write_u64_helper(const char *buffer, unsigned long count, - __u64 *val); +extern int lprocfs_write_u64_helper(const char __user *buffer, + unsigned long count, __u64 *val); extern int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, __u64 *val, int mult); @@ -716,7 +716,8 @@ static struct file_operations name##_fops = { \ return lprocfs_rd_##type(m, m->private); \ } \ static ssize_t name##_##type##_seq_write(struct file *file, \ - const char *buffer, size_t count, loff_t *off) \ + const char __user *buffer, size_t count, \ + loff_t *off) \ { \ struct seq_file *seq = file->private_data; \ return lprocfs_wr_##type(file, buffer, \ @@ -726,7 +727,8 @@ static struct file_operations name##_fops = { \ #define LPROC_SEQ_FOPS_WR_ONLY(name, type) \ static ssize_t name##_##type##_write(struct file *file, \ - const char *buffer, size_t count, loff_t *off) \ + const char __user *buffer, size_t count, \ + loff_t *off) \ { \ return lprocfs_wr_##type(file, buffer, count, off); \ } \ @@ -939,20 +941,24 @@ static inline int lprocfs_at_hist_helper(struct seq_file *m, static inline int lprocfs_rd_timeouts(struct seq_file *m, void *data) { return 0; } static inline int lprocfs_wr_timeouts(struct file *file, - const char *buffer, - unsigned long count, void *data) + const char __user *buffer, + unsigned long count, void *data) { return 0; } -static inline int lprocfs_wr_evict_client(struct file *file, const char *buffer, - size_t count, loff_t *off) +static inline int lprocfs_wr_evict_client(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { return 0; } -static inline int lprocfs_wr_ping(struct file *file, const char *buffer, - size_t count, loff_t *off) +static inline int lprocfs_wr_ping(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { return 0; } -static inline int lprocfs_wr_import(struct file *file, const char *buffer, - size_t count, loff_t *off) +static inline int lprocfs_wr_import(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { return 0; } -static inline int lprocfs_wr_pinger_recov(struct file *file, const char *buffer, - size_t count, loff_t *off) +static inline int lprocfs_wr_pinger_recov(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { return 0; } /* Statfs helpers */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index 6c6c57c..20e64cd 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -249,8 +249,9 @@ typedef enum ldlm_policy_res ldlm_policy_res_t; struct __##var##__dummy_read {; } /* semicolon catcher */ #define LDLM_POOL_PROC_WRITER(var, type) \ - static int lprocfs_wr_##var(struct file *file, const char *buffer, \ - unsigned long count, void *data) \ + static int lprocfs_wr_##var(struct file *file, \ + const char __user *buffer, \ + unsigned long count, void *data) \ { \ struct ldlm_pool *pl = data; \ type tmp; \ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 4c838f6..142b3dd 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -697,8 +697,8 @@ LPROC_SEQ_FOPS_RO(lprocfs_grant_plan); LDLM_POOL_PROC_READER_SEQ_SHOW(recalc_period, int); LDLM_POOL_PROC_WRITER(recalc_period, int); static ssize_t lprocfs_recalc_period_seq_write(struct file *file, - const char *buf, size_t len, - loff_t *off) + const char __user *buf, + size_t len, loff_t *off) { struct seq_file *seq = file->private_data; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 1f150e4..c6f62a9 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -72,7 +72,7 @@ extern unsigned int ldlm_cancel_unused_locks_before_replay; unsigned int ldlm_dump_granted_max = 256; #if defined(CONFIG_PROC_FS) -static ssize_t lprocfs_wr_dump_ns(struct file *file, const char *buffer, +static ssize_t lprocfs_wr_dump_ns(struct file *file, const char __user *buffer, size_t count, loff_t *off) { ldlm_dump_all_namespaces(LDLM_NAMESPACE_SERVER, D_DLMTRACE); @@ -287,8 +287,9 @@ static int lprocfs_elc_seq_show(struct seq_file *m, void *v) return lprocfs_rd_uint(m, &supp); } -static ssize_t lprocfs_elc_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t lprocfs_elc_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct ldlm_namespace *ns = ((struct seq_file *)file->private_data)->private; unsigned int supp = -1; diff --git a/drivers/staging/lustre/lustre/lov/lproc_lov.c b/drivers/staging/lustre/lustre/lov/lproc_lov.c index c993f25..c99f2f4 100644 --- a/drivers/staging/lustre/lustre/lov/lproc_lov.c +++ b/drivers/staging/lustre/lustre/lov/lproc_lov.c @@ -51,8 +51,9 @@ static int lov_stripesize_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%llu\n", desc->ld_default_stripe_size); } -static ssize_t lov_stripesize_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t lov_stripesize_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct lov_desc *desc; @@ -81,8 +82,9 @@ static int lov_stripeoffset_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%llu\n", desc->ld_default_stripe_offset); } -static ssize_t lov_stripeoffset_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t lov_stripeoffset_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct lov_desc *desc; @@ -110,8 +112,9 @@ static int lov_stripetype_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%u\n", desc->ld_pattern); } -static ssize_t lov_stripetype_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t lov_stripetype_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct lov_desc *desc; @@ -140,8 +143,9 @@ static int lov_stripecount_seq_show(struct seq_file *m, void *v) (__s16)(desc->ld_default_stripe_count + 1) - 1); } -static ssize_t lov_stripecount_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t lov_stripecount_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct lov_desc *desc; diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index 16341c8..c420219 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -52,7 +52,7 @@ static int mdc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v) } static ssize_t mdc_max_rpcs_in_flight_seq_write(struct file *file, - const char *buffer, + const char __user *buffer, size_t count, loff_t *off) { @@ -82,8 +82,9 @@ static int mdc_kuc_open(struct inode *inode, struct file *file) } /* temporary for testing */ -static ssize_t mdc_kuc_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t mdc_kuc_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index 66ceab2..b5007b8 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -272,8 +272,9 @@ static int obd_proc_jobid_var_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%s\n", obd_jobid_var); } -static ssize_t obd_proc_jobid_var_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t obd_proc_jobid_var_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { if (!count || count > JOBSTATS_JOBID_VAR_MAX_LEN) return -EINVAL; diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 3b7dfc3..f78a241 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -1849,7 +1849,7 @@ int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult) } EXPORT_SYMBOL(lprocfs_seq_read_frac_helper); -int lprocfs_write_u64_helper(const char *buffer, unsigned long count, +int lprocfs_write_u64_helper(const char __user *buffer, unsigned long count, __u64 *val) { return lprocfs_write_frac_u64_helper(buffer, count, val, 1); diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 9f719bc..8e22e45 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -53,8 +53,9 @@ static int osc_active_seq_show(struct seq_file *m, void *v) return rc; } -static ssize_t osc_active_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_active_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; int val, rc; @@ -88,7 +89,8 @@ static int osc_max_rpcs_in_flight_seq_show(struct seq_file *m, void *v) } static ssize_t osc_max_rpcs_in_flight_seq_write(struct file *file, - const char *buffer, size_t count, loff_t *off) + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &dev->u.cli; @@ -130,8 +132,9 @@ static int osc_max_dirty_mb_seq_show(struct seq_file *m, void *v) return lprocfs_seq_read_frac_helper(m, val, mult); } -static ssize_t osc_max_dirty_mb_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_max_dirty_mb_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &dev->u.cli; @@ -233,8 +236,9 @@ static int osc_cur_grant_bytes_seq_show(struct seq_file *m, void *v) return rc; } -static ssize_t osc_cur_grant_bytes_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_cur_grant_bytes_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &obd->u.cli; @@ -290,7 +294,8 @@ static int osc_grant_shrink_interval_seq_show(struct seq_file *m, void *v) } static ssize_t osc_grant_shrink_interval_seq_write(struct file *file, - const char *buffer, size_t count, loff_t *off) + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; int val, rc; @@ -322,8 +327,9 @@ static int osc_checksum_seq_show(struct seq_file *m, void *v) obd->u.cli.cl_checksum ? 1 : 0); } -static ssize_t osc_checksum_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_checksum_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; int val, rc; @@ -362,7 +368,8 @@ static int osc_checksum_type_seq_show(struct seq_file *m, void *v) return 0; } -static ssize_t osc_checksum_type_seq_write(struct file *file, const char *buffer, +static ssize_t osc_checksum_type_seq_write(struct file *file, + const char __user *buffer, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; @@ -401,8 +408,9 @@ static int osc_resend_count_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%u\n", atomic_read(&obd->u.cli.cl_resends)); } -static ssize_t osc_resend_count_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_resend_count_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; int val, rc; @@ -428,8 +436,9 @@ static int osc_contention_seconds_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%u\n", od->od_contention_time); } -static ssize_t osc_contention_seconds_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_contention_seconds_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; struct osc_device *od = obd2osc_dev(obd); @@ -447,8 +456,9 @@ static int osc_lockless_truncate_seq_show(struct seq_file *m, void *v) return seq_printf(m, "%u\n", od->od_lockless_truncate); } -static ssize_t osc_lockless_truncate_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +static ssize_t osc_lockless_truncate_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; struct osc_device *od = obd2osc_dev(obd); @@ -472,7 +482,8 @@ static int osc_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *v) } static ssize_t osc_obd_max_pages_per_rpc_seq_write(struct file *file, - const char *buffer, size_t count, loff_t *off) + const char __user *buffer, + size_t count, loff_t *off) { struct obd_device *dev = ((struct seq_file *)file->private_data)->private; struct client_obd *cli = &dev->u.cli; @@ -664,8 +675,9 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) } #undef pct -static ssize_t osc_rpc_stats_seq_write(struct file *file, const char *buf, - size_t len, loff_t *off) +static ssize_t osc_rpc_stats_seq_write(struct file *file, + const char __user *buf, + size_t len, loff_t *off) { struct seq_file *seq = file->private_data; struct obd_device *dev = seq->private; @@ -702,8 +714,9 @@ static int osc_stats_seq_show(struct seq_file *seq, void *v) return 0; } -static ssize_t osc_stats_seq_write(struct file *file, const char *buf, - size_t len, loff_t *off) +static ssize_t osc_stats_seq_write(struct file *file, + const char __user *buf, + size_t len, loff_t *off) { struct seq_file *seq = file->private_data; struct obd_device *dev = seq->private; diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index 4011e00..7b22afd 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -284,8 +284,9 @@ ptlrpc_lprocfs_req_history_max_seq_show(struct seq_file *m, void *n) } static ssize_t -ptlrpc_lprocfs_req_history_max_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +ptlrpc_lprocfs_req_history_max_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; int bufpages; @@ -329,8 +330,9 @@ ptlrpc_lprocfs_threads_min_seq_show(struct seq_file *m, void *n) } static ssize_t -ptlrpc_lprocfs_threads_min_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +ptlrpc_lprocfs_threads_min_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; int val; @@ -381,8 +383,9 @@ ptlrpc_lprocfs_threads_max_seq_show(struct seq_file *m, void *n) } static ssize_t -ptlrpc_lprocfs_threads_max_seq_write(struct file *file, const char *buffer, - size_t count, loff_t *off) +ptlrpc_lprocfs_threads_max_seq_write(struct file *file, + const char __user *buffer, + size_t count, loff_t *off) { struct ptlrpc_service *svc = ((struct seq_file *)file->private_data)->private; int val; @@ -1025,7 +1028,7 @@ static int ptlrpc_lprocfs_hp_ratio_seq_show(struct seq_file *m, void *v) } static ssize_t ptlrpc_lprocfs_hp_ratio_seq_write(struct file *file, - const char *buffer, + const char __user *buffer, size_t count, loff_t *off) { @@ -1175,7 +1178,7 @@ EXPORT_SYMBOL(ptlrpc_lprocfs_unregister_obd); #define BUFLEN (UUID_MAX + 5) -int lprocfs_wr_evict_client(struct file *file, const char *buffer, +int lprocfs_wr_evict_client(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; @@ -1223,7 +1226,7 @@ EXPORT_SYMBOL(lprocfs_wr_evict_client); #undef BUFLEN -int lprocfs_wr_ping(struct file *file, const char *buffer, +int lprocfs_wr_ping(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; @@ -1251,7 +1254,7 @@ EXPORT_SYMBOL(lprocfs_wr_ping); * The connection UUID is a node's primary NID. For example, * "echo connection=192.168.0.1@tcp0::instance > .../import". */ -int lprocfs_wr_import(struct file *file, const char *buffer, +int lprocfs_wr_import(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; @@ -1329,7 +1332,7 @@ int lprocfs_rd_pinger_recov(struct seq_file *m, void *n) } EXPORT_SYMBOL(lprocfs_rd_pinger_recov); -int lprocfs_wr_pinger_recov(struct file *file, const char *buffer, +int lprocfs_wr_pinger_recov(struct file *file, const char __user *buffer, size_t count, loff_t *off) { struct obd_device *obd = ((struct seq_file *)file->private_data)->private; -- cgit v0.10.2 From 376048962321f630b523d5f1421f5c9cfa051cd0 Mon Sep 17 00:00:00 2001 From: Tristan Lelong Date: Sat, 6 Dec 2014 16:00:30 -0800 Subject: staging: lustre: replace static value with define This patch replace the value '80' used in several files in the lustre source code with a define LUSTRE_MDT_MAXNAMELEN. This value is used in 4 different structures as the maximum len for a service name. According to the comments, these names follow a convention which make it possible to use the same define for LCS, LSS, LCF, and LSF. Signed-off-by: Tristan Lelong Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/fld/fld_internal.h b/drivers/staging/lustre/lustre/fld/fld_internal.h index 8806b60..6125bbe 100644 --- a/drivers/staging/lustre/lustre/fld/fld_internal.h +++ b/drivers/staging/lustre/lustre/fld/fld_internal.h @@ -111,7 +111,7 @@ struct fld_cache { /** * Cache name used for debug and messages. */ - char fci_name[80]; + char fci_name[LUSTRE_MDT_MAXNAMELEN]; unsigned int fci_no_shrink:1; }; diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 7b7457c..305ecbe 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -105,6 +105,11 @@ * FOO_BULK_PORTAL is for incoming bulk on the FOO */ +/* Lustre service names are following the format + * service name + MDT + seq name + */ +#define LUSTRE_MDT_MAXNAMELEN 80 + #define CONNMGR_REQUEST_PORTAL 1 #define CONNMGR_REPLY_PORTAL 2 //#define OSC_REQUEST_PORTAL 3 diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index 2d6fbb4..0a0929f 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -358,7 +358,7 @@ struct lu_client_seq { * Service uuid, passed from MDT + seq name to form unique seq name to * use it with procfs. */ - char lcs_name[80]; + char lcs_name[LUSTRE_MDT_MAXNAMELEN]; /* * Sequence width, that is how many objects may be allocated in one @@ -408,7 +408,7 @@ struct lu_server_seq { * Service uuid, passed from MDT + seq name to form unique seq name to * use it with procfs. */ - char lss_name[80]; + char lss_name[LUSTRE_MDT_MAXNAMELEN]; /* * Allocation chunks for super and meta sequences. Default values are diff --git a/drivers/staging/lustre/lustre/include/lustre_fld.h b/drivers/staging/lustre/lustre/include/lustre_fld.h index 64c5048..5ee4b1e 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fld.h +++ b/drivers/staging/lustre/lustre/include/lustre_fld.h @@ -93,7 +93,7 @@ struct lu_server_fld { /** * Fld service name in form "fld-srv-lustre-MDTXXX" */ - char lsf_name[80]; + char lsf_name[LUSTRE_MDT_MAXNAMELEN]; }; @@ -124,7 +124,7 @@ struct lu_client_fld { /** * Client fld proc entry name. */ - char lcf_name[80]; + char lcf_name[LUSTRE_MDT_MAXNAMELEN]; int lcf_flags; }; -- cgit v0.10.2 From ff2bf19e8d611caa2033e158f041e2876742570a Mon Sep 17 00:00:00 2001 From: Fred Chou Date: Mon, 8 Dec 2014 17:52:07 +0800 Subject: staging:lustre:lustre:ptlrpc: fix sparse warnings in lproc_ptlrpc.c Fixed the below warning in sparse: drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c:184:6: warning: symbol 'ptlrpc_lprocfs_register' was not declared. Should it be static? Signed-off-by: Fred Chou Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index 7b22afd..90448e9 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -181,9 +181,10 @@ const char *ll_eopcode2str(__u32 opcode) return ll_eopcode_table[opcode].opname; } #if defined (CONFIG_PROC_FS) -void ptlrpc_lprocfs_register(struct proc_dir_entry *root, char *dir, - char *name, struct proc_dir_entry **procroot_ret, - struct lprocfs_stats **stats_ret) +static void ptlrpc_lprocfs_register(struct proc_dir_entry *root, char *dir, + char *name, + struct proc_dir_entry **procroot_ret, + struct lprocfs_stats **stats_ret) { struct proc_dir_entry *svc_procroot; struct lprocfs_stats *svc_stats; -- cgit v0.10.2 From 4d4e1eef9a513437dad15d8d116a3f669e0d578d Mon Sep 17 00:00:00 2001 From: Dean Ancajas Date: Mon, 8 Dec 2014 11:36:33 -0700 Subject: Staging: lustre: obd: Fix a coding style issue Fixed a brace coding style issue for functions. Signed-off-by: Dean Michael Ancajas Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index ce96bd2..c40bb6c 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -662,7 +662,8 @@ static int cl_env_store_init(void) { return cl_env_hash != NULL ? 0 :-ENOMEM; } -static void cl_env_store_fini(void) { +static void cl_env_store_fini(void) +{ cfs_hash_putref(cl_env_hash); } -- cgit v0.10.2 From f351bad2b4b4bb74810ad4f127f6602e2d2ae403 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 2 Dec 2014 17:15:37 +0000 Subject: lustre: don't use iovec instead of kvec Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index 7e89b3b..99fb52a 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -752,9 +752,9 @@ int lnet_fail_nid(lnet_nid_t nid, unsigned int threshold); void lnet_counters_get(lnet_counters_t *counters); void lnet_counters_reset(void); -unsigned int lnet_iov_nob(unsigned int niov, struct iovec *iov); -int lnet_extract_iov(int dst_niov, struct iovec *dst, - int src_niov, struct iovec *src, +unsigned int lnet_iov_nob(unsigned int niov, struct kvec *iov); +int lnet_extract_iov(int dst_niov, struct kvec *dst, + int src_niov, struct kvec *src, unsigned int offset, unsigned int len); unsigned int lnet_kiov_nob(unsigned int niov, lnet_kiov_t *iov); @@ -762,17 +762,17 @@ int lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, int src_niov, lnet_kiov_t *src, unsigned int offset, unsigned int len); -void lnet_copy_iov2iov(unsigned int ndiov, struct iovec *diov, +void lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, - unsigned int nsiov, struct iovec *siov, + unsigned int nsiov, struct kvec *siov, unsigned int soffset, unsigned int nob); -void lnet_copy_kiov2iov(unsigned int niov, struct iovec *iov, +void lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, unsigned int nkiov, lnet_kiov_t *kiov, unsigned int kiovoffset, unsigned int nob); void lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, unsigned int kiovoffset, - unsigned int niov, struct iovec *iov, + unsigned int niov, struct kvec *iov, unsigned int iovoffset, unsigned int nob); void lnet_copy_kiov2kiov(unsigned int ndkiov, lnet_kiov_t *dkiov, unsigned int doffset, @@ -781,10 +781,10 @@ void lnet_copy_kiov2kiov(unsigned int ndkiov, lnet_kiov_t *dkiov, static inline void lnet_copy_iov2flat(int dlen, void *dest, unsigned int doffset, - unsigned int nsiov, struct iovec *siov, unsigned int soffset, + unsigned int nsiov, struct kvec *siov, unsigned int soffset, unsigned int nob) { - struct iovec diov = {/*.iov_base = */ dest, /*.iov_len = */ dlen}; + struct kvec diov = {/*.iov_base = */ dest, /*.iov_len = */ dlen}; lnet_copy_iov2iov(1, &diov, doffset, nsiov, siov, soffset, nob); @@ -795,17 +795,17 @@ lnet_copy_kiov2flat(int dlen, void *dest, unsigned int doffset, unsigned int nsiov, lnet_kiov_t *skiov, unsigned int soffset, unsigned int nob) { - struct iovec diov = {/* .iov_base = */ dest, /* .iov_len = */ dlen}; + struct kvec diov = {/* .iov_base = */ dest, /* .iov_len = */ dlen}; lnet_copy_kiov2iov(1, &diov, doffset, nsiov, skiov, soffset, nob); } static inline void -lnet_copy_flat2iov(unsigned int ndiov, struct iovec *diov, unsigned int doffset, +lnet_copy_flat2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, int slen, void *src, unsigned int soffset, unsigned int nob) { - struct iovec siov = {/*.iov_base = */ src, /*.iov_len = */slen}; + struct kvec siov = {/*.iov_base = */ src, /*.iov_len = */slen}; lnet_copy_iov2iov(ndiov, diov, doffset, 1, &siov, soffset, nob); @@ -816,7 +816,7 @@ lnet_copy_flat2kiov(unsigned int ndiov, lnet_kiov_t *dkiov, unsigned int doffset, int slen, void *src, unsigned int soffset, unsigned int nob) { - struct iovec siov = {/* .iov_base = */ src, /* .iov_len = */ slen}; + struct kvec siov = {/* .iov_base = */ src, /* .iov_len = */ slen}; lnet_copy_iov2kiov(ndiov, dkiov, doffset, 1, &siov, soffset, nob); diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index f16213f..ba1876f 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -217,7 +217,7 @@ typedef struct lnet_msg { unsigned int msg_wanted; unsigned int msg_offset; unsigned int msg_niov; - struct iovec *msg_iov; + struct kvec *msg_iov; lnet_kiov_t *msg_kiov; lnet_event_t msg_ev; @@ -271,7 +271,7 @@ typedef struct lnet_libmd { lnet_eq_t *md_eq; unsigned int md_niov; /* # frags */ union { - struct iovec iov[LNET_MAX_IOV]; + struct kvec iov[LNET_MAX_IOV]; lnet_kiov_t kiov[LNET_MAX_IOV]; } md_iov; } lnet_libmd_t; @@ -346,7 +346,7 @@ typedef struct lnet_lnd { * credit if the LND does flow control. */ int (*lnd_recv)(struct lnet_ni *ni, void *private, lnet_msg_t *msg, int delayed, unsigned int niov, - struct iovec *iov, lnet_kiov_t *kiov, + struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen); /* lnet_parse() has had to delay processing of this message diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index b02b4ec..ab128de 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -1026,5 +1026,5 @@ int kiblnd_post_rx (kib_rx_t *rx, int credit); int kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg); int kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, - unsigned int niov, struct iovec *iov, lnet_kiov_t *kiov, + unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen); diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index b48d7ed..77e9f6f 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -697,7 +697,7 @@ kiblnd_map_tx(lnet_ni_t *ni, kib_tx_t *tx, static int kiblnd_setup_rd_iov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, - unsigned int niov, struct iovec *iov, int offset, int nob) + unsigned int niov, struct kvec *iov, int offset, int nob) { kib_net_t *net = ni->ni_data; struct page *page; @@ -1461,7 +1461,7 @@ kiblnd_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) int target_is_router = lntmsg->msg_target_is_router; int routing = lntmsg->msg_routing; unsigned int payload_niov = lntmsg->msg_niov; - struct iovec *payload_iov = lntmsg->msg_iov; + struct kvec *payload_iov = lntmsg->msg_iov; lnet_kiov_t *payload_kiov = lntmsg->msg_kiov; unsigned int payload_offset = lntmsg->msg_offset; unsigned int payload_nob = lntmsg->msg_len; @@ -1628,7 +1628,7 @@ kiblnd_reply (lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg) { lnet_process_id_t target = lntmsg->msg_target; unsigned int niov = lntmsg->msg_niov; - struct iovec *iov = lntmsg->msg_iov; + struct kvec *iov = lntmsg->msg_iov; lnet_kiov_t *kiov = lntmsg->msg_kiov; unsigned int offset = lntmsg->msg_offset; unsigned int nob = lntmsg->msg_len; @@ -1687,7 +1687,7 @@ kiblnd_reply (lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg) int kiblnd_recv (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, - unsigned int niov, struct iovec *iov, lnet_kiov_t *kiov, + unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen) { kib_rx_t *rx = private; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index a29d4da..03488d2 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -69,7 +69,7 @@ typedef struct /* per scheduler state */ int kss_nconns; struct ksock_sched_info *kss_info; /* owner of it */ struct page *kss_rx_scratch_pgs[LNET_MAX_IOV]; - struct iovec kss_scratch_iov[LNET_MAX_IOV]; + struct kvec kss_scratch_iov[LNET_MAX_IOV]; } ksock_sched_t; struct ksock_sched_info { @@ -213,7 +213,7 @@ typedef struct /* transmit packet */ int tx_nob; /* # packet bytes */ int tx_resid; /* residual bytes */ int tx_niov; /* # packet iovec frags */ - struct iovec *tx_iov; /* packet iovec frags */ + struct kvec *tx_iov; /* packet iovec frags */ int tx_nkiov; /* # packet page frags */ unsigned short tx_zc_aborted; /* aborted ZC request */ unsigned short tx_zc_capable:1; /* payload is large enough for ZC */ @@ -227,11 +227,11 @@ typedef struct /* transmit packet */ int tx_desc_size; /* size of this descriptor */ union { struct { - struct iovec iov; /* virt hdr */ + struct kvec iov; /* virt hdr */ lnet_kiov_t kiov[0]; /* paged payload */ } paged; struct { - struct iovec iov[1]; /* virt hdr + payload */ + struct kvec iov[1]; /* virt hdr + payload */ } virt; } tx_frags; } ksock_tx_t; @@ -243,7 +243,7 @@ typedef struct /* transmit packet */ /* space for the rx frag descriptors; we either read a single contiguous * header, or up to LNET_MAX_IOV frags of payload of either type. */ typedef union { - struct iovec iov[LNET_MAX_IOV]; + struct kvec iov[LNET_MAX_IOV]; lnet_kiov_t kiov[LNET_MAX_IOV]; } ksock_rxiovspace_t; @@ -284,7 +284,7 @@ typedef struct ksock_conn { int ksnc_rx_nob_left; /* # bytes to next hdr/body */ int ksnc_rx_nob_wanted; /* bytes actually wanted */ int ksnc_rx_niov; /* # iovec frags */ - struct iovec *ksnc_rx_iov; /* the iovec frags */ + struct kvec *ksnc_rx_iov; /* the iovec frags */ int ksnc_rx_nkiov; /* # page frags */ lnet_kiov_t *ksnc_rx_kiov; /* the page frags */ ksock_rxiovspace_t ksnc_rx_iov_space;/* space for frag descriptors */ @@ -517,7 +517,7 @@ int ksocknal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg); int ksocknal_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg); int ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, unsigned int niov, - struct iovec *iov, lnet_kiov_t *kiov, + struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen); int ksocknal_accept(lnet_ni_t *ni, struct socket *sock); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index e6c1d36..768c671 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -110,7 +110,7 @@ ksocknal_free_tx (ksock_tx_t *tx) static int ksocknal_send_iov (ksock_conn_t *conn, ksock_tx_t *tx) { - struct iovec *iov = tx->tx_iov; + struct kvec *iov = tx->tx_iov; int nob; int rc; @@ -251,7 +251,7 @@ ksocknal_transmit (ksock_conn_t *conn, ksock_tx_t *tx) static int ksocknal_recv_iov (ksock_conn_t *conn) { - struct iovec *iov = conn->ksnc_rx_iov; + struct kvec *iov = conn->ksnc_rx_iov; int nob; int rc; @@ -926,7 +926,7 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) int type = lntmsg->msg_type; lnet_process_id_t target = lntmsg->msg_target; unsigned int payload_niov = lntmsg->msg_niov; - struct iovec *payload_iov = lntmsg->msg_iov; + struct kvec *payload_iov = lntmsg->msg_iov; lnet_kiov_t *payload_kiov = lntmsg->msg_kiov; unsigned int payload_offset = lntmsg->msg_offset; unsigned int payload_nob = lntmsg->msg_len; @@ -1047,8 +1047,8 @@ ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) case KSOCK_PROTO_V2: case KSOCK_PROTO_V3: conn->ksnc_rx_state = SOCKNAL_RX_KSM_HEADER; - conn->ksnc_rx_iov = (struct iovec *)&conn->ksnc_rx_iov_space; - conn->ksnc_rx_iov[0].iov_base = (char *)&conn->ksnc_msg; + conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; + conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg; conn->ksnc_rx_nob_wanted = offsetof(ksock_msg_t, ksm_u); conn->ksnc_rx_nob_left = offsetof(ksock_msg_t, ksm_u); @@ -1061,8 +1061,8 @@ ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) conn->ksnc_rx_nob_wanted = sizeof(lnet_hdr_t); conn->ksnc_rx_nob_left = sizeof(lnet_hdr_t); - conn->ksnc_rx_iov = (struct iovec *)&conn->ksnc_rx_iov_space; - conn->ksnc_rx_iov[0].iov_base = (char *)&conn->ksnc_msg.ksm_u.lnetmsg; + conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; + conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg.ksm_u.lnetmsg; conn->ksnc_rx_iov[0].iov_len = sizeof (lnet_hdr_t); break; @@ -1082,7 +1082,7 @@ ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) conn->ksnc_rx_state = SOCKNAL_RX_SLOP; conn->ksnc_rx_nob_left = nob_to_skip; - conn->ksnc_rx_iov = (struct iovec *)&conn->ksnc_rx_iov_space; + conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; skipped = 0; niov = 0; @@ -1212,8 +1212,8 @@ ksocknal_process_receive (ksock_conn_t *conn) conn->ksnc_rx_nob_wanted = sizeof(ksock_lnet_msg_t); conn->ksnc_rx_nob_left = sizeof(ksock_lnet_msg_t); - conn->ksnc_rx_iov = (struct iovec *)&conn->ksnc_rx_iov_space; - conn->ksnc_rx_iov[0].iov_base = (char *)&conn->ksnc_msg.ksm_u.lnetmsg; + conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; + conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg.ksm_u.lnetmsg; conn->ksnc_rx_iov[0].iov_len = sizeof(ksock_lnet_msg_t); conn->ksnc_rx_niov = 1; @@ -1311,7 +1311,7 @@ ksocknal_process_receive (ksock_conn_t *conn) int ksocknal_recv (lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, - unsigned int niov, struct iovec *iov, lnet_kiov_t *kiov, + unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen) { ksock_conn_t *conn = (ksock_conn_t *)private; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c index 245c9d7..66cc509 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c @@ -92,11 +92,11 @@ ksocknal_lib_send_iov (ksock_conn_t *conn, ksock_tx_t *tx) { #if SOCKNAL_SINGLE_FRAG_TX - struct iovec scratch; - struct iovec *scratchiov = &scratch; + struct kvec scratch; + struct kvec *scratchiov = &scratch; unsigned int niov = 1; #else - struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; + struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; unsigned int niov = tx->tx_niov; #endif struct msghdr msg = {.msg_flags = MSG_DONTWAIT}; @@ -111,7 +111,7 @@ ksocknal_lib_send_iov (ksock_conn_t *conn, ksock_tx_t *tx) nob < tx->tx_resid) msg.msg_flags |= MSG_MORE; - rc = kernel_sendmsg(sock, &msg, (struct kvec *)scratchiov, niov, nob); + rc = kernel_sendmsg(sock, &msg, scratchiov, niov, nob); } return rc; } @@ -153,14 +153,14 @@ ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx) } } else { #if SOCKNAL_SINGLE_FRAG_TX || !SOCKNAL_RISK_KMAP_DEADLOCK - struct iovec scratch; - struct iovec *scratchiov = &scratch; + struct kvec scratch; + struct kvec *scratchiov = &scratch; unsigned int niov = 1; #else #ifdef CONFIG_HIGHMEM #warning "XXX risk of kmap deadlock on multiple frags..." #endif - struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; + struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; unsigned int niov = tx->tx_nkiov; #endif struct msghdr msg = {.msg_flags = MSG_DONTWAIT}; @@ -203,14 +203,14 @@ int ksocknal_lib_recv_iov (ksock_conn_t *conn) { #if SOCKNAL_SINGLE_FRAG_RX - struct iovec scratch; - struct iovec *scratchiov = &scratch; + struct kvec scratch; + struct kvec *scratchiov = &scratch; unsigned int niov = 1; #else - struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; + struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; unsigned int niov = conn->ksnc_rx_niov; #endif - struct iovec *iov = conn->ksnc_rx_iov; + struct kvec *iov = conn->ksnc_rx_iov; struct msghdr msg = { .msg_flags = 0 }; @@ -232,7 +232,7 @@ ksocknal_lib_recv_iov (ksock_conn_t *conn) LASSERT (nob <= conn->ksnc_rx_nob_wanted); rc = kernel_recvmsg(conn->ksnc_sock, &msg, - (struct kvec *)scratchiov, niov, nob, MSG_DONTWAIT); + scratchiov, niov, nob, MSG_DONTWAIT); saved_csum = 0; if (conn->ksnc_proto == &ksocknal_protocol_v2x) { @@ -269,7 +269,7 @@ ksocknal_lib_kiov_vunmap(void *addr) static void * ksocknal_lib_kiov_vmap(lnet_kiov_t *kiov, int niov, - struct iovec *iov, struct page **pages) + struct kvec *iov, struct page **pages) { void *addr; int nob; @@ -307,15 +307,15 @@ int ksocknal_lib_recv_kiov (ksock_conn_t *conn) { #if SOCKNAL_SINGLE_FRAG_RX || !SOCKNAL_RISK_KMAP_DEADLOCK - struct iovec scratch; - struct iovec *scratchiov = &scratch; + struct kvec scratch; + struct kvec *scratchiov = &scratch; struct page **pages = NULL; unsigned int niov = 1; #else #ifdef CONFIG_HIGHMEM #warning "XXX risk of kmap deadlock on multiple frags..." #endif - struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; + struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov; struct page **pages = conn->ksnc_scheduler->kss_rx_scratch_pgs; unsigned int niov = conn->ksnc_rx_nkiov; #endif @@ -390,13 +390,13 @@ ksocknal_lib_csum_tx(ksock_tx_t *tx) __u32 csum; void *base; - LASSERT(tx->tx_iov[0].iov_base == (void *)&tx->tx_msg); + LASSERT(tx->tx_iov[0].iov_base == &tx->tx_msg); LASSERT(tx->tx_conn != NULL); LASSERT(tx->tx_conn->ksnc_proto == &ksocknal_protocol_v2x); tx->tx_msg.ksm_csum = 0; - csum = ksocknal_csum(~0, (void *)tx->tx_iov[0].iov_base, + csum = ksocknal_csum(~0, tx->tx_iov[0].iov_base, tx->tx_iov[0].iov_len); if (tx->tx_kiov != NULL) { diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c index ea9d80f..b2f88eb 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c @@ -717,7 +717,7 @@ ksocknal_pack_msg_v1(ksock_tx_t *tx) LASSERT(tx->tx_msg.ksm_type != KSOCK_MSG_NOOP); LASSERT(tx->tx_lnetmsg != NULL); - tx->tx_iov[0].iov_base = (void *)&tx->tx_lnetmsg->msg_hdr; + tx->tx_iov[0].iov_base = &tx->tx_lnetmsg->msg_hdr; tx->tx_iov[0].iov_len = sizeof(lnet_hdr_t); tx->tx_resid = tx->tx_nob = tx->tx_lnetmsg->msg_len + sizeof(lnet_hdr_t); @@ -726,7 +726,7 @@ ksocknal_pack_msg_v1(ksock_tx_t *tx) static void ksocknal_pack_msg_v2(ksock_tx_t *tx) { - tx->tx_iov[0].iov_base = (void *)&tx->tx_msg; + tx->tx_iov[0].iov_base = &tx->tx_msg; if (tx->tx_lnetmsg != NULL) { LASSERT(tx->tx_msg.ksm_type != KSOCK_MSG_NOOP); diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index c8c1ed8..39a41c7 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -158,7 +158,7 @@ fail_peer(lnet_nid_t nid, int outgoing) } unsigned int -lnet_iov_nob(unsigned int niov, struct iovec *iov) +lnet_iov_nob(unsigned int niov, struct kvec *iov) { unsigned int nob = 0; @@ -170,8 +170,8 @@ lnet_iov_nob(unsigned int niov, struct iovec *iov) EXPORT_SYMBOL(lnet_iov_nob); void -lnet_copy_iov2iov(unsigned int ndiov, struct iovec *diov, unsigned int doffset, - unsigned int nsiov, struct iovec *siov, unsigned int soffset, +lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, + unsigned int nsiov, struct kvec *siov, unsigned int soffset, unsigned int nob) { /* NB diov, siov are READ-ONLY */ @@ -229,8 +229,8 @@ lnet_copy_iov2iov(unsigned int ndiov, struct iovec *diov, unsigned int doffset, EXPORT_SYMBOL(lnet_copy_iov2iov); int -lnet_extract_iov(int dst_niov, struct iovec *dst, - int src_niov, struct iovec *src, +lnet_extract_iov(int dst_niov, struct kvec *dst, + int src_niov, struct kvec *src, unsigned int offset, unsigned int len) { /* Initialise 'dst' to the subset of 'src' starting at 'offset', @@ -371,7 +371,7 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, EXPORT_SYMBOL(lnet_copy_kiov2kiov); void -lnet_copy_kiov2iov(unsigned int niov, struct iovec *iov, unsigned int iovoffset, +lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, unsigned int nkiov, lnet_kiov_t *kiov, unsigned int kiovoffset, unsigned int nob) { @@ -443,7 +443,7 @@ EXPORT_SYMBOL(lnet_copy_kiov2iov); void lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, unsigned int kiovoffset, unsigned int niov, - struct iovec *iov, unsigned int iovoffset, + struct kvec *iov, unsigned int iovoffset, unsigned int nob) { /* NB kiov, iov are READ-ONLY */ @@ -566,7 +566,7 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, unsigned int offset, unsigned int mlen, unsigned int rlen) { unsigned int niov = 0; - struct iovec *iov = NULL; + struct kvec *iov = NULL; lnet_kiov_t *kiov = NULL; int rc; diff --git a/drivers/staging/lustre/lnet/lnet/lo.c b/drivers/staging/lustre/lnet/lnet/lo.c index 17e1643..f708c2e 100644 --- a/drivers/staging/lustre/lnet/lnet/lo.c +++ b/drivers/staging/lustre/lnet/lnet/lo.c @@ -47,7 +47,7 @@ lolnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) static int lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, unsigned int niov, - struct iovec *iov, lnet_kiov_t *kiov, + struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen) { lnet_msg_t *sendmsg = private; -- cgit v0.10.2 From 5156647235d036ec3c827551395aac7a200e5c76 Mon Sep 17 00:00:00 2001 From: Matthew Tyler Date: Mon, 15 Dec 2014 22:37:27 +0800 Subject: staging: lustre: Fix minor style error in libcfs_string.c Signed-off-by: Matthew Tyler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c index fb88733..e67a18d 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c @@ -132,7 +132,7 @@ char *cfs_firststr(char *str, size_t size) ++end; } - *end= '\0'; + *end = '\0'; out: return str; } -- cgit v0.10.2 From 3f9773a54a98d279530c7c5d7734b24edc1f757f Mon Sep 17 00:00:00 2001 From: Matthew Tyler Date: Mon, 15 Dec 2014 22:37:53 +0800 Subject: staging: lustre: Cleanup cfs_str2mask in libcfs_string.c - Replace body-less for-loop with while loop - Use '\0' for null character instead of 0 Signed-off-by: Matthew Tyler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c index e67a18d..76d4392 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c @@ -47,7 +47,7 @@ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit), int *oldmask, int minmask, int allmask) { const char *debugstr; - char op = 0; + char op = '\0'; int newmask = minmask, i, len, found = 0; /* must be a list of tokens separated by whitespace @@ -55,10 +55,10 @@ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit), * appears first in , '*oldmask' is used as the starting point * (relative), otherwise minmask is used (absolute). An operator * applies to all following tokens up to the next operator. */ - while (*str != 0) { + while (*str != '\0') { while (isspace(*str)) str++; - if (*str == 0) + if (*str == '\0') break; if (*str == '+' || *str == '-') { op = *str++; @@ -67,13 +67,15 @@ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit), newmask = *oldmask; while (isspace(*str)) str++; - if (*str == 0) /* trailing op */ + if (*str == '\0') /* trailing op */ return -EINVAL; } /* find token length */ - for (len = 0; str[len] != 0 && !isspace(str[len]) && - str[len] != '+' && str[len] != '-'; len++); + len = 0; + while (str[len] != '\0' && !isspace(str[len]) && + str[len] != '+' && str[len] != '-') + len++; /* match token */ found = 0; -- cgit v0.10.2 From 054cd8374facbefeafa335d6c3c663939612a889 Mon Sep 17 00:00:00 2001 From: Jia He Date: Tue, 16 Dec 2014 22:37:36 +0800 Subject: staging: lustre: libcfs: fix sparse warnings about static declaration make sparse happy since these two fuchtion are only used in module.c. tested by successful compilation. Signed-off-by: Jia He Cc: Oleg Drokin Cc: Andreas Dilger Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index 2c4fc74..b9ee37c 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -42,8 +42,7 @@ #include "../../include/linux/lnet/lnet.h" #include "tracefile.h" -void -kportal_memhog_free (struct libcfs_device_userstate *ldu) +static void kportal_memhog_free (struct libcfs_device_userstate *ldu) { struct page **level0p = &ldu->ldu_memhog_root_page; struct page **level1p; @@ -86,8 +85,7 @@ kportal_memhog_free (struct libcfs_device_userstate *ldu) LASSERT (ldu->ldu_memhog_pages == 0); } -int -kportal_memhog_alloc(struct libcfs_device_userstate *ldu, int npages, +static int kportal_memhog_alloc(struct libcfs_device_userstate *ldu, int npages, gfp_t flags) { struct page **level0p; -- cgit v0.10.2 From 965bd8b9f743dfc7fd4175fc5072643d321e55d4 Mon Sep 17 00:00:00 2001 From: Chris Rorvick Date: Tue, 16 Dec 2014 22:24:01 -0600 Subject: drivers: staging: lustre: Use mult if units not specified Units can be passed to lprocfs_write_frac_u64_helper() via a suffix (e.g., "...K", "...M", etc.) tacked onto the value. A comment states that "specified units override the multiplier," though the multiplier is overridden regardless. Update the conditional logic so that it only applies when units are specified. Signed-off-by: Chris Rorvick Reviewed-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index f78a241..5aada17 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -1908,7 +1908,7 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, units <<= 10; } /* Specified units override the multiplier */ - if (units) + if (units > 1) mult = mult < 0 ? -units : units; frac *= mult; -- cgit v0.10.2 From f56cb9da50ea8c38d397534cd45aff53d7f693dc Mon Sep 17 00:00:00 2001 From: Chris Rorvick Date: Tue, 16 Dec 2014 22:24:02 -0600 Subject: drivers: staging: lustre: Track sign separately The `mult' parameter is negated if the user data begins with a '-' so that the final value has the appropriate sign. But `mult' is only used if the user data does not include a "units" suffix. In this case, `mult' is overridden with the numeric scale conveyed by the units suffix, but retains the sign of the original value. Having `mult' serving double-duty works but is confusing. Use a new local variable to store the sign of the user data instead. This also fixes a pitfall of passing 0 to `mult', expecting it to be ignored when a units suffix is specified, but having the effect of taking the absolute value of the user-provided data. Signed-off-by: Chris Rorvick Reviewed-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 5aada17..9043f72 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -1862,6 +1862,7 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, char kernbuf[22], *end, *pbuf; __u64 whole, frac = 0, units; unsigned frac_d = 1; + int sign = 1; if (count > (sizeof(kernbuf) - 1)) return -EINVAL; @@ -1872,7 +1873,7 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, kernbuf[count] = '\0'; pbuf = kernbuf; if (*pbuf == '-') { - mult = -mult; + sign = -1; pbuf++; } @@ -1909,11 +1910,11 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, } /* Specified units override the multiplier */ if (units > 1) - mult = mult < 0 ? -units : units; + mult = units; frac *= mult; do_div(frac, frac_d); - *val = whole * mult + frac; + *val = sign * (whole * mult + frac); return 0; } EXPORT_SYMBOL(lprocfs_write_frac_u64_helper); -- cgit v0.10.2 From cc1cf0e0e6566afcf9fd5346c0fe3c3fd6b9b2ac Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Wed, 17 Dec 2014 23:42:53 +0100 Subject: staging: lustre: lustre: mdc: mdc_lib.c: Removed an unnecessary NULL check Removed an unnecessary NULL check. I have checked the only place this function is called from. Signed-off-by: Rickard Strandqvist Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 4e59995..d3234cb 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -222,10 +222,9 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, rec->cr_fsuid = from_kuid(&init_user_ns, current_fsuid()); rec->cr_fsgid = from_kgid(&init_user_ns, current_fsgid()); rec->cr_cap = cfs_curproc_cap_pack(); - if (op_data != NULL) { - rec->cr_fid1 = op_data->op_fid1; - rec->cr_fid2 = op_data->op_fid2; - } + rec->cr_fid1 = op_data->op_fid1; + rec->cr_fid2 = op_data->op_fid2; + rec->cr_mode = mode; cr_flags = mds_pack_open_flags(flags, mode); rec->cr_rdev = rdev; -- cgit v0.10.2 From 439d9eadf648a9d62ab74c64b0e7432b3a15ec3b Mon Sep 17 00:00:00 2001 From: Spencer Baugh Date: Sat, 20 Dec 2014 15:48:13 -0500 Subject: lustre: ptlrpc: add "ptlrpc_internal.h" to sec_gc.c ptlrpc_internal.h contains the prototypes for sptlrpc_gc_init() and sptlrpc_gc_fini(), which are defined in sec_gc.c. This removes the following sparse warnings: drivers/staging/lustre/lustre/ptlrpc/sec_gc.c:217:5: warning: symbol 'sptlrpc_gc_init' was not declared. Should it be static? drivers/staging/lustre/lustre/ptlrpc/sec_gc.c:241:6: warning: symbol 'sptlrpc_gc_fini' was not declared. Should it be static? Signed-off-by: Spencer Baugh Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c index c500aff..81de68e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c @@ -47,6 +47,8 @@ #include "../include/lustre_net.h" #include "../include/lustre_sec.h" +#include "ptlrpc_internal.h" + #define SEC_GC_INTERVAL (30 * 60) -- cgit v0.10.2 From e9a8606905c01b8a8b681b68c995090ff839505a Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 21 Dec 2014 19:30:50 +0100 Subject: staging: lustre: lustre: obdclass: lprocfs_status.c: Removed an unnecessary NULL check Removed an unnecessary NULL check. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 9043f72..572ecad 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -1881,7 +1881,7 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, if (pbuf == end) return -EINVAL; - if (end != NULL && *end == '.') { + if (*end == '.') { int i; pbuf = end + 1; -- cgit v0.10.2 From 466fc15cb03dfbf77f871dacc3d0255ceeee8962 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 21 Dec 2014 19:42:43 +0100 Subject: staging: lustre: lustre: obdclass: lprocfs_status.c: Tidied up some code in a case statement Tidied up some code in a case statement after a discussion. This was partly found using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 572ecad..ddab94d 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -45,6 +45,7 @@ #include "../include/lprocfs_status.h" #include "../include/lustre/lustre_idl.h" #include +#include static const char * const obd_connect_names[] = { "read_only", @@ -1896,16 +1897,16 @@ int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, } units = 1; - switch (*end) { - case 'p': case 'P': + switch (tolower(*end)) { + case 'p': units <<= 10; - case 't': case 'T': + case 't': units <<= 10; - case 'g': case 'G': + case 'g': units <<= 10; - case 'm': case 'M': + case 'm': units <<= 10; - case 'k': case 'K': + case 'k': units <<= 10; } /* Specified units override the multiplier */ -- cgit v0.10.2 From 3b66ea435234aab8fd8f389e929baedb556726c4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 22 Dec 2014 10:52:39 +0300 Subject: Staging: lustre: error handling tweaks in obd_ioctl_getdata() 1) The places which called copy_from_user() were returning the number of bytes not copied instead of -EFAULT. 2) The user could trigger a memory leak if the condition "(hdr.ioc_len != data->ioc_len)" was true. Instead of adding a new call to OBD_FREE_LARGE(), I created a free_buf label and changed everything to use that label. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index b5007b8..b94aeac 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -83,9 +83,8 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) int err; int offset = 0; - err = copy_from_user(&hdr, (void *)arg, sizeof(hdr)); - if (err) - return err; + if (copy_from_user(&hdr, (void *)arg, sizeof(hdr))) + return -EFAULT; if (hdr.ioc_version != OBD_IOCTL_VERSION) { CERROR("Version mismatch kernel (%x) vs application (%x)\n", @@ -117,18 +116,19 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) *len = hdr.ioc_len; data = (struct obd_ioctl_data *)*buf; - err = copy_from_user(*buf, (void *)arg, hdr.ioc_len); - if (err) { - OBD_FREE_LARGE(*buf, hdr.ioc_len); - return err; + if (copy_from_user(*buf, (void *)arg, hdr.ioc_len)) { + err = -EFAULT; + goto free_buf; + } + if (hdr.ioc_len != data->ioc_len) { + err = -EINVAL; + goto free_buf; } - if (hdr.ioc_len != data->ioc_len) - return -EINVAL; if (obd_ioctl_is_invalid(data)) { CERROR("ioctl not correctly formatted\n"); - OBD_FREE_LARGE(*buf, hdr.ioc_len); - return -EINVAL; + err = -EINVAL; + goto free_buf; } if (data->ioc_inllen1) { @@ -151,6 +151,10 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) } return 0; + +free_buf: + OBD_FREE_LARGE(*buf, hdr.ioc_len); + return err; } EXPORT_SYMBOL(obd_ioctl_getdata); -- cgit v0.10.2 From 3f3af378f5d7e9085496a064ef2b0c3b35a8a62c Mon Sep 17 00:00:00 2001 From: samuel kihahu Date: Tue, 23 Dec 2014 15:04:14 +0300 Subject: staging: lustre: cleanup align switch and case Align switch and case to be at the same indent. Signed-off-by: Samuel Kihahu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/selftest/module.c b/drivers/staging/lustre/lnet/selftest/module.c index c6ef5b0..faf4098 100644 --- a/drivers/staging/lustre/lnet/selftest/module.c +++ b/drivers/staging/lustre/lnet/selftest/module.c @@ -61,31 +61,31 @@ lnet_selftest_fini(void) int i; switch (lst_init_step) { - case LST_INIT_CONSOLE: - lstcon_console_fini(); - case LST_INIT_FW: - sfw_shutdown(); - case LST_INIT_RPC: - srpc_shutdown(); - case LST_INIT_WI_TEST: - for (i = 0; - i < cfs_cpt_number(lnet_cpt_table()); i++) { - if (lst_sched_test[i] == NULL) - continue; - cfs_wi_sched_destroy(lst_sched_test[i]); - } - LIBCFS_FREE(lst_sched_test, - sizeof(lst_sched_test[0]) * - cfs_cpt_number(lnet_cpt_table())); - lst_sched_test = NULL; - - case LST_INIT_WI_SERIAL: - cfs_wi_sched_destroy(lst_sched_serial); - lst_sched_serial = NULL; - case LST_INIT_NONE: - break; - default: - LBUG(); + case LST_INIT_CONSOLE: + lstcon_console_fini(); + case LST_INIT_FW: + sfw_shutdown(); + case LST_INIT_RPC: + srpc_shutdown(); + case LST_INIT_WI_TEST: + for (i = 0; + i < cfs_cpt_number(lnet_cpt_table()); i++) { + if (lst_sched_test[i] == NULL) + continue; + cfs_wi_sched_destroy(lst_sched_test[i]); + } + LIBCFS_FREE(lst_sched_test, + sizeof(lst_sched_test[0]) * + cfs_cpt_number(lnet_cpt_table())); + lst_sched_test = NULL; + + case LST_INIT_WI_SERIAL: + cfs_wi_sched_destroy(lst_sched_serial); + lst_sched_serial = NULL; + case LST_INIT_NONE: + break; + default: + LBUG(); } return; } -- cgit v0.10.2 From 0c5754178d8b39e5709da82873f0a6d975ea92f5 Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Thu, 25 Dec 2014 16:04:41 -0800 Subject: staging: lustre: use min/max instead of MIN/MAX, simple cases Custom MIN/MAX operations are being used which are not as robust as the built in min/max operations which will warn about potentially problematic type comparisons. For the simple cases, where no type warning is produced, simply replace MIN/MAX with min/max. Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 77e9f6f..4fd5d94 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -1125,7 +1125,7 @@ kiblnd_init_rdma (kib_conn_t *conn, kib_tx_t *tx, int type, break; } - wrknob = MIN(MIN(kiblnd_rd_frag_size(srcrd, srcidx), + wrknob = min(min(kiblnd_rd_frag_size(srcrd, srcidx), kiblnd_rd_frag_size(dstrd, dstidx)), resid); sge = &tx->tx_sge[tx->tx_nwrq]; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index 9188b34..5956dba 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -773,7 +773,7 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips) /* Only match interfaces for additional connections * if I have > 1 interface */ n_ips = (net->ksnn_ninterfaces < 2) ? 0 : - MIN(n_peerips, net->ksnn_ninterfaces); + min(n_peerips, net->ksnn_ninterfaces); for (i = 0; peer->ksnp_n_passive_ips < n_ips; i++) { /* ^ yes really... */ diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 768c671..0910a18 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -1950,10 +1950,10 @@ ksocknal_connect (ksock_route_t *route) /* This is a retry rather than a new connection */ route->ksnr_retry_interval *= 2; route->ksnr_retry_interval = - MAX(route->ksnr_retry_interval, + max(route->ksnr_retry_interval, cfs_time_seconds(*ksocknal_tunables.ksnd_min_reconnectms)/1000); route->ksnr_retry_interval = - MIN(route->ksnr_retry_interval, + min(route->ksnr_retry_interval, cfs_time_seconds(*ksocknal_tunables.ksnd_max_reconnectms)/1000); LASSERT (route->ksnr_retry_interval != 0); diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 39a41c7..4182bda 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -201,9 +201,9 @@ lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, do { LASSERT(ndiov > 0); LASSERT(nsiov > 0); - this_nob = MIN(diov->iov_len - doffset, + this_nob = min(diov->iov_len - doffset, siov->iov_len - soffset); - this_nob = MIN(this_nob, nob); + this_nob = min(this_nob, nob); memcpy((char *)diov->iov_base + doffset, (char *)siov->iov_base + soffset, this_nob); @@ -322,9 +322,9 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, do { LASSERT(ndiov > 0); LASSERT(nsiov > 0); - this_nob = MIN(diov->kiov_len - doffset, + this_nob = min(diov->kiov_len - doffset, siov->kiov_len - soffset); - this_nob = MIN(this_nob, nob); + this_nob = min(this_nob, nob); if (daddr == NULL) daddr = ((char *)kmap(diov->kiov_page)) + @@ -405,7 +405,7 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, LASSERT(nkiov > 0); this_nob = MIN(iov->iov_len - iovoffset, kiov->kiov_len - kiovoffset); - this_nob = MIN(this_nob, nob); + this_nob = min(this_nob, nob); if (addr == NULL) addr = ((char *)kmap(kiov->kiov_page)) + @@ -476,7 +476,7 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, LASSERT(niov > 0); this_nob = MIN(kiov->kiov_len - kiovoffset, iov->iov_len - iovoffset); - this_nob = MIN(this_nob, nob); + this_nob = min(this_nob, nob); if (addr == NULL) addr = ((char *)kmap(kiov->kiov_page)) + diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index c667b5b..b43e110 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -793,7 +793,7 @@ lnet_update_ni_status_locked(void) LASSERT(the_lnet.ln_routing); timeout = router_ping_timeout + - MAX(live_router_check_interval, dead_router_check_interval); + max(live_router_check_interval, dead_router_check_interval); now = get_seconds(); list_for_each_entry(ni, &the_lnet.ln_nis, ni_list) { @@ -1593,7 +1593,7 @@ lnet_router_checker (void) return; if (last != 0 && - interval > MAX(live_router_check_interval, + interval > max(live_router_check_interval, dead_router_check_interval)) CNETERR("Checker(%d/%d) not called for %d seconds\n", live_router_check_interval, dead_router_check_interval, diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.h b/drivers/staging/lustre/lnet/selftest/conrpc.h index fc1cb56..2353889 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.h +++ b/drivers/staging/lustre/lnet/selftest/conrpc.h @@ -54,7 +54,7 @@ #define LST_TRANS_TIMEOUT 30 #define LST_TRANS_MIN_TIMEOUT 3 -#define LST_VALIDATE_TIMEOUT(t) MIN(MAX(t, LST_TRANS_MIN_TIMEOUT), LST_TRANS_TIMEOUT) +#define LST_VALIDATE_TIMEOUT(t) min(max(t, LST_TRANS_MIN_TIMEOUT), LST_TRANS_TIMEOUT) #define LST_PING_INTERVAL 8 diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index f753add..b602077 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -559,7 +559,7 @@ srpc_add_buffer(struct swi_workitem *wi) LASSERT(scd->scd_buf_posting > 0); scd->scd_buf_posting--; scd->scd_buf_total++; - scd->scd_buf_low = MAX(2, scd->scd_buf_total / 4); + scd->scd_buf_low = max(2, scd->scd_buf_total / 4); } if (rc != 0) { @@ -1486,7 +1486,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) if (scd->scd_buf_err == 0 && /* adding buffer is enabled */ scd->scd_buf_adjust == 0 && scd->scd_buf_nposted < scd->scd_buf_low) { - scd->scd_buf_adjust = MAX(scd->scd_buf_total / 2, + scd->scd_buf_adjust = max(scd->scd_buf_total / 2, SFW_TEST_WI_MIN); swi_schedule_workitem(&scd->scd_buf_wi); } diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c index 976c61e..fdc7189 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c @@ -269,5 +269,5 @@ int cfs_trace_max_debug_mb(void) { int total_mb = (totalram_pages >> (20 - PAGE_SHIFT)); - return MAX(512, (total_mb * 80)/100); + return max(512, (total_mb * 80)/100); } -- cgit v0.10.2 From 462ef1e0e7e2d140ca9b41e7eae48c5f9348c68a Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Thu, 25 Dec 2014 16:04:42 -0800 Subject: staging: lustre: replace MIN with min_t Switch from MIN to the built in min_t with the int type. Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 0910a18..92760fe 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -1087,7 +1087,7 @@ ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) niov = 0; do { - nob = MIN (nob_to_skip, sizeof (ksocknal_slop_buffer)); + nob = min_t(int, nob_to_skip, sizeof(ksocknal_slop_buffer)); conn->ksnc_rx_iov[niov].iov_base = ksocknal_slop_buffer; conn->ksnc_rx_iov[niov].iov_len = nob; -- cgit v0.10.2 From 387915ded529bc47138d1b1401c94569ac4ce71c Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Thu, 25 Dec 2014 16:04:43 -0800 Subject: staging: lustre: replace MIN/MAX with min_t/max_t Switch from MIN/MAX to min_t/max_t with a size_t type. The size_t type was chosen because one operand is a size_t and all the others are immediate integer values. Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c index 46cde70..c055afc 100644 --- a/drivers/staging/lustre/lnet/lnet/router_proc.c +++ b/drivers/staging/lustre/lnet/lnet/router_proc.c @@ -49,7 +49,7 @@ enum { */ #define LNET_PROC_CPT_BITS (LNET_CPT_BITS + 1) /* change version, 16 bits or 8 bits */ -#define LNET_PROC_VER_BITS MAX(((MIN(LNET_LOFFT_BITS, 64)) / 4), 8) +#define LNET_PROC_VER_BITS max_t(size_t, min_t(size_t, LNET_LOFFT_BITS, 64) / 4, 8) #define LNET_PROC_HASH_BITS LNET_PEER_HASH_BITS /* -- cgit v0.10.2 From fce6ad229b5d7a0601f59afa6ce6fdaa09b177f1 Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Thu, 25 Dec 2014 16:04:44 -0800 Subject: staging: lustre: replace MIN with min, cast (__kernel_size_t) Switch from MIN to min and fix the new type warning. The warning is produced because a comparison between iov_len, which is a __kernel_size_t, is made to kiov_len, which is an unsigned int (include/linux/lnet/types.h). Fix the warning by casting kiov_len to __kernel_size_t. Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 4182bda..39e27c1 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -403,8 +403,8 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, do { LASSERT(niov > 0); LASSERT(nkiov > 0); - this_nob = MIN(iov->iov_len - iovoffset, - kiov->kiov_len - kiovoffset); + this_nob = min(iov->iov_len - iovoffset, + (__kernel_size_t) kiov->kiov_len - kiovoffset); this_nob = min(this_nob, nob); if (addr == NULL) @@ -474,7 +474,7 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, do { LASSERT(nkiov > 0); LASSERT(niov > 0); - this_nob = MIN(kiov->kiov_len - kiovoffset, + this_nob = min((__kernel_size_t) kiov->kiov_len - kiovoffset, iov->iov_len - iovoffset); this_nob = min(this_nob, nob); -- cgit v0.10.2 From 28b12e41683e6722a0c4d058fdf69be845e4832b Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Thu, 25 Dec 2014 16:04:45 -0800 Subject: staging: lustre: replace MIN with min_t, remove cast Switch from MIN to min_t and remove the previous cast of the second argument to int. Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 39e27c1..ed6eec9 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -1530,7 +1530,7 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg_t *msg) LASSERT(md->md_offset == 0); rlength = hdr->payload_length; - mlength = MIN(rlength, (int)md->md_length); + mlength = min_t(int, rlength, md->md_length); if (mlength < rlength && (md->md_options & LNET_MD_TRUNCATE) == 0) { -- cgit v0.10.2 From 90d2ced902331613ba1d953d8d8884cae21da296 Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Thu, 25 Dec 2014 16:04:46 -0800 Subject: staging: lustre: remove custom MIN/MAX and min_t operations Remove all custom MIN/MAX and min_t operations since they are no longer needed. Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index 2817112..3d86fb5 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -458,14 +458,6 @@ struct libcfs_device_userstate { struct page *ldu_memhog_root_page; }; -/* what used to be in portals_lib.h */ -#ifndef MIN -# define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef MAX -# define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif - #define MKSTR(ptr) ((ptr)) ? (ptr) : "" static inline int cfs_size_round4(int val) diff --git a/drivers/staging/lustre/lustre/osc/osc_internal.h b/drivers/staging/lustre/lustre/osc/osc_internal.h index d788dac..af96c7b 100644 --- a/drivers/staging/lustre/lustre/osc/osc_internal.h +++ b/drivers/staging/lustre/lustre/osc/osc_internal.h @@ -160,11 +160,6 @@ static inline unsigned long rpcs_in_flight(struct client_obd *cli) return cli->cl_r_in_flight + cli->cl_w_in_flight; } -#ifndef min_t -#define min_t(type, x, y) \ - ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) -#endif - struct osc_device { struct cl_device od_cl; struct obd_export *od_exp; -- cgit v0.10.2 From 2e6e0a4646ea9cea15a35449f98e8baa75db4859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Brinkmann?= Date: Fri, 26 Dec 2014 07:10:50 +0100 Subject: staging: lustre: libcfs/nidstrings: Declare internal symbols static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes sparse warnings: staging/lustre/lustre/libcfs/nidstrings.c:200:11: warning: symbol 'libcfs_nnetstrfns' was not declared. Should it be static? drivers/staging/lustre/lustre/libcfs/nidstrings.c:203:1: warning: symbol 'libcfs_lo_str2addr' was not declared. Should it be static? drivers/staging/lustre/lustre/libcfs/nidstrings.c:210:1: warning: symbol 'libcfs_ip_addr2str' was not declared. Should it be static? drivers/staging/lustre/lustre/libcfs/nidstrings.c:227:1: warning: symbol 'libcfs_ip_str2addr' was not declared. Should it be static? drivers/staging/lustre/lustre/libcfs/nidstrings.c:248:1: warning: symbol 'libcfs_decnum_addr2str' was not declared. Should it be static? drivers/staging/lustre/lustre/libcfs/nidstrings.c:254:1: warning: symbol 'libcfs_hexnum_addr2str' was not declared. Should it be static? drivers/staging/lustre/lustre/libcfs/nidstrings.c:260:1: warning: symbol 'libcfs_num_str2addr' was not declared. Should it be static? staging/lustre/lustre/libcfs/nidstrings.c:279:18: warning: symbol 'libcfs_lnd2netstrfns' was not declared. Should it be static? drivers/staging/lustre/lustre/libcfs/nidstrings.c:292:18: warning: symbol 'libcfs_namenum2netstrfns' was not declared. Should it be static? drivers/staging/lustre/lustre/libcfs/nidstrings.c:307:18: warning: symbol 'libcfs_name2netstrfns' was not declared. Should it be static? Some functions had static forward declarations followed by non-static implementations. Those forward declarations are removed and the implementations are declared static and moved into a location that doesn't require forward declarations. Signed-off-by: Sören Brinkmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/nidstrings.c b/drivers/staging/lustre/lustre/libcfs/nidstrings.c index 47c239f..a73424a 100644 --- a/drivers/staging/lustre/lustre/libcfs/nidstrings.c +++ b/drivers/staging/lustre/lustre/libcfs/nidstrings.c @@ -81,12 +81,68 @@ libcfs_next_nidstring(void) return str; } -static int libcfs_lo_str2addr(const char *str, int nob, __u32 *addr); -static void libcfs_ip_addr2str(__u32 addr, char *str); -static int libcfs_ip_str2addr(const char *str, int nob, __u32 *addr); -static void libcfs_decnum_addr2str(__u32 addr, char *str); -static void libcfs_hexnum_addr2str(__u32 addr, char *str); -static int libcfs_num_str2addr(const char *str, int nob, __u32 *addr); +static int libcfs_lo_str2addr(const char *str, int nob, __u32 *addr) +{ + *addr = 0; + return 1; +} + +static void libcfs_ip_addr2str(__u32 addr, char *str) +{ + snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u", + (addr >> 24) & 0xff, (addr >> 16) & 0xff, + (addr >> 8) & 0xff, addr & 0xff); +} + +static int libcfs_ip_str2addr(const char *str, int nob, __u32 *addr) +{ + unsigned int a; + unsigned int b; + unsigned int c; + unsigned int d; + int n = nob; /* XscanfX */ + + /* numeric IP? */ + if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 && + n == nob && + (a & ~0xff) == 0 && (b & ~0xff) == 0 && + (c & ~0xff) == 0 && (d & ~0xff) == 0) { + *addr = ((a<<24)|(b<<16)|(c<<8)|d); + return 1; + } + + return 0; +} + +static void libcfs_decnum_addr2str(__u32 addr, char *str) +{ + snprintf(str, LNET_NIDSTR_SIZE, "%u", addr); +} + +static void libcfs_hexnum_addr2str(__u32 addr, char *str) +{ + snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr); +} + +static int libcfs_num_str2addr(const char *str, int nob, __u32 *addr) +{ + int n; + + n = nob; + if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob) + return 1; + + n = nob; + if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob) + return 1; + + n = nob; + if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob) + return 1; + + return 0; +} + static int libcfs_num_parse(char *str, int len, struct list_head *list); static int libcfs_num_match(__u32 addr, struct list_head *list); @@ -197,24 +253,7 @@ static struct netstrfns libcfs_netstrfns[] = { {/* .nf_type */ -1}, }; -const int libcfs_nnetstrfns = ARRAY_SIZE(libcfs_netstrfns); - -int -libcfs_lo_str2addr(const char *str, int nob, __u32 *addr) -{ - *addr = 0; - return 1; -} - -void -libcfs_ip_addr2str(__u32 addr, char *str) -{ -#if 0 /* never lookup */ -#endif - snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u", - (addr >> 24) & 0xff, (addr >> 16) & 0xff, - (addr >> 8) & 0xff, addr & 0xff); -} +static const int libcfs_nnetstrfns = ARRAY_SIZE(libcfs_netstrfns); /* CAVEAT EMPTOR XscanfX * I use "%n" at the end of a sscanf format to detect trailing junk. However @@ -223,60 +262,7 @@ libcfs_ip_addr2str(__u32 addr, char *str) * fine, if it doesn't, then the scan ended at the end of the string, which is * fine too :) */ -int -libcfs_ip_str2addr(const char *str, int nob, __u32 *addr) -{ - unsigned int a; - unsigned int b; - unsigned int c; - unsigned int d; - int n = nob; /* XscanfX */ - - /* numeric IP? */ - if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 && - n == nob && - (a & ~0xff) == 0 && (b & ~0xff) == 0 && - (c & ~0xff) == 0 && (d & ~0xff) == 0) { - *addr = ((a<<24)|(b<<16)|(c<<8)|d); - return 1; - } - - return 0; -} - -void -libcfs_decnum_addr2str(__u32 addr, char *str) -{ - snprintf(str, LNET_NIDSTR_SIZE, "%u", addr); -} - -void -libcfs_hexnum_addr2str(__u32 addr, char *str) -{ - snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr); -} - -int -libcfs_num_str2addr(const char *str, int nob, __u32 *addr) -{ - int n; - - n = nob; - if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob) - return 1; - - n = nob; - if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob) - return 1; - - n = nob; - if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob) - return 1; - - return 0; -} - -struct netstrfns * +static struct netstrfns * libcfs_lnd2netstrfns(int lnd) { int i; @@ -289,7 +275,7 @@ libcfs_lnd2netstrfns(int lnd) return NULL; } -struct netstrfns * +static struct netstrfns * libcfs_namenum2netstrfns(const char *name) { struct netstrfns *nf; @@ -304,7 +290,7 @@ libcfs_namenum2netstrfns(const char *name) return NULL; } -struct netstrfns * +static struct netstrfns * libcfs_name2netstrfns(const char *name) { int i; -- cgit v0.10.2 From fd17846d8d6acf991c660ed3498031c6451db61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Brinkmann?= Date: Fri, 26 Dec 2014 07:10:51 +0100 Subject: staging: lustre: libcfs/nidstrings: Avoid forward declarations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid forward declaratoins by moving functions to a location before they are referenced. Signed-off-by: Sören Brinkmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/nidstrings.c b/drivers/staging/lustre/lustre/libcfs/nidstrings.c index a73424a..c70da37 100644 --- a/drivers/staging/lustre/lustre/libcfs/nidstrings.c +++ b/drivers/staging/lustre/lustre/libcfs/nidstrings.c @@ -143,8 +143,43 @@ static int libcfs_num_str2addr(const char *str, int nob, __u32 *addr) return 0; } -static int libcfs_num_parse(char *str, int len, struct list_head *list); -static int libcfs_num_match(__u32 addr, struct list_head *list); +/** + * Nf_parse_addrlist method for networks using numeric addresses. + * + * Examples of such networks are gm and elan. + * + * \retval 0 if \a str parsed to numeric address + * \retval errno otherwise + */ +static int +libcfs_num_parse(char *str, int len, struct list_head *list) +{ + struct cfs_expr_list *el; + int rc; + + rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el); + if (rc == 0) + list_add_tail(&el->el_link, list); + + return rc; +} + +/* + * Nf_match_addr method for networks using numeric addresses + * + * \retval 1 on match + * \retval 0 otherwise + */ +static int +libcfs_num_match(__u32 addr, struct list_head *numaddr) +{ + struct cfs_expr_list *el; + + LASSERT(!list_empty(numaddr)); + el = list_entry(numaddr->next, struct cfs_expr_list, el_link); + + return cfs_expr_list_match(addr, el); +} struct netstrfns { int nf_type; @@ -572,27 +607,6 @@ struct addrrange { }; /** - * Nf_parse_addrlist method for networks using numeric addresses. - * - * Examples of such networks are gm and elan. - * - * \retval 0 if \a str parsed to numeric address - * \retval errno otherwise - */ -static int -libcfs_num_parse(char *str, int len, struct list_head *list) -{ - struct cfs_expr_list *el; - int rc; - - rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el); - if (rc == 0) - list_add_tail(&el->el_link, list); - - return rc; -} - -/** * Parses \ token on the syntax. * * Allocates struct addrrange and links to \a nidrange via @@ -798,23 +812,6 @@ cfs_parse_nidlist(char *str, int len, struct list_head *nidlist) } EXPORT_SYMBOL(cfs_parse_nidlist); -/* - * Nf_match_addr method for networks using numeric addresses - * - * \retval 1 on match - * \retval 0 otherwise - */ -static int -libcfs_num_match(__u32 addr, struct list_head *numaddr) -{ - struct cfs_expr_list *el; - - LASSERT(!list_empty(numaddr)); - el = list_entry(numaddr->next, struct cfs_expr_list, el_link); - - return cfs_expr_list_match(addr, el); -} - /** * Matches a nid (\a nid) against the compiled list of nidranges (\a nidlist). * -- cgit v0.10.2 From 8f67fe2cd1ded2d8e5736f04064eabe51bd69712 Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Sat, 27 Dec 2014 12:46:46 -0800 Subject: staging: lustre: selftest: fix "not declared" by declaring in header Fix several "symbol '...' was not declared" sparse warnings which are caused by global variables by declaring them in the header file. Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 9b5c5df..d487018 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -609,4 +609,16 @@ srpc_wait_service_shutdown(srpc_service_t *sv) } } +extern sfw_test_client_ops_t brw_test_client; +void brw_init_test_client(void); + +extern srpc_service_t brw_test_service; +void brw_init_test_service(void); + +extern sfw_test_client_ops_t ping_test_client; +void ping_init_test_client(void); + +extern srpc_service_t ping_test_service; +void ping_init_test_service(void); + #endif /* __SELFTEST_SELFTEST_H__ */ -- cgit v0.10.2 From 62366bf14c9a198ae4daadffd4d8c4156febfd18 Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Sat, 27 Dec 2014 12:46:47 -0800 Subject: staging: lustre: selftest: fix "not declared" by declaring static Fix several "symbol '...' was not declared" sparse warnings for variables which are only used locally by declaring them static. Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index cc9d182..56b4ef4 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -103,7 +103,7 @@ do { \ #define sfw_test_active(t) (atomic_read(&(t)->tsi_nactive) != 0) #define sfw_batch_active(b) (atomic_read(&(b)->bat_nactive) != 0) -struct smoketest_framework { +static struct smoketest_framework { struct list_head fw_zombie_rpcs; /* RPCs to be recycled */ struct list_head fw_zombie_sessions; /* stopping sessions */ struct list_head fw_tests; /* registered test cases */ diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index b602077..bb6aa2e 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -54,7 +54,7 @@ typedef enum { SRPC_STATE_STOPPING, } srpc_state_t; -struct smoketest_rpc { +static struct smoketest_rpc { spinlock_t rpc_glock; /* global lock */ srpc_service_t *rpc_services[SRPC_SERVICE_MAX_ID + 1]; lnet_handle_eq_t rpc_lnet_eq; /* _the_ LNet event queue */ diff --git a/drivers/staging/lustre/lnet/selftest/timer.c b/drivers/staging/lustre/lnet/selftest/timer.c index f8352c2..441f947 100644 --- a/drivers/staging/lustre/lnet/selftest/timer.c +++ b/drivers/staging/lustre/lnet/selftest/timer.c @@ -57,7 +57,7 @@ #define STTIMER_SLOT(t) (&stt_data.stt_hash[(((t) >> STTIMER_MINPOLL) & \ (STTIMER_NSLOTS - 1))]) -struct st_timer_data { +static struct st_timer_data { spinlock_t stt_lock; /* start time of the slot processed previously */ unsigned long stt_prev_slot; -- cgit v0.10.2 From 8a136d117d4508d3a701e70e608077032dc1b909 Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Sat, 27 Dec 2014 12:46:48 -0800 Subject: staging: lustre: selftest: fix sfw_deactivate_session context imbalance Fix the sparse warning about a context imbalance in the sfw_deactivate_session function by telling sparse that it should expect the lock to be held on entry and held on exit. drivers/staging/lustre/lnet/selftest/framework.c:210:9: warning: context imbalance in 'sfw_deactivate_session' - unexpected unlock Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 56b4ef4..5709148 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -194,9 +194,9 @@ sfw_del_session_timer (void) return EBUSY; /* racing with sfw_session_expired() */ } -/* called with sfw_data.fw_lock held */ static void sfw_deactivate_session (void) + __must_hold(&sfw_data.fw_lock) { sfw_session_t *sn = sfw_data.fw_session; int nactive = 0; -- cgit v0.10.2 From dbfeb73092e849e258fd7f9aa5b00e4ab2ee6fbc Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Sat, 27 Dec 2014 12:46:49 -0800 Subject: staging: lustre: selftest: fix _post_buffer context imbalance Fix the sparse warning about a context imbalance in the srpc_service_post_buffer function by telling sparse that it should expect the lock to be held on entry and held on exit. drivers/staging/lustre/lnet/selftest/rpc.c:508:17: warning: context imbalance in 'srpc_service_post_buffer' - unexpected unlock Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index bb6aa2e..2e9094b 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -468,6 +468,7 @@ srpc_post_passive_rqtbuf(int service, int local, void *buf, int len, static int srpc_service_post_buffer(struct srpc_service_cd *scd, struct srpc_buffer *buf) + __must_hold(&scd->scd_lock) { struct srpc_service *sv = scd->scd_svc; struct srpc_msg *msg = &buf->buf_msg; -- cgit v0.10.2 From 48cbf26505d91385722afc30632952e465d8bb7c Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Sat, 27 Dec 2014 12:46:50 -0800 Subject: staging: lustre: selftest: fix _recycle_buffer context imbalance Fix the sparse warning about a context imbalance in the srpc_service_recycle_buffer function by telling sparse that it should expect the lock to be held on entry and held on exit. drivers/staging/lustre/lnet/selftest/rpc.c:725:20: warning: context imbalance in 'srpc_service_recycle_buffer' - unexpected unlock Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 2e9094b..1f7d9a6 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -698,6 +698,7 @@ srpc_finish_service(struct srpc_service *sv) /* called with sv->sv_lock held */ static void srpc_service_recycle_buffer(struct srpc_service_cd *scd, srpc_buffer_t *buf) + __must_hold(&scd->scd_lock) { if (!scd->scd_svc->sv_shuttingdown && scd->scd_buf_adjust >= 0) { if (srpc_service_post_buffer(scd, buf) != 0) { -- cgit v0.10.2 From f96d1d7ee64c833e6bc11dda2a7d1c8d28394560 Mon Sep 17 00:00:00 2001 From: Balavasu Date: Mon, 29 Dec 2014 20:00:31 +0530 Subject: staging: lustre: lnet: lnet: do not initialise statics to 0 or NULL This patch fixes the checkpatch.pl issue Error: do not initialise statics to 0 or NULL Signed-off-by: Balavasu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index b43e110..0d41ee8 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -46,7 +46,7 @@ MODULE_PARM_DESC(small_router_buffers, "# of small (1 page) messages to buffer i static int large_router_buffers; module_param(large_router_buffers, int, 0444); MODULE_PARM_DESC(large_router_buffers, "# of large messages to buffer in the router"); -static int peer_buffer_credits = 0; +static int peer_buffer_credits; module_param(peer_buffer_credits, int, 0444); MODULE_PARM_DESC(peer_buffer_credits, "# router buffer credits per peer"); @@ -80,7 +80,7 @@ lnet_peer_buffer_credits(lnet_ni_t *ni) #endif -static int check_routers_before_use = 0; +static int check_routers_before_use; module_param(check_routers_before_use, int, 0444); MODULE_PARM_DESC(check_routers_before_use, "Assume routers are down and ping them before use"); @@ -245,7 +245,7 @@ lnet_find_net_locked (__u32 net) static void lnet_shuffle_seed(void) { - static int seeded = 0; + static int seeded; int lnd_type, seed[2]; struct timeval tv; lnet_ni_t *ni; @@ -1578,8 +1578,8 @@ lnet_notify (lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when) void lnet_router_checker (void) { - static time_t last = 0; - static int running = 0; + static time_t last; + static int running; time_t now = get_seconds(); int interval = now - last; -- cgit v0.10.2 From d372a4cdfaa62943286a0da338c2b18c7d55a1b3 Mon Sep 17 00:00:00 2001 From: Serguey Parkhomovsky Date: Wed, 31 Dec 2014 10:59:47 -0800 Subject: staging: lustre: libcfs: fix sparse warnings about static declaration Fixes the following sparse warnings: drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c:198:1: warning: symbol 'libcfs_arch_init' was not declared. Should it be static? drivers/staging/lustre/lustre/libcfs/linux/linux-prim.c:204:1: warning: symbol 'libcfs_arch_cleanup' was not declared. Should it be static? Signed-off-by: Serguey Parkhomovsky Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index a6b2f90..4410d7f 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -85,6 +85,9 @@ static inline int __is_po2(unsigned long long val) #include +int libcfs_arch_init(void); +void libcfs_arch_cleanup(void); + /* libcfs tcpip */ int libcfs_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask); int libcfs_ipif_enumerate(char ***names); diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index b9ee37c..7dc77dd 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -332,8 +332,6 @@ extern struct mutex cfs_trace_thread_mutex; extern struct cfs_wi_sched *cfs_sched_rehash; extern void libcfs_init_nidstrings(void); -extern int libcfs_arch_init(void); -extern void libcfs_arch_cleanup(void); static int init_libcfs_module(void) { -- cgit v0.10.2 From ef4356bf0cf7ed2c9aed45dd64d73538da023718 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 6 Jan 2015 12:57:08 +0300 Subject: staging: lustre: potential underflow in mdc_iocontrol() Smatch complains that "data->ioc_plen2" is a user controlled value and, since we cast to signed int, the limit check can underflow. It's not very serious because probably the copy_to_user() would return -EFAULT on every arch that matters instead of creating an info leak. Also I haven't followed it through to see if the value is really user controlled. But definitely it would be safer to cast to unsigned so let's do that. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 3b0f245..05d05ce 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1908,8 +1908,8 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, /* copy UUID */ if (copy_to_user(data->ioc_pbuf2, obd2cli_tgt(obd), - min((int) data->ioc_plen2, - (int) sizeof(struct obd_uuid)))) { + min_t(size_t, data->ioc_plen2, + sizeof(struct obd_uuid)))) { rc = -EFAULT; goto out; } @@ -1921,8 +1921,8 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, goto out; if (copy_to_user(data->ioc_pbuf1, &stat_buf, - min((int) data->ioc_plen1, - (int) sizeof(stat_buf)))) { + min_t(size_t, data->ioc_plen1, + sizeof(stat_buf)))) { rc = -EFAULT; goto out; } -- cgit v0.10.2 From 1f3fd50391d5644edcb25222b2542a5d165d7464 Mon Sep 17 00:00:00 2001 From: Andreas Ruprecht Date: Sat, 3 Jan 2015 12:29:05 +0100 Subject: staging: lustre: fid: Remove space before braces for defined() check checkpatch complains about three places where a space is prohibited before the braces for an "#if defined()" check. This patch removes the spaces. Signed-off-by: Andreas Ruprecht Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/fid/fid_internal.h b/drivers/staging/lustre/lustre/fid/fid_internal.h index eb607c5..b5e8da8 100644 --- a/drivers/staging/lustre/lustre/fid/fid_internal.h +++ b/drivers/staging/lustre/lustre/fid/fid_internal.h @@ -47,7 +47,7 @@ int seq_client_alloc_super(struct lu_client_seq *seq, const struct lu_env *env); -#if defined (CONFIG_PROC_FS) +#if defined(CONFIG_PROC_FS) extern struct lprocfs_vars seq_client_proc_list[]; #endif diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c index 64b1d80..063441a 100644 --- a/drivers/staging/lustre/lustre/fid/fid_request.c +++ b/drivers/staging/lustre/lustre/fid/fid_request.c @@ -402,7 +402,7 @@ EXPORT_SYMBOL(seq_client_flush); static void seq_client_proc_fini(struct lu_client_seq *seq) { -#if defined (CONFIG_PROC_FS) +#if defined(CONFIG_PROC_FS) if (seq->lcs_proc_dir) { if (!IS_ERR(seq->lcs_proc_dir)) lprocfs_remove(&seq->lcs_proc_dir); @@ -413,7 +413,7 @@ static void seq_client_proc_fini(struct lu_client_seq *seq) static int seq_client_proc_init(struct lu_client_seq *seq) { -#if defined (CONFIG_PROC_FS) +#if defined(CONFIG_PROC_FS) int rc; seq->lcs_proc_dir = lprocfs_register(seq->lcs_name, -- cgit v0.10.2 From 747327975cd0e613f87695283f3865690010dfad Mon Sep 17 00:00:00 2001 From: Igor Ishchenko Date: Mon, 12 Jan 2015 18:16:26 +0200 Subject: staging: lustre: lnet: Removed spaces before increments and decrements Fixed a coding style issue Signed-off-by: Igor Ishchenko Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 62b575d..6510169 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -1538,7 +1538,7 @@ kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, int status) fmr->fmr_pfmr = NULL; spin_lock(&fps->fps_lock); - fpo->fpo_map_count --; /* decref the pool */ + fpo->fpo_map_count--; /* decref the pool */ list_for_each_entry_safe(fpo, tmp, &fps->fps_pool_list, fpo_list) { /* the first pool is persistent */ @@ -1547,7 +1547,7 @@ kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, int status) if (kiblnd_fmr_pool_is_idle(fpo, now)) { list_move(&fpo->fpo_list, &zombies); - fps->fps_version ++; + fps->fps_version++; } } spin_unlock(&fps->fps_lock); @@ -1752,7 +1752,7 @@ kiblnd_pool_free_node(kib_pool_t *pool, struct list_head *node) LASSERT (pool->po_allocated > 0); list_add(node, &pool->po_free_list); - pool->po_allocated --; + pool->po_allocated--; list_for_each_entry_safe(pool, tmp, &ps->ps_pool_list, po_list) { /* the first pool is persistent */ @@ -1781,7 +1781,7 @@ kiblnd_pool_alloc_node(kib_poolset_t *ps) if (list_empty(&pool->po_free_list)) continue; - pool->po_allocated ++; + pool->po_allocated++; pool->po_deadline = cfs_time_shift(IBLND_POOL_DEADLINE); node = pool->po_free_list.next; list_del(node); @@ -1864,7 +1864,7 @@ kiblnd_pmr_pool_map(kib_pmr_poolset_t *pps, kib_hca_dev_t *hdev, return -EAGAIN; } - for (i = 0; i < rd->rd_nfrags; i ++) { + for (i = 0; i < rd->rd_nfrags; i++) { pmr->pmr_ipb[i].addr = rd->rd_frags[i].rf_addr; pmr->pmr_ipb[i].size = rd->rd_frags[i].rf_nob; } @@ -2117,7 +2117,7 @@ kiblnd_tx_init(kib_pool_t *pool, struct list_head *node) tps_poolset); kib_tx_t *tx = list_entry(node, kib_tx_t, tx_list); - tx->tx_cookie = tps->tps_next_tx_cookie ++; + tx->tx_cookie = tps->tps_next_tx_cookie++; } static void @@ -2326,7 +2326,7 @@ kiblnd_hdev_get_attr(kib_hca_dev_t *hdev) } for (hdev->ibh_mr_shift = 0; - hdev->ibh_mr_shift < 64; hdev->ibh_mr_shift ++) { + hdev->ibh_mr_shift < 64; hdev->ibh_mr_shift++) { if (hdev->ibh_mr_size == (1ULL << hdev->ibh_mr_shift) || hdev->ibh_mr_size == (1ULL << hdev->ibh_mr_shift) - 1) return 0; -- cgit v0.10.2 From 88ee4bde2d7224eed10f731917670ccf420e72e7 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 13 Jan 2015 23:33:02 +0100 Subject: staging/lustre: remove unused function Signed-off-by: Luca Ceresoli Cc: Peng Tao Cc: HPDD-discuss@lists.01.org Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c index d71ad5e..9515347 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c @@ -88,11 +88,6 @@ void cfs_kernel_cap_pack(kernel_cap_t kcap, cfs_cap_t *cap) *cap = kcap.cap[0]; } -void cfs_kernel_cap_unpack(kernel_cap_t *kcap, cfs_cap_t cap) -{ - kcap->cap[0] = cap; -} - cfs_cap_t cfs_curproc_cap_pack(void) { cfs_cap_t cap; -- cgit v0.10.2 From 5e0db1a3a8f53634d3b83b1eb8cb1cf9bf167774 Mon Sep 17 00:00:00 2001 From: Balavasu Date: Thu, 15 Jan 2015 11:12:58 +0530 Subject: staging: lustre: lnet: lnet: trailing statements should be on next line This patch fixes the checkpatch.pl issue Error: trailing statements should be on next line Signed-off-by: Balavasu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index 0d41ee8..1bbaa5b 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -1664,13 +1664,16 @@ lnet_get_tunables (void) char *s; s = getenv("LNET_ROUTER_PING_TIMEOUT"); - if (s != NULL) router_ping_timeout = atoi(s); + if (s != NULL) + router_ping_timeout = atoi(s); s = getenv("LNET_LIVE_ROUTER_CHECK_INTERVAL"); - if (s != NULL) live_router_check_interval = atoi(s); + if (s != NULL) + live_router_check_interval = atoi(s); s = getenv("LNET_DEAD_ROUTER_CHECK_INTERVAL"); - if (s != NULL) dead_router_check_interval = atoi(s); + if (s != NULL) + dead_router_check_interval = atoi(s); /* This replaces old lnd_notify mechanism */ check_routers_before_use = 1; -- cgit v0.10.2 From d6b87b0a64879fd548e836bdc901ad20de99cd4b Mon Sep 17 00:00:00 2001 From: Arno Tiemersma Date: Wed, 14 Jan 2015 15:41:33 +0100 Subject: staging: lustre: Add blank lines after declarations Fixes this checkpatch warning: WARNING: Missing a blank line after declarations Signed-off-by: Arno Tiemersma Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h index b3b841f..316500c 100644 --- a/drivers/staging/lustre/lustre/include/lclient.h +++ b/drivers/staging/lustre/lustre/include/lclient.h @@ -135,6 +135,7 @@ static inline struct ccc_thread_info *ccc_env_info(const struct lu_env *env) static inline struct cl_attr *ccc_env_thread_attr(const struct lu_env *env) { struct cl_attr *attr = &ccc_env_info(env)->cti_attr; + memset(attr, 0, sizeof(*attr)); return attr; } @@ -142,6 +143,7 @@ static inline struct cl_attr *ccc_env_thread_attr(const struct lu_env *env) static inline struct cl_io *ccc_env_thread_io(const struct lu_env *env) { struct cl_io *io = &ccc_env_info(env)->cti_io; + memset(io, 0, sizeof(*io)); return io; } -- cgit v0.10.2 From 60c47c62f012b4f551132374e37e4f93a9596107 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Fri, 2 Jan 2015 13:17:06 -0500 Subject: cptm1217: check if interrupts are masked at probe the function cp_tm1217_mask_interrupt can return failure. added the check and the failure path. Cc: Ramesh Agarwal Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/cptm1217/clearpad_tm1217.c b/drivers/staging/cptm1217/clearpad_tm1217.c index 7f265ce..4304604 100644 --- a/drivers/staging/cptm1217/clearpad_tm1217.c +++ b/drivers/staging/cptm1217/clearpad_tm1217.c @@ -446,6 +446,12 @@ static int cp_tm1217_probe(struct i2c_client *client, /* Mask all the interrupts */ retval = cp_tm1217_mask_interrupt(ts); + if (retval) { + dev_err(ts->dev, "failed to mask interrupts, error: %d\n", + retval); + kfree(ts); + return retval; + } /* Read the controller information */ cp_tm1217_init_data(ts); -- cgit v0.10.2 From b6461b53e723ec24d57bdd7c23ee6fee4472bee9 Mon Sep 17 00:00:00 2001 From: Athira Lekshmi Date: Sun, 7 Dec 2014 14:35:00 +0530 Subject: Clocking-wizard: Fixed missing blank line warning Added a new line after declaration to remove the warning 'Missing a blank line after declarations' Signed-off-by: Athira Lekshmi Acked-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c index 471d0877..9a7b369 100644 --- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c +++ b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c @@ -239,6 +239,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) /* register div per output */ for (i = WZRD_NUM_OUTPUTS - 1; i >= 0 ; i--) { const char *clkout_name; + if (of_property_read_string_index(np, "clock-output-names", i, &clkout_name)) { dev_err(&pdev->dev, -- cgit v0.10.2 From 19f15a3000a6ede8c3fcd2735225b894002a7cc1 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 5 Jan 2015 09:21:29 -0800 Subject: staging: clocking-wizard: Handle invalid clk in notifier Even though it should never happen, handle the case that the clock notifier is called with an unexpected clock handle. This avoids the compiler warning: drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c: In function 'clk_wzrd_clk_notifier': >> drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c:99:6: warning: 'max' may be used uninitialized in this function [-Wmaybe-uninitialized] if (ndata->new_rate > max) ^ Reported-by: kbuild test robot Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c index 9a7b369..5455bf3 100644 --- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c +++ b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c @@ -91,8 +91,10 @@ static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event, if (ndata->clk == clk_wzrd->clk_in1) max = clk_wzrd_max_freq[clk_wzrd->speed_grade - 1]; - if (ndata->clk == clk_wzrd->axi_clk) + else if (ndata->clk == clk_wzrd->axi_clk) max = WZRD_ACLK_MAX_FREQ; + else + return NOTIFY_DONE; /* should never happen */ switch (event) { case PRE_RATE_CHANGE: -- cgit v0.10.2 From 7f703fae17d53adadaa9e71af174c51f2655e680 Mon Sep 17 00:00:00 2001 From: Robert Kmiec Date: Sun, 4 Jan 2015 01:32:07 +0100 Subject: staging: rts5208/ms.c: Code style fix (space before comma) This commit fixes the following errors reported by checkpatch.pl -f: ./rts5208/ms.c:1294: ERROR: space prohibited before that ',' (ctx:WxW) ./rts5208/ms.c:1345: ERROR: space prohibited before that ',' (ctx:WxW) ./rts5208/ms.c:1622: ERROR: space prohibited before that ',' (ctx:WxW) ./rts5208/ms.c:1991: ERROR: space prohibited before that ',' (ctx:WxW) This patch also adds missing spaces before and after '+' sign in two places. This file has some other style issues and they will be fixed with latter patches. Signed-off-by: Robert Kmiec Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c index b4612fb..a47a191 100644 --- a/drivers/staging/rts5208/ms.c +++ b/drivers/staging/rts5208/ms.c @@ -781,7 +781,7 @@ static int msxc_change_power(struct rtsx_chip *chip, u8 mode) buf[4] = 0; buf[5] = 0; - retval = ms_write_bytes(chip, PRO_WRITE_REG , 6, NO_WAIT_INT, buf, 6); + retval = ms_write_bytes(chip, PRO_WRITE_REG, 6, NO_WAIT_INT, buf, 6); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); @@ -1291,7 +1291,7 @@ static int ms_write_extra_data(struct rtsx_chip *chip, for (i = 6; i < MS_EXTRA_SIZE + 6; i++) data[i] = buf[i - 6]; - retval = ms_write_bytes(chip, WRITE_REG , (6+MS_EXTRA_SIZE), + retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE), NO_WAIT_INT, data, 16); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); @@ -1342,7 +1342,7 @@ static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num) data[4] = 0x20; data[5] = page_num; - retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, data, 6); + retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); @@ -1619,7 +1619,7 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, data[4] = 0x20; data[5] = i; - retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, + retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); @@ -1695,7 +1695,7 @@ static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk, } retval = ms_set_rw_reg_addr(chip, OverwriteFlag, - MS_EXTRA_SIZE, SystemParm, (6+MS_EXTRA_SIZE)); + MS_EXTRA_SIZE, SystemParm, (6 + MS_EXTRA_SIZE)); ms_set_err_code(chip, MS_NO_ERROR); @@ -1988,7 +1988,7 @@ RE_SEARCH: RTSX_WRITE_REG(chip, PPBUF_BASE2, 0xFF, 0x88); RTSX_WRITE_REG(chip, PPBUF_BASE2 + 1, 0xFF, 0); - retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG , 1, + retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG, 1, NO_WAIT_INT); if (retval != STATUS_SUCCESS) TRACE_RET(chip, STATUS_FAIL); -- cgit v0.10.2 From aa9895da3e2e6aa2674ffa54b3b927503cc47b49 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Fri, 26 Dec 2014 10:34:32 +0900 Subject: staging: dgap: use gotos for handling error in dgap_remap() Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index bdb5317..518ab56 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -1400,27 +1400,27 @@ static int dgap_remap(struct board_t *brd) return -ENOMEM; if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, - "dgap")) { - release_mem_region(brd->membase, 0x200000); - return -ENOMEM; - } + "dgap")) + goto err_req_mem; brd->re_map_membase = ioremap(brd->membase, 0x200000); - if (!brd->re_map_membase) { - release_mem_region(brd->membase, 0x200000); - release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000); - return -ENOMEM; - } + if (!brd->re_map_membase) + goto err_remap_mem; brd->re_map_port = ioremap((brd->membase + PCI_IO_OFFSET), 0x200000); - if (!brd->re_map_port) { - release_mem_region(brd->membase, 0x200000); - release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000); - iounmap(brd->re_map_membase); - return -ENOMEM; - } + if (!brd->re_map_port) + goto err_remap_port; return 0; + +err_remap_port: + iounmap(brd->re_map_membase); +err_remap_mem: + release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000); +err_req_mem: + release_mem_region(brd->membase, 0x200000); + + return -ENOMEM; } static void dgap_unmap(struct board_t *brd) -- cgit v0.10.2 From 81980c16e27cc87c10265e7c62779ccabcaf456b Mon Sep 17 00:00:00 2001 From: Eduardo Barretto Date: Fri, 19 Dec 2014 23:34:33 -0200 Subject: Staging: wlan-ng: hfa384x_usb: fixed an 'else' statement coding style issue Removed useless 'else' statement that followed an 'if' statement that had a return 1 and moved all the content from the 'else' to outside of the switch case, this way if any case is sufficient it returns '1', otherwise it will return 0. Signed-off-by: Eduardo Barretto Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 55d2f56..de33a07 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -4123,12 +4123,11 @@ static int hfa384x_isgood_pdrcode(u16 pdrcode) pr_debug("Encountered unknown PDR#=0x%04x, assuming it's ok.\n", pdrcode); return 1; - } else { - /* bad code */ - pr_debug("Encountered unknown PDR#=0x%04x, (>=0x1000), assuming it's bad.\n", - pdrcode); - return 0; } + break; } - return 0; /* avoid compiler warnings */ + /* bad code */ + pr_debug("Encountered unknown PDR#=0x%04x, (>=0x1000), assuming it's bad.\n", + pdrcode); + return 0; } -- cgit v0.10.2 From 1a6dfce737cc7d8f7a99c79ca7c15c64fb840534 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Mon, 1 Dec 2014 00:29:00 +0900 Subject: staging: wlan-ng: Fix typo in comments and printk This patch fix spelling typo in comments and print. Signed-off-by: Masanari Iida Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 20d146b..5b7b408 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -1268,7 +1268,7 @@ typedef struct hfa384x { hfa384x_downloadbuffer_t bufinfo; u16 dltimeout; - int scanflag; /* to signal scan comlete */ + int scanflag; /* to signal scan complete */ int join_ap; /* are we joined to a specific ap */ int join_retries; /* number of join retries till we fail */ hfa384x_JoinRequest_data_t joinreq; /* join request saved data */ diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index de33a07..2245339 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -382,7 +382,7 @@ done: * * Arguments: * hw device struct -* tx_urb URB of data for tranmission +* tx_urb URB of data for transmission * memflags memory allocation flags * * Returns: @@ -2391,7 +2391,7 @@ int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len) * 0 success * >0 f/w reported error - f/w status code * <0 driver reported error -* -ETIMEDOUT timout waiting for the cmd regs to become +* -ETIMEDOUT timeout waiting for the cmd regs to become * available, or waiting for the control reg * to indicate the Aux port is enabled. * -ENODATA the buffer does NOT contain a valid PDA. diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 7eaaf9a..bd69e8c 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -511,7 +511,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, * protocol. * * Arguments: -* proto protocl number (in host order) to search for. +* proto protocol number (in host order) to search for. * * Returns: * 1 - if the table is empty or a match is found. diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c index 7221379..4b84b56 100644 --- a/drivers/staging/wlan-ng/p80211req.c +++ b/drivers/staging/wlan-ng/p80211req.c @@ -80,7 +80,7 @@ static void p80211req_mibset_mibget(wlandevice_t *wlandev, /*---------------------------------------------------------------- * p80211req_dorequest * -* Handles an MLME reqest/confirm message. +* Handles an MLME request/confirm message. * * Arguments: * wlandev WLAN device struct diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index b62fdcb..16f1239 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -45,7 +45,7 @@ * -------------------------------------------------------------------- * * This file contains the constants and data structures for interaction -* with the hfa384x Wireless LAN (WLAN) Media Access Contoller (MAC). +* with the hfa384x Wireless LAN (WLAN) Media Access Controller (MAC). * The hfa384x is a portion of the Harris PRISM(tm) WLAN chipset. * * [Implementation and usage notes] diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index df577df..182cc7f 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -662,7 +662,7 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) "ident: ap f/w: id=0x%02x %d.%d.%d\n", hw->ident_sta_fw.id, hw->ident_sta_fw.major, hw->ident_sta_fw.minor, hw->ident_sta_fw.variant); - netdev_err(wlandev->netdev, "Unsupported Tertiary AP firmeare loaded!\n"); + netdev_err(wlandev->netdev, "Unsupported Tertiary AP firmware loaded!\n"); goto failed; } -- cgit v0.10.2 From 0175b9bf4b8911de25ff442de51783991b5b3edb Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Mon, 1 Dec 2014 00:29:01 +0900 Subject: staging: wlan-ng: Fix comment in prism2sta.c This patch fix a spelling typo and modify a comment. Signed-off-by: Masanari Iida Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c index 182cc7f..10ad24a 100644 --- a/drivers/staging/wlan-ng/prism2sta.c +++ b/drivers/staging/wlan-ng/prism2sta.c @@ -199,7 +199,7 @@ static int prism2sta_close(wlandevice_t *wlandev) /*---------------------------------------------------------------- * prism2sta_reset * -* Not currently implented. +* Currently not implemented. * * Arguments: * wlandev wlan device structure -- cgit v0.10.2 From 05719ac7d5684cc23967320ae3a4e90e496bd9f6 Mon Sep 17 00:00:00 2001 From: "Panir.Nyan" Date: Wed, 24 Dec 2014 04:07:31 +0000 Subject: staging: speakup: Split the comment to fit the length Split the comment to fit the length. Signed-off-by: Panir Nyan Acked-by: Samuel Thibault Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index f3aa423..01eddab 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c @@ -30,9 +30,9 @@ struct speakup_info_t speakup_info = { * must be taken at each kernel->speakup transition and released at * each corresponding speakup->kernel transition. * - * The progression thread only interferes with the speakup machinery through - * the synth buffer, so only needs to take the lock while tinkering with - * the buffer. + * The progression thread only interferes with the speakup machinery + * through the synth buffer, so only needs to take the lock + * while tinkering with the buffer. * * We use spin_lock/trylock_irqsave and spin_unlock_irqrestore with this * spinlock because speakup needs to disable the keyboard IRQ. -- cgit v0.10.2 From 25c048680b53c689ec918b3adfcfe62e1f03d4f0 Mon Sep 17 00:00:00 2001 From: "Panir.Nyan" Date: Wed, 24 Dec 2014 04:07:32 +0000 Subject: staging: speakup: Combine the consecutive string Combine the consecutive string Signed-off-by: Panir Nyan Acked-by: Samuel Thibault Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c index b12c76d..3708bc1 100644 --- a/drivers/staging/speakup/kobjects.c +++ b/drivers/staging/speakup/kobjects.c @@ -566,7 +566,7 @@ ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr, if (ch >= ' ' && ch < '~') *cp1++ = ch; else - cp1 += sprintf(cp1, "\\""x%02x", ch); + cp1 += sprintf(cp1, "\\x%02x", ch); } *cp1++ = '"'; *cp1++ = '\n'; -- cgit v0.10.2 From 1f5cf8028dc472d5b5374c55b1399a8c294de58d Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Fri, 5 Dec 2014 15:34:27 -0500 Subject: staging: mt29f_spinand: check for the return value of spinand_read_status The spinan_read_status can fail, check for the return value and fail if the spinand_read_status fails. Cc: Kamlakant Patel Signed-off-by: Devendra Naga Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 3628bcb..3b191fc 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -626,7 +626,8 @@ static int spinand_write_page_hwecc(struct mtd_info *mtd, static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { - u8 retval, status; + int retval; + u8 status; uint8_t *p = buf; int eccsize = chip->ecc.size; int eccsteps = chip->ecc.steps; @@ -640,6 +641,13 @@ static int spinand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, while (1) { retval = spinand_read_status(info->spi, &status); + if (retval < 0) { + dev_err(&mtd->dev, + "error %d reading status register\n", + retval); + return retval; + } + if ((status & STATUS_OIP_MASK) == STATUS_READY) { if ((status & STATUS_ECC_MASK) == STATUS_ECC_ERROR) { pr_info("spinand: ECC error\n"); @@ -685,6 +693,13 @@ static int spinand_wait(struct mtd_info *mtd, struct nand_chip *chip) while (time_before(jiffies, timeo)) { retval = spinand_read_status(info->spi, &status); + if (retval < 0) { + dev_err(&mtd->dev, + "error %d reading status register\n", + retval); + return retval; + } + if ((status & STATUS_OIP_MASK) == STATUS_READY) return 0; -- cgit v0.10.2 From e5e76d247f4a40827fef69a72939771943774e87 Mon Sep 17 00:00:00 2001 From: Zeng Tao Date: Tue, 9 Dec 2014 09:19:40 +0800 Subject: staging: ion: ion_cma_heap: remove ion_cma_get_sgtable Remove the temporary code ion_cma_get_sgtable, use dma_common_get_sgtable instead Signed-off-by: Zeng Tao Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index f8cabcb..f4211f1 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -39,24 +39,6 @@ struct ion_cma_buffer_info { struct sg_table *table; }; -/* - * Create scatter-list for the already allocated DMA buffer. - * This function could be replaced by dma_common_get_sgtable - * as soon as it will avalaible. - */ -static int ion_cma_get_sgtable(struct device *dev, struct sg_table *sgt, - void *cpu_addr, dma_addr_t handle, size_t size) -{ - struct page *page = virt_to_page(cpu_addr); - int ret; - - ret = sg_alloc_table(sgt, 1, GFP_KERNEL); - if (unlikely(ret)) - return ret; - - sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); - return 0; -} /* ION CMA heap operations functions */ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, @@ -91,7 +73,7 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, if (!info->table) goto free_mem; - if (ion_cma_get_sgtable + if (dma_common_get_sgtable (dev, info->table, info->cpu_addr, info->handle, len)) goto free_table; /* keep this for memory release */ -- cgit v0.10.2 From 38c977230c4947d1e99c558a603eb49666a42568 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Wed, 31 Dec 2014 16:57:46 +0530 Subject: staging: xgifb: remove unnecessary check the check for htotal and vtotal is not required as we have already checked for them and returned -EINVAL if any of them is zero. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 709d49e..74a8db8 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -952,7 +952,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, } pr_debug("var->pixclock=%d, htotal=%d, vtotal=%d\n", var->pixclock, htotal, vtotal); - if (var->pixclock && htotal && vtotal) { + if (var->pixclock) { drate = 1000000000 / var->pixclock; hrate = (drate * 1000) / htotal; xgifb_info->refresh_rate = (unsigned int) (hrate * 2 -- cgit v0.10.2 From 95e53ddd8240bad37df985a9ae2d2a07f49e6bf1 Mon Sep 17 00:00:00 2001 From: Mitchel Humpherys Date: Thu, 8 Jan 2015 17:24:27 -0800 Subject: staging: ion: always initialize the free list parameters Currently we initialize the heap free_lock and free list size in ion_heap_init_deferred_free, which is only called when the ION_HEAP_FLAG_DEFER_FREE heap flag is given. However, the lock and size are used in the shrinker path as well as the deferred free path, and we can register a shrinker *without* enabling deferred freeing. So, if a heap provides a shrinker but *doesn't* set the DEFER_FREE flag we will use these parameters uninitialized (resulting in a spinlock bug and broken shrinker accounting). Fix these problems by initializing the free list parameters directly in ion_device_add_heap, which is always called no matter which heap features are being used. Signed-off-by: Mitchel Humpherys Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 296d347..b8f1c49 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1508,6 +1508,9 @@ void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap) pr_err("%s: can not add heap with invalid ops struct.\n", __func__); + spin_lock_init(&heap->free_lock); + heap->free_list_size = 0; + if (heap->flags & ION_HEAP_FLAG_DEFER_FREE) ion_heap_init_deferred_free(heap); diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c index 4605e04..fd13d05 100644 --- a/drivers/staging/android/ion/ion_heap.c +++ b/drivers/staging/android/ion/ion_heap.c @@ -253,8 +253,6 @@ int ion_heap_init_deferred_free(struct ion_heap *heap) struct sched_param param = { .sched_priority = 0 }; INIT_LIST_HEAD(&heap->free_list); - heap->free_list_size = 0; - spin_lock_init(&heap->free_lock); init_waitqueue_head(&heap->waitqueue); heap->task = kthread_run(ion_heap_deferred_free, heap, "%s", heap->name); -- cgit v0.10.2 From 4f0cc93bbbea49b01da6a818766a3e0f79c10180 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 11 Jan 2015 21:01:27 +0100 Subject: staging: virtpci: Remove no-op suspend/resume functions The virtpci bus driver still uses the legacy suspend/resume callbacks. In their current implementation these callbacks only contain a macro that always expands to 'do { } while(0)'. So instead of converting them to dev PM ops just remove them. Signed-off-by: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virtpci/virtpci.c b/drivers/staging/unisys/virtpci/virtpci.c index 729affc..8fdfd6f 100644 --- a/drivers/staging/unisys/virtpci/virtpci.c +++ b/drivers/staging/unisys/virtpci/virtpci.c @@ -104,8 +104,6 @@ static ssize_t virtpci_driver_attr_store(struct kobject *kobj, const char *buf, size_t count); static int virtpci_bus_match(struct device *dev, struct device_driver *drv); static int virtpci_uevent(struct device *dev, struct kobj_uevent_env *env); -static int virtpci_device_suspend(struct device *dev, pm_message_t state); -static int virtpci_device_resume(struct device *dev); static int virtpci_device_probe(struct device *dev); static int virtpci_device_remove(struct device *dev); @@ -128,8 +126,6 @@ static struct bus_type virtpci_bus_type = { .name = "uisvirtpci", .match = virtpci_bus_match, .uevent = virtpci_uevent, - .suspend = virtpci_device_suspend, - .resume = virtpci_device_resume, }; static struct device virtpci_rootbus_device = { @@ -757,18 +753,6 @@ static int virtpci_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } -static int virtpci_device_suspend(struct device *dev, pm_message_t state) -{ - DBGINF("In virtpci_device_suspend -NYI ****\n"); - return 0; -} - -static int virtpci_device_resume(struct device *dev) -{ - DBGINF("In virtpci_device_resume -NYI ****\n"); - return 0; -} - /* For a child device just created on a client bus, fill in * information about the driver that is controlling this device into * the appropriate slot within the vbus channel of the bus -- cgit v0.10.2 From 13c11072536f2613fcf551957a3e3ea972c067cf Mon Sep 17 00:00:00 2001 From: Tsung-Han Lin Date: Thu, 18 Dec 2014 02:33:24 +0800 Subject: staging:board: remove unnecessary function Remove the unnecessary 'of_can_translate_address', which is already removed in commit d9c6866be8a145e32da616d8dcbae806032d75b5 ("of: kill off of_can_translate_address"). Signed-off-by: Tsung-Han Lin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/board/board.c b/drivers/staging/board/board.c index 6050fbd..d5a6abc 100644 --- a/drivers/staging/board/board.c +++ b/drivers/staging/board/board.c @@ -11,8 +11,7 @@ static bool find_by_address(u64 base_address) struct resource res; while (dn) { - if (of_can_translate_address(dn) - && !of_address_to_resource(dn, 0, &res)) { + if (!of_address_to_resource(dn, 0, &res)) { if (res.start == base_address) { of_node_put(dn); return true; -- cgit v0.10.2 From 0541cdf585a8f0049d81abc88a6d735ed2a010d8 Mon Sep 17 00:00:00 2001 From: Steve Pennington Date: Wed, 24 Dec 2014 09:33:02 -0600 Subject: Staging: android: fix line length coding style issue in sync_debug.c This is a patch to sync_debug.c that fixes an over 80 character warning found by the checkpatch.pl tool Signed-off-by: Steve Pennington Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 1532a86..91ed2c4 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -96,7 +96,8 @@ static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence) sync_status_str(status)); if (status <= 0) { - struct timespec64 ts64 = ktime_to_timespec64(pt->base.timestamp); + struct timespec64 ts64 = + ktime_to_timespec64(pt->base.timestamp); seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); } -- cgit v0.10.2 From ddc00b98254e51f33668a08e38f85db9636418c4 Mon Sep 17 00:00:00 2001 From: Guillaume Vercoutere Date: Mon, 5 Jan 2015 15:24:06 +0100 Subject: staging: android: Correct coding style in logger.c Correct intent and missing space Signed-off-by: Guillaume Vercoutere Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index a673ffa..59ea1a7 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -63,7 +63,6 @@ struct logger_log { static LIST_HEAD(log_list); - /** * struct logger_reader - a logging device open for reading * @log: The associated log @@ -89,7 +88,6 @@ static size_t logger_offset(struct logger_log *log, size_t n) return n & (log->size - 1); } - /* * file_get_log - Given a file structure, return the associated log * @@ -122,14 +120,15 @@ static inline struct logger_log *file_get_log(struct file *file) * the log entry spans the end and beginning of the circular buffer. */ static struct logger_entry *get_entry_header(struct logger_log *log, - size_t off, struct logger_entry *scratch) + size_t off, + struct logger_entry *scratch) { size_t len = min(sizeof(struct logger_entry), log->size - off); if (len != sizeof(struct logger_entry)) { - memcpy(((void *) scratch), log->buffer + off, len); - memcpy(((void *) scratch) + len, log->buffer, - sizeof(struct logger_entry) - len); + memcpy(((void *)scratch), log->buffer + off, len); + memcpy(((void *)scratch) + len, log->buffer, + sizeof(struct logger_entry) - len); return scratch; } @@ -163,7 +162,7 @@ static size_t get_user_hdr_len(int ver) } static ssize_t copy_header_to_user(int ver, struct logger_entry *entry, - char __user *buf) + char __user *buf) { void *hdr; size_t hdr_len; @@ -213,7 +212,7 @@ static ssize_t do_read_log_to_user(struct logger_log *log, count -= get_user_hdr_len(reader->r_ver); buf += get_user_hdr_len(reader->r_ver); msg_start = logger_offset(log, - reader->r_off + sizeof(struct logger_entry)); + reader->r_off + sizeof(struct logger_entry)); /* * We read from the msg in two disjoint operations. First, we read from @@ -243,7 +242,7 @@ static ssize_t do_read_log_to_user(struct logger_log *log, * 'log->buffer' which contains the first entry readable by 'euid' */ static size_t get_next_entry_by_uid(struct logger_log *log, - size_t off, kuid_t euid) + size_t off, kuid_t euid) { while (off != log->w_off) { struct logger_entry *entry; @@ -530,8 +529,9 @@ static int logger_open(struct inode *inode, struct file *file) mutex_unlock(&log->mutex); file->private_data = reader; - } else + } else { file->private_data = log; + } return 0; } @@ -611,7 +611,7 @@ static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct logger_log *log = file_get_log(file); struct logger_reader *reader; long ret = -EINVAL; - void __user *argp = (void __user *) arg; + void __user *argp = (void __user *)arg; mutex_lock(&log->mutex); @@ -653,7 +653,7 @@ static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } if (!(in_egroup_p(file_inode(file)->i_gid) || - capable(CAP_SYSLOG))) { + capable(CAP_SYSLOG))) { ret = -EPERM; break; } @@ -741,12 +741,12 @@ static int __init create_log(char *log_name, int size) ret = misc_register(&log->misc); if (unlikely(ret)) { pr_err("failed to register misc device for log '%s'!\n", - log->misc.name); + log->misc.name); goto out_free_misc_name; } pr_info("created %luK log '%s'\n", - (unsigned long) log->size >> 10, log->misc.name); + (unsigned long)log->size >> 10, log->misc.name); return 0; @@ -799,7 +799,6 @@ static void __exit logger_exit(void) } } - device_initcall(logger_init); module_exit(logger_exit); -- cgit v0.10.2 From 002397c4c72d5082a10a4a81946966b5bb3a200f Mon Sep 17 00:00:00 2001 From: Fabian Holler Date: Wed, 7 Jan 2015 10:39:52 +0100 Subject: staging: android: fix indentation to match open parenthesis This patches fixes the following checkpatch.pl warning: ashmem.c:450: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis Signed-off-by: Fabian Holler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 8c78527..181a71e 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -447,8 +447,8 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) loff_t end = (range->pgend + 1) * PAGE_SIZE; vfs_fallocate(range->asma->file, - FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, - start, end - start); + FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + start, end - start); range->purged = ASHMEM_WAS_PURGED; lru_del(range); -- cgit v0.10.2 From e46945ceacc286f7526382bfe8f9e5292a4a2ee1 Mon Sep 17 00:00:00 2001 From: Fabian Holler Date: Wed, 7 Jan 2015 10:39:53 +0100 Subject: staging: android: remove blank lines after open braces This patch fixes the following checkpatch.pl warnings: ashmem.c:552: CHECK:BRACES: Blank lines aren't necessary after an open brace '{' ashmem.c:801: CHECK:BRACES: Blank lines aren't necessary after an open brace Signed-off-by: Fabian Holler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 181a71e..6b228d9 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -549,7 +549,6 @@ static int get_name(struct ashmem_area *asma, void __user *name) mutex_lock(&ashmem_mutex); if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') { - /* * Copying only `len', instead of ASHMEM_NAME_LEN, bytes * prevents us from revealing one user's stack to another. @@ -798,7 +797,6 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static long compat_ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - switch (cmd) { case COMPAT_ASHMEM_SET_SIZE: cmd = ASHMEM_SET_SIZE; -- cgit v0.10.2 From 1703ca9039e3a8362f5d8c4dbb9a68318e734da6 Mon Sep 17 00:00:00 2001 From: Fabian Holler Date: Wed, 7 Jan 2015 10:39:54 +0100 Subject: staging: android: remove space after casts This patch fixes the following checkpatch.pl warnings: ashmem.c:753: CHECK:SPACING: No space is necessary after a cast ashmem.c:756: CHECK:SPACING: No space is necessary after a cast ashmem.c:777: CHECK:SPACING: No space is necessary after a cast Signed-off-by: Fabian Holler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 6b228d9..d140b733 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -750,10 +750,10 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) switch (cmd) { case ASHMEM_SET_NAME: - ret = set_name(asma, (void __user *) arg); + ret = set_name(asma, (void __user *)arg); break; case ASHMEM_GET_NAME: - ret = get_name(asma, (void __user *) arg); + ret = get_name(asma, (void __user *)arg); break; case ASHMEM_SET_SIZE: ret = -EINVAL; @@ -774,7 +774,7 @@ static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case ASHMEM_PIN: case ASHMEM_UNPIN: case ASHMEM_GET_PIN_STATUS: - ret = ashmem_pin_unpin(asma, cmd, (void __user *) arg); + ret = ashmem_pin_unpin(asma, cmd, (void __user *)arg); break; case ASHMEM_PURGE_ALL_CACHES: ret = -EPERM; -- cgit v0.10.2 From 0cba55bac3e349d315f7bad31871d8e7cce23652 Mon Sep 17 00:00:00 2001 From: Aya Mahfouz Date: Wed, 14 Jan 2015 23:46:49 +0200 Subject: staging: davinci_vpfe: fix space prohibited before semicolon warning This patch fixes the following checkpatch.pl warning: space prohibited before semicolon Signed-off-by: Aya Mahfouz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c index 704fa20..a425f71 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c @@ -901,7 +901,7 @@ static int ipipe_set_gbce_params(struct vpfe_ipipe_device *ipipe, void *param) struct device *dev = ipipe->subdev.v4l2_dev->dev; if (!gbce_param) { - memset(gbce, 0 , sizeof(struct vpfe_ipipe_gbce)); + memset(gbce, 0, sizeof(struct vpfe_ipipe_gbce)); } else { memcpy(gbce, gbce_param, sizeof(struct vpfe_ipipe_gbce)); if (ipipe_validate_gbce_params(gbce) < 0) { @@ -1086,7 +1086,7 @@ static int ipipe_set_car_params(struct vpfe_ipipe_device *ipipe, void *param) struct vpfe_ipipe_car *car = &ipipe->config.car; if (!car_param) { - memset(car , 0, sizeof(struct vpfe_ipipe_car)); + memset(car, 0, sizeof(struct vpfe_ipipe_car)); } else { memcpy(car, car_param, sizeof(struct vpfe_ipipe_car)); if (ipipe_validate_car_params(car) < 0) { -- cgit v0.10.2 From ab666bb2dc16fc2af1b1dc0e61438f27c1a6b8ca Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Thu, 15 Jan 2015 19:47:24 +0900 Subject: staging: mt29f_spinand: Fix typo in Kconfig This patch fix a spelling typo in Kconfig. Signed-off-by: Masanari Iida Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/mt29f_spinand/Kconfig b/drivers/staging/mt29f_spinand/Kconfig index 4031748..f3f9cb3 100644 --- a/drivers/staging/mt29f_spinand/Kconfig +++ b/drivers/staging/mt29f_spinand/Kconfig @@ -12,5 +12,5 @@ config MTD_SPINAND_ONDIEECC bool "Use SPINAND internal ECC" depends on MTD_SPINAND_MT29F help - Internel ECC. + Internal ECC. Enables Hardware ECC support for Micron SPI NAND. -- cgit v0.10.2 From c296d5f9957c03994a699d6739c27d4581a9f6c7 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:09 +0100 Subject: staging: fbtft: core support This commit adds the core fbtft framework from https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 815de37..ce8f420 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -106,4 +106,6 @@ source "drivers/staging/unisys/Kconfig" source "drivers/staging/clocking-wizard/Kconfig" +source "drivers/staging/fbtft/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 33c640b..c242787 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -45,3 +45,4 @@ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/ obj-$(CONFIG_CRYPTO_SKEIN) += skein/ obj-$(CONFIG_UNISYSSPAR) += unisys/ obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ +obj-$(CONFIG_FB_TFT) += fbtft/ diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig new file mode 100644 index 0000000..3d6598b --- /dev/null +++ b/drivers/staging/fbtft/Kconfig @@ -0,0 +1,9 @@ +menuconfig FB_TFT + tristate "Support for small TFT LCD display modules" + depends on FB && SPI && GPIOLIB + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + select FB_BACKLIGHT diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile new file mode 100644 index 0000000..9132dde --- /dev/null +++ b/drivers/staging/fbtft/Makefile @@ -0,0 +1,3 @@ +# Core module +obj-$(CONFIG_FB_TFT) += fbtft.o +fbtft-y += fbtft-core.o fbtft-sysfs.o fbtft-bus.o fbtft-io.o diff --git a/drivers/staging/fbtft/README b/drivers/staging/fbtft/README new file mode 100644 index 0000000..bc89b58 --- /dev/null +++ b/drivers/staging/fbtft/README @@ -0,0 +1,32 @@ + FBTFT +========= + +Linux Framebuffer drivers for small TFT LCD display modules. +The module 'fbtft' makes writing drivers for some of these displays very easy. + +Development is done on a Raspberry Pi running the Raspbian "wheezy" distribution. + +INSTALLATION + Download kernel sources + + From Linux 3.15 + cd drivers/video/fbdev/fbtft + git clone https://github.com/notro/fbtft.git + + Add to drivers/video/fbdev/Kconfig: source "drivers/video/fbdev/fbtft/Kconfig" + Add to drivers/video/fbdev/Makefile: obj-y += fbtft/ + + Before Linux 3.15 + cd drivers/video + git clone https://github.com/notro/fbtft.git + + Add to drivers/video/Kconfig: source "drivers/video/fbtft/Kconfig" + Add to drivers/video/Makefile: obj-y += fbtft/ + + Enable driver(s) in menuconfig and build the kernel + + +See wiki for more information: https://github.com/notro/fbtft/wiki + + +Source: https://github.com/notro/fbtft/ diff --git a/drivers/staging/fbtft/fbtft-bus.c b/drivers/staging/fbtft/fbtft-bus.c new file mode 100644 index 0000000..b3cddb0 --- /dev/null +++ b/drivers/staging/fbtft/fbtft-bus.c @@ -0,0 +1,256 @@ +#include +#include +#include +#include +#include "fbtft.h" + + + + +/***************************************************************************** + * + * void (*write_reg)(struct fbtft_par *par, int len, ...); + * + *****************************************************************************/ + +#define define_fbtft_write_reg(func, type, modifier) \ +void func(struct fbtft_par *par, int len, ...) \ +{ \ + va_list args; \ + int i, ret; \ + int offset = 0; \ + type *buf = (type *)par->buf; \ + \ + if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { \ + va_start(args, len); \ + for (i = 0; i < len; i++) { \ + buf[i] = (type)va_arg(args, unsigned int); \ + } \ + va_end(args); \ + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, par->info->device, type, buf, len, "%s: ", __func__); \ + } \ + \ + va_start(args, len); \ + \ + if (par->startbyte) { \ + *(u8 *)par->buf = par->startbyte; \ + buf = (type *)(par->buf + 1); \ + offset = 1; \ + } \ + \ + *buf = modifier((type)va_arg(args, unsigned int)); \ + if (par->gpio.dc != -1) \ + gpio_set_value(par->gpio.dc, 0); \ + ret = par->fbtftops.write(par, par->buf, sizeof(type)+offset); \ + if (ret < 0) { \ + va_end(args); \ + dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret); \ + return; \ + } \ + len--; \ + \ + if (par->startbyte) \ + *(u8 *)par->buf = par->startbyte | 0x2; \ + \ + if (len) { \ + i = len; \ + while (i--) { \ + *buf++ = modifier((type)va_arg(args, unsigned int)); \ + } \ + if (par->gpio.dc != -1) \ + gpio_set_value(par->gpio.dc, 1); \ + ret = par->fbtftops.write(par, par->buf, len * (sizeof(type)+offset)); \ + if (ret < 0) { \ + va_end(args); \ + dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret); \ + return; \ + } \ + } \ + va_end(args); \ +} \ +EXPORT_SYMBOL(func); + +define_fbtft_write_reg(fbtft_write_reg8_bus8, u8, ) +define_fbtft_write_reg(fbtft_write_reg16_bus8, u16, cpu_to_be16) +define_fbtft_write_reg(fbtft_write_reg16_bus16, u16, ) + +void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...) +{ + va_list args; + int i, ret; + int pad = 0; + u16 *buf = (u16 *)par->buf; + + if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { + va_start(args, len); + for (i = 0; i < len; i++) + *(((u8 *)buf) + i) = (u8)va_arg(args, unsigned int); + va_end(args); + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, + par->info->device, u8, buf, len, "%s: ", __func__); + } + if (len <= 0) + return; + + if (par->spi && (par->spi->bits_per_word == 8)) { + /* we're emulating 9-bit, pad start of buffer with no-ops + (assuming here that zero is a no-op) */ + pad = (len % 4) ? 4 - (len % 4) : 0; + for (i = 0; i < pad; i++) + *buf++ = 0x000; + } + + va_start(args, len); + *buf++ = (u8)va_arg(args, unsigned int); + i = len - 1; + while (i--) { + *buf = (u8)va_arg(args, unsigned int); + *buf++ |= 0x100; /* dc=1 */ + } + va_end(args); + ret = par->fbtftops.write(par, par->buf, (len + pad) * sizeof(u16)); + if (ret < 0) { + dev_err(par->info->device, + "%s: write() failed and returned %d\n", __func__, ret); + return; + } +} +EXPORT_SYMBOL(fbtft_write_reg8_bus9); + + + + +/***************************************************************************** + * + * int (*write_vmem)(struct fbtft_par *par); + * + *****************************************************************************/ + +/* 16 bit pixel over 8-bit databus */ +int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16; + u16 *txbuf16 = (u16 *)par->txbuf.buf; + size_t remain; + size_t to_copy; + size_t tx_array_size; + int i; + int ret = 0; + size_t startbyte_size = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", + __func__, offset, len); + + remain = len / 2; + vmem16 = (u16 *)(par->info->screen_base + offset); + + if (par->gpio.dc != -1) + gpio_set_value(par->gpio.dc, 1); + + /* non buffered write */ + if (!par->txbuf.buf) + return par->fbtftops.write(par, vmem16, len); + + /* buffered write */ + tx_array_size = par->txbuf.len / 2; + + if (par->startbyte) { + txbuf16 = (u16 *)(par->txbuf.buf + 1); + tx_array_size -= 2; + *(u8 *)(par->txbuf.buf) = par->startbyte | 0x2; + startbyte_size = 1; + } + + while (remain) { + to_copy = remain > tx_array_size ? tx_array_size : remain; + dev_dbg(par->info->device, " to_copy=%zu, remain=%zu\n", + to_copy, remain - to_copy); + + for (i = 0; i < to_copy; i++) + txbuf16[i] = cpu_to_be16(vmem16[i]); + + vmem16 = vmem16 + to_copy; + ret = par->fbtftops.write(par, par->txbuf.buf, + startbyte_size + to_copy * 2); + if (ret < 0) + return ret; + remain -= to_copy; + } + + return ret; +} +EXPORT_SYMBOL(fbtft_write_vmem16_bus8); + +/* 16 bit pixel over 9-bit SPI bus: dc + high byte, dc + low byte */ +int fbtft_write_vmem16_bus9(struct fbtft_par *par, size_t offset, size_t len) +{ + u8 *vmem8; + u16 *txbuf16 = par->txbuf.buf; + size_t remain; + size_t to_copy; + size_t tx_array_size; + int i; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", + __func__, offset, len); + + if (!par->txbuf.buf) { + dev_err(par->info->device, "%s: txbuf.buf is NULL\n", __func__); + return -1; + } + + remain = len; + vmem8 = par->info->screen_base + offset; + + tx_array_size = par->txbuf.len / 2; + + while (remain) { + to_copy = remain > tx_array_size ? tx_array_size : remain; + dev_dbg(par->info->device, " to_copy=%zu, remain=%zu\n", + to_copy, remain - to_copy); + +#ifdef __LITTLE_ENDIAN + for (i = 0; i < to_copy; i += 2) { + txbuf16[i] = 0x0100 | vmem8[i+1]; + txbuf16[i+1] = 0x0100 | vmem8[i]; + } +#else + for (i = 0; i < to_copy; i++) + txbuf16[i] = 0x0100 | vmem8[i]; +#endif + vmem8 = vmem8 + to_copy; + ret = par->fbtftops.write(par, par->txbuf.buf, to_copy*2); + if (ret < 0) + return ret; + remain -= to_copy; + } + + return ret; +} +EXPORT_SYMBOL(fbtft_write_vmem16_bus9); + +int fbtft_write_vmem8_bus8(struct fbtft_par *par, size_t offset, size_t len) +{ + dev_err(par->info->device, "%s: function not implemented\n", __func__); + return -1; +} +EXPORT_SYMBOL(fbtft_write_vmem8_bus8); + +/* 16 bit pixel over 16-bit databus */ +int fbtft_write_vmem16_bus16(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", + __func__, offset, len); + + vmem16 = (u16 *)(par->info->screen_base + offset); + + if (par->gpio.dc != -1) + gpio_set_value(par->gpio.dc, 1); + + /* no need for buffered write with 16-bit bus */ + return par->fbtftops.write(par, vmem16, len); +} +EXPORT_SYMBOL(fbtft_write_vmem16_bus16); diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c new file mode 100644 index 0000000..873e2c7 --- /dev/null +++ b/drivers/staging/fbtft/fbtft-core.c @@ -0,0 +1,1516 @@ +/* + * Copyright (C) 2013 Noralf Tronnes + * + * This driver is inspired by: + * st7735fb.c, Copyright (C) 2011, Matt Porter + * broadsheetfb.c, Copyright (C) 2008, Jaya Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fbtft.h" + +extern void fbtft_sysfs_init(struct fbtft_par *par); +extern void fbtft_sysfs_exit(struct fbtft_par *par); +extern void fbtft_expand_debug_value(unsigned long *debug); +extern int fbtft_gamma_parse_str(struct fbtft_par *par, unsigned long *curves, + const char *str, int size); + +static unsigned long debug; +module_param(debug, ulong , 0); +MODULE_PARM_DESC(debug, "override device debug level"); + +static bool dma = true; +module_param(dma, bool, 0); +MODULE_PARM_DESC(dma, "Use DMA buffer"); + + +void fbtft_dbg_hex(const struct device *dev, int groupsize, + void *buf, size_t len, const char *fmt, ...) +{ + va_list args; + static char textbuf[512]; + char *text = textbuf; + size_t text_len; + + va_start(args, fmt); + text_len = vscnprintf(text, sizeof(textbuf), fmt, args); + va_end(args); + + hex_dump_to_buffer(buf, len, 32, groupsize, text + text_len, + 512 - text_len, false); + + if (len > 32) + dev_info(dev, "%s ...\n", text); + else + dev_info(dev, "%s\n", text); +} +EXPORT_SYMBOL(fbtft_dbg_hex); + +unsigned long fbtft_request_gpios_match(struct fbtft_par *par, + const struct fbtft_gpio *gpio) +{ + int ret; + long val; + + fbtft_par_dbg(DEBUG_REQUEST_GPIOS_MATCH, par, "%s('%s')\n", + __func__, gpio->name); + + if (strcasecmp(gpio->name, "reset") == 0) { + par->gpio.reset = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } else if (strcasecmp(gpio->name, "dc") == 0) { + par->gpio.dc = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } else if (strcasecmp(gpio->name, "cs") == 0) { + par->gpio.cs = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } else if (strcasecmp(gpio->name, "wr") == 0) { + par->gpio.wr = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } else if (strcasecmp(gpio->name, "rd") == 0) { + par->gpio.rd = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } else if (strcasecmp(gpio->name, "latch") == 0) { + par->gpio.latch = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } else if (gpio->name[0] == 'd' && gpio->name[1] == 'b') { + ret = kstrtol(&gpio->name[2], 10, &val); + if (ret == 0 && val < 16) { + par->gpio.db[val] = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } + } else if (strcasecmp(gpio->name, "led") == 0) { + par->gpio.led[0] = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } else if (strcasecmp(gpio->name, "led_") == 0) { + par->gpio.led[0] = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } + + return FBTFT_GPIO_NO_MATCH; +} + +int fbtft_request_gpios(struct fbtft_par *par) +{ + struct fbtft_platform_data *pdata = par->pdata; + const struct fbtft_gpio *gpio; + unsigned long flags; + int ret; + + if (pdata && pdata->gpios) { + gpio = pdata->gpios; + while (gpio->name[0]) { + flags = FBTFT_GPIO_NO_MATCH; + /* if driver provides match function, try it first, + if no match use our own */ + if (par->fbtftops.request_gpios_match) + flags = par->fbtftops.request_gpios_match(par, gpio); + if (flags == FBTFT_GPIO_NO_MATCH) + flags = fbtft_request_gpios_match(par, gpio); + if (flags != FBTFT_GPIO_NO_MATCH) { + ret = devm_gpio_request_one(par->info->device, + gpio->gpio, flags, + par->info->device->driver->name); + if (ret < 0) { + dev_err(par->info->device, + "%s: gpio_request_one('%s'=%d) failed with %d\n", + __func__, gpio->name, + gpio->gpio, ret); + return ret; + } + fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, + "%s: '%s' = GPIO%d\n", + __func__, gpio->name, gpio->gpio); + } + gpio++; + } + } + + return 0; +} + +#ifdef CONFIG_OF +static int fbtft_request_one_gpio(struct fbtft_par *par, + const char *name, int index, int *gpiop) +{ + struct device *dev = par->info->device; + struct device_node *node = dev->of_node; + int gpio, flags, ret = 0; + enum of_gpio_flags of_flags; + + if (of_find_property(node, name, NULL)) { + gpio = of_get_named_gpio_flags(node, name, index, &of_flags); + if (gpio == -ENOENT) + return 0; + if (gpio == -EPROBE_DEFER) + return gpio; + if (gpio < 0) { + dev_err(dev, + "failed to get '%s' from DT\n", name); + return gpio; + } + + /* active low translates to initially low */ + flags = (of_flags & OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW : + GPIOF_OUT_INIT_HIGH; + ret = devm_gpio_request_one(dev, gpio, flags, + dev->driver->name); + if (ret) { + dev_err(dev, + "gpio_request_one('%s'=%d) failed with %d\n", + name, gpio, ret); + return ret; + } + if (gpiop) + *gpiop = gpio; + fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' = GPIO%d\n", + __func__, name, gpio); + } + + return ret; +} + +static int fbtft_request_gpios_dt(struct fbtft_par *par) +{ + int i; + int ret; + + if (!par->info->device->of_node) + return -EINVAL; + + ret = fbtft_request_one_gpio(par, "reset-gpios", 0, &par->gpio.reset); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "dc-gpios", 0, &par->gpio.dc); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "rd-gpios", 0, &par->gpio.rd); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "wr-gpios", 0, &par->gpio.wr); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "cs-gpios", 0, &par->gpio.cs); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "latch-gpios", 0, &par->gpio.latch); + if (ret) + return ret; + for (i = 0; i < 16; i++) { + ret = fbtft_request_one_gpio(par, "db-gpios", i, + &par->gpio.db[i]); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "led-gpios", i, + &par->gpio.led[i]); + if (ret) + return ret; + ret = fbtft_request_one_gpio(par, "aux-gpios", i, + &par->gpio.aux[i]); + if (ret) + return ret; + } + + return 0; +} +#endif + +#ifdef CONFIG_FB_BACKLIGHT +int fbtft_backlight_update_status(struct backlight_device *bd) +{ + struct fbtft_par *par = bl_get_data(bd); + bool polarity = !!(bd->props.state & BL_CORE_DRIVER1); + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, + "%s: polarity=%d, power=%d, fb_blank=%d\n", + __func__, polarity, bd->props.power, bd->props.fb_blank); + + if ((bd->props.power == FB_BLANK_UNBLANK) && (bd->props.fb_blank == FB_BLANK_UNBLANK)) + gpio_set_value(par->gpio.led[0], polarity); + else + gpio_set_value(par->gpio.led[0], !polarity); + + return 0; +} + +int fbtft_backlight_get_brightness(struct backlight_device *bd) +{ + return bd->props.brightness; +} + +void fbtft_unregister_backlight(struct fbtft_par *par) +{ + const struct backlight_ops *bl_ops; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, "%s()\n", __func__); + + if (par->info->bl_dev) { + par->info->bl_dev->props.power = FB_BLANK_POWERDOWN; + backlight_update_status(par->info->bl_dev); + bl_ops = par->info->bl_dev->ops; + backlight_device_unregister(par->info->bl_dev); + par->info->bl_dev = NULL; + } +} + +void fbtft_register_backlight(struct fbtft_par *par) +{ + struct backlight_device *bd; + struct backlight_properties bl_props = { 0, }; + struct backlight_ops *bl_ops; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, "%s()\n", __func__); + + if (par->gpio.led[0] == -1) { + fbtft_par_dbg(DEBUG_BACKLIGHT, par, + "%s(): led pin not set, exiting.\n", __func__); + return; + } + + bl_ops = devm_kzalloc(par->info->device, sizeof(struct backlight_ops), + GFP_KERNEL); + if (!bl_ops) { + dev_err(par->info->device, + "%s: could not allocate memeory for backlight operations.\n", + __func__); + return; + } + + bl_ops->get_brightness = fbtft_backlight_get_brightness; + bl_ops->update_status = fbtft_backlight_update_status; + bl_props.type = BACKLIGHT_RAW; + /* Assume backlight is off, get polarity from current state of pin */ + bl_props.power = FB_BLANK_POWERDOWN; + if (!gpio_get_value(par->gpio.led[0])) + bl_props.state |= BL_CORE_DRIVER1; + + bd = backlight_device_register(dev_driver_string(par->info->device), + par->info->device, par, bl_ops, &bl_props); + if (IS_ERR(bd)) { + dev_err(par->info->device, + "cannot register backlight device (%ld)\n", + PTR_ERR(bd)); + return; + } + par->info->bl_dev = bd; + + if (!par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight = fbtft_unregister_backlight; +} +#else +void fbtft_register_backlight(struct fbtft_par *par) { }; +void fbtft_unregister_backlight(struct fbtft_par *par) { }; +#endif +EXPORT_SYMBOL(fbtft_register_backlight); +EXPORT_SYMBOL(fbtft_unregister_backlight); + +void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address set */ + write_reg(par, 0x2A, + (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF); + + /* Row adress set */ + write_reg(par, 0x2B, + (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + + +void fbtft_reset(struct fbtft_par *par) +{ + if (par->gpio.reset == -1) + return; + fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__); + gpio_set_value(par->gpio.reset, 0); + udelay(20); + gpio_set_value(par->gpio.reset, 1); + mdelay(120); +} + + +void fbtft_update_display(struct fbtft_par *par, unsigned start_line, unsigned end_line) +{ + size_t offset, len; + struct timespec ts_start, ts_end, ts_fps, ts_duration; + long fps_ms, fps_us, duration_ms, duration_us; + long fps, throughput; + bool timeit = false; + int ret = 0; + + if (unlikely(par->debug & (DEBUG_TIME_FIRST_UPDATE | DEBUG_TIME_EACH_UPDATE))) { + if ((par->debug & DEBUG_TIME_EACH_UPDATE) || \ + ((par->debug & DEBUG_TIME_FIRST_UPDATE) && !par->first_update_done)) { + getnstimeofday(&ts_start); + timeit = true; + } + } + + /* Sanity checks */ + if (start_line > end_line) { + dev_warn(par->info->device, + "%s: start_line=%u is larger than end_line=%u. Shouldn't happen, will do full display update\n", + __func__, start_line, end_line); + start_line = 0; + end_line = par->info->var.yres - 1; + } + if (start_line > par->info->var.yres - 1 || end_line > par->info->var.yres - 1) { + dev_warn(par->info->device, + "%s: start_line=%u or end_line=%u is larger than max=%d. Shouldn't happen, will do full display update\n", + __func__, start_line, end_line, par->info->var.yres - 1); + start_line = 0; + end_line = par->info->var.yres - 1; + } + + fbtft_par_dbg(DEBUG_UPDATE_DISPLAY, par, "%s(start_line=%u, end_line=%u)\n", + __func__, start_line, end_line); + + if (par->fbtftops.set_addr_win) + par->fbtftops.set_addr_win(par, 0, start_line, + par->info->var.xres-1, end_line); + + offset = start_line * par->info->fix.line_length; + len = (end_line - start_line + 1) * par->info->fix.line_length; + ret = par->fbtftops.write_vmem(par, offset, len); + if (ret < 0) + dev_err(par->info->device, + "%s: write_vmem failed to update display buffer\n", + __func__); + + if (unlikely(timeit)) { + getnstimeofday(&ts_end); + if (par->update_time.tv_nsec == 0 && par->update_time.tv_sec == 0) { + par->update_time.tv_sec = ts_start.tv_sec; + par->update_time.tv_nsec = ts_start.tv_nsec; + } + ts_fps = timespec_sub(ts_start, par->update_time); + par->update_time.tv_sec = ts_start.tv_sec; + par->update_time.tv_nsec = ts_start.tv_nsec; + fps_ms = (ts_fps.tv_sec * 1000) + ((ts_fps.tv_nsec / 1000000) % 1000); + fps_us = (ts_fps.tv_nsec / 1000) % 1000; + fps = fps_ms * 1000 + fps_us; + fps = fps ? 1000000 / fps : 0; + + ts_duration = timespec_sub(ts_end, ts_start); + duration_ms = (ts_duration.tv_sec * 1000) + ((ts_duration.tv_nsec / 1000000) % 1000); + duration_us = (ts_duration.tv_nsec / 1000) % 1000; + throughput = duration_ms * 1000 + duration_us; + throughput = throughput ? (len * 1000) / throughput : 0; + throughput = throughput * 1000 / 1024; + + dev_info(par->info->device, + "Display update: %ld kB/s (%ld.%.3ld ms), fps=%ld (%ld.%.3ld ms)\n", + throughput, duration_ms, duration_us, + fps, fps_ms, fps_us); + par->first_update_done = true; + } +} + + +void fbtft_mkdirty(struct fb_info *info, int y, int height) +{ + struct fbtft_par *par = info->par; + struct fb_deferred_io *fbdefio = info->fbdefio; + + /* special case, needed ? */ + if (y == -1) { + y = 0; + height = info->var.yres - 1; + } + + /* Mark display lines/area as dirty */ + spin_lock(&par->dirty_lock); + if (y < par->dirty_lines_start) + par->dirty_lines_start = y; + if (y + height - 1 > par->dirty_lines_end) + par->dirty_lines_end = y + height - 1; + spin_unlock(&par->dirty_lock); + + /* Schedule deferred_io to update display (no-op if already on queue)*/ + schedule_delayed_work(&info->deferred_work, fbdefio->delay); +} + +void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist) +{ + struct fbtft_par *par = info->par; + unsigned dirty_lines_start, dirty_lines_end; + struct page *page; + unsigned long index; + unsigned y_low = 0, y_high = 0; + int count = 0; + + spin_lock(&par->dirty_lock); + dirty_lines_start = par->dirty_lines_start; + dirty_lines_end = par->dirty_lines_end; + /* set display line markers as clean */ + par->dirty_lines_start = par->info->var.yres - 1; + par->dirty_lines_end = 0; + spin_unlock(&par->dirty_lock); + + /* Mark display lines as dirty */ + list_for_each_entry(page, pagelist, lru) { + count++; + index = page->index << PAGE_SHIFT; + y_low = index / info->fix.line_length; + y_high = (index + PAGE_SIZE - 1) / info->fix.line_length; + fbtft_dev_dbg(DEBUG_DEFERRED_IO, par, info->device, + "page->index=%lu y_low=%d y_high=%d\n", + page->index, y_low, y_high); + if (y_high > info->var.yres - 1) + y_high = info->var.yres - 1; + if (y_low < dirty_lines_start) + dirty_lines_start = y_low; + if (y_high > dirty_lines_end) + dirty_lines_end = y_high; + } + + par->fbtftops.update_display(info->par, + dirty_lines_start, dirty_lines_end); +} + + +void fbtft_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + struct fbtft_par *par = info->par; + + fbtft_dev_dbg(DEBUG_FB_FILLRECT, par, info->dev, + "%s: dx=%d, dy=%d, width=%d, height=%d\n", + __func__, rect->dx, rect->dy, rect->width, rect->height); + sys_fillrect(info, rect); + + par->fbtftops.mkdirty(info, rect->dy, rect->height); +} + +void fbtft_fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) +{ + struct fbtft_par *par = info->par; + + fbtft_dev_dbg(DEBUG_FB_COPYAREA, par, info->dev, + "%s: dx=%d, dy=%d, width=%d, height=%d\n", + __func__, area->dx, area->dy, area->width, area->height); + sys_copyarea(info, area); + + par->fbtftops.mkdirty(info, area->dy, area->height); +} + +void fbtft_fb_imageblit(struct fb_info *info, const struct fb_image *image) +{ + struct fbtft_par *par = info->par; + + fbtft_dev_dbg(DEBUG_FB_IMAGEBLIT, par, info->dev, + "%s: dx=%d, dy=%d, width=%d, height=%d\n", + __func__, image->dx, image->dy, image->width, image->height); + sys_imageblit(info, image); + + par->fbtftops.mkdirty(info, image->dy, image->height); +} + +ssize_t fbtft_fb_write(struct fb_info *info, + const char __user *buf, size_t count, loff_t *ppos) +{ + struct fbtft_par *par = info->par; + ssize_t res; + + fbtft_dev_dbg(DEBUG_FB_WRITE, par, info->dev, + "%s: count=%zd, ppos=%llu\n", __func__, count, *ppos); + res = fb_sys_write(info, buf, count, ppos); + + /* TODO: only mark changed area + update all for now */ + par->fbtftops.mkdirty(info, -1, 0); + + return res; +} + +/* from pxafb.c */ +unsigned int chan_to_field(unsigned chan, struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +int fbtft_fb_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + struct fbtft_par *par = info->par; + unsigned val; + int ret = 1; + + fbtft_dev_dbg(DEBUG_FB_SETCOLREG, par, info->dev, + "%s(regno=%u, red=0x%X, green=0x%X, blue=0x%X, trans=0x%X)\n", + __func__, regno, red, green, blue, transp); + + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + if (regno < 16) { + u32 *pal = info->pseudo_palette; + + val = chan_to_field(red, &info->var.red); + val |= chan_to_field(green, &info->var.green); + val |= chan_to_field(blue, &info->var.blue); + + pal[regno] = val; + ret = 0; + } + break; + + } + return ret; +} + +int fbtft_fb_blank(int blank, struct fb_info *info) +{ + struct fbtft_par *par = info->par; + int ret = -EINVAL; + + fbtft_dev_dbg(DEBUG_FB_BLANK, par, info->dev, "%s(blank=%d)\n", + __func__, blank); + + if (!par->fbtftops.blank) + return ret; + + switch (blank) { + case FB_BLANK_POWERDOWN: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_NORMAL: + ret = par->fbtftops.blank(par, true); + break; + case FB_BLANK_UNBLANK: + ret = par->fbtftops.blank(par, false); + break; + } + return ret; +} + +void fbtft_merge_fbtftops(struct fbtft_ops *dst, struct fbtft_ops *src) +{ + if (src->write) + dst->write = src->write; + if (src->read) + dst->read = src->read; + if (src->write_vmem) + dst->write_vmem = src->write_vmem; + if (src->write_register) + dst->write_register = src->write_register; + if (src->set_addr_win) + dst->set_addr_win = src->set_addr_win; + if (src->reset) + dst->reset = src->reset; + if (src->mkdirty) + dst->mkdirty = src->mkdirty; + if (src->update_display) + dst->update_display = src->update_display; + if (src->init_display) + dst->init_display = src->init_display; + if (src->blank) + dst->blank = src->blank; + if (src->request_gpios_match) + dst->request_gpios_match = src->request_gpios_match; + if (src->request_gpios) + dst->request_gpios = src->request_gpios; + if (src->verify_gpios) + dst->verify_gpios = src->verify_gpios; + if (src->register_backlight) + dst->register_backlight = src->register_backlight; + if (src->unregister_backlight) + dst->unregister_backlight = src->unregister_backlight; + if (src->set_var) + dst->set_var = src->set_var; + if (src->set_gamma) + dst->set_gamma = src->set_gamma; +} + +/** + * fbtft_framebuffer_alloc - creates a new frame buffer info structure + * + * @display: pointer to structure describing the display + * @dev: pointer to the device for this fb, this can be NULL + * + * Creates a new frame buffer info structure. + * + * Also creates and populates the following structures: + * info->fbops + * info->fbdefio + * info->pseudo_palette + * par->fbtftops + * par->txbuf + * + * Returns the new structure, or NULL if an error occurred. + * + */ +struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, + struct device *dev) +{ + struct fb_info *info; + struct fbtft_par *par; + struct fb_ops *fbops = NULL; + struct fb_deferred_io *fbdefio = NULL; + struct fbtft_platform_data *pdata = dev->platform_data; + u8 *vmem = NULL; + void *txbuf = NULL; + void *buf = NULL; + unsigned width; + unsigned height; + int txbuflen = display->txbuflen; + unsigned bpp = display->bpp; + unsigned fps = display->fps; + int vmem_size, i; + int *init_sequence = display->init_sequence; + char *gamma = display->gamma; + unsigned long *gamma_curves = NULL; + + /* sanity check */ + if (display->gamma_num * display->gamma_len > FBTFT_GAMMA_MAX_VALUES_TOTAL) { + dev_err(dev, + "%s: FBTFT_GAMMA_MAX_VALUES_TOTAL=%d is exceeded\n", + __func__, FBTFT_GAMMA_MAX_VALUES_TOTAL); + return NULL; + } + + /* defaults */ + if (!fps) + fps = 20; + if (!bpp) + bpp = 16; + + if (!pdata) { + dev_err(dev, "platform data is missing\n"); + return NULL; + } + + /* override driver values? */ + if (pdata->fps) + fps = pdata->fps; + if (pdata->txbuflen) + txbuflen = pdata->txbuflen; + if (pdata->display.init_sequence) + init_sequence = pdata->display.init_sequence; + if (pdata->gamma) + gamma = pdata->gamma; + if (pdata->display.debug) + display->debug = pdata->display.debug; + if (pdata->display.backlight) + display->backlight = pdata->display.backlight; + if (pdata->display.width) + display->width = pdata->display.width; + if (pdata->display.height) + display->height = pdata->display.height; + if (pdata->display.buswidth) + display->buswidth = pdata->display.buswidth; + if (pdata->display.regwidth) + display->regwidth = pdata->display.regwidth; + + display->debug |= debug; + fbtft_expand_debug_value(&display->debug); + + switch (pdata->rotate) { + case 90: + case 270: + width = display->height; + height = display->width; + break; + default: + width = display->width; + height = display->height; + } + + vmem_size = display->width * display->height * bpp / 8; + vmem = vzalloc(vmem_size); + if (!vmem) + goto alloc_fail; + + fbops = devm_kzalloc(dev, sizeof(struct fb_ops), GFP_KERNEL); + if (!fbops) + goto alloc_fail; + + fbdefio = devm_kzalloc(dev, sizeof(struct fb_deferred_io), GFP_KERNEL); + if (!fbdefio) + goto alloc_fail; + + buf = devm_kzalloc(dev, 128, GFP_KERNEL); + if (!buf) + goto alloc_fail; + + if (display->gamma_num && display->gamma_len) { + gamma_curves = devm_kzalloc(dev, display->gamma_num * display->gamma_len * sizeof(gamma_curves[0]), + GFP_KERNEL); + if (!gamma_curves) + goto alloc_fail; + } + + info = framebuffer_alloc(sizeof(struct fbtft_par), dev); + if (!info) + goto alloc_fail; + + info->screen_base = (u8 __force __iomem *)vmem; + info->fbops = fbops; + info->fbdefio = fbdefio; + + fbops->owner = dev->driver->owner; + fbops->fb_read = fb_sys_read; + fbops->fb_write = fbtft_fb_write; + fbops->fb_fillrect = fbtft_fb_fillrect; + fbops->fb_copyarea = fbtft_fb_copyarea; + fbops->fb_imageblit = fbtft_fb_imageblit; + fbops->fb_setcolreg = fbtft_fb_setcolreg; + fbops->fb_blank = fbtft_fb_blank; + + fbdefio->delay = HZ/fps; + fbdefio->deferred_io = fbtft_deferred_io; + fb_deferred_io_init(info); + + strncpy(info->fix.id, dev->driver->name, 16); + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.xpanstep = 0; + info->fix.ypanstep = 0; + info->fix.ywrapstep = 0; + info->fix.line_length = width*bpp/8; + info->fix.accel = FB_ACCEL_NONE; + info->fix.smem_len = vmem_size; + + info->var.rotate = pdata->rotate; + info->var.xres = width; + info->var.yres = height; + info->var.xres_virtual = info->var.xres; + info->var.yres_virtual = info->var.yres; + info->var.bits_per_pixel = bpp; + info->var.nonstd = 1; + + /* RGB565 */ + info->var.red.offset = 11; + info->var.red.length = 5; + info->var.green.offset = 5; + info->var.green.length = 6; + info->var.blue.offset = 0; + info->var.blue.length = 5; + info->var.transp.offset = 0; + info->var.transp.length = 0; + + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; + + par = info->par; + par->info = info; + par->pdata = dev->platform_data; + par->debug = display->debug; + par->buf = buf; + spin_lock_init(&par->dirty_lock); + par->bgr = pdata->bgr; + par->startbyte = pdata->startbyte; + par->init_sequence = init_sequence; + par->gamma.curves = gamma_curves; + par->gamma.num_curves = display->gamma_num; + par->gamma.num_values = display->gamma_len; + mutex_init(&par->gamma.lock); + info->pseudo_palette = par->pseudo_palette; + + if (par->gamma.curves && gamma) { + if (fbtft_gamma_parse_str(par, + par->gamma.curves, gamma, strlen(gamma))) + goto alloc_fail; + } + + /* Transmit buffer */ + if (txbuflen == -1) + txbuflen = vmem_size + 2; /* add in case startbyte is used */ + +#ifdef __LITTLE_ENDIAN + if ((!txbuflen) && (bpp > 8)) + txbuflen = PAGE_SIZE; /* need buffer for byteswapping */ +#endif + + if (txbuflen > 0) { + if (dma) { + dev->coherent_dma_mask = ~0; + txbuf = dmam_alloc_coherent(dev, txbuflen, &par->txbuf.dma, GFP_DMA); + } else { + txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_KERNEL); + } + if (!txbuf) + goto alloc_fail; + par->txbuf.buf = txbuf; + par->txbuf.len = txbuflen; + } + + /* Initialize gpios to disabled */ + par->gpio.reset = -1; + par->gpio.dc = -1; + par->gpio.rd = -1; + par->gpio.wr = -1; + par->gpio.cs = -1; + par->gpio.latch = -1; + for (i = 0; i < 16; i++) { + par->gpio.db[i] = -1; + par->gpio.led[i] = -1; + par->gpio.aux[i] = -1; + } + + /* default fbtft operations */ + par->fbtftops.write = fbtft_write_spi; + par->fbtftops.read = fbtft_read_spi; + par->fbtftops.write_vmem = fbtft_write_vmem16_bus8; + par->fbtftops.write_register = fbtft_write_reg8_bus8; + par->fbtftops.set_addr_win = fbtft_set_addr_win; + par->fbtftops.reset = fbtft_reset; + par->fbtftops.mkdirty = fbtft_mkdirty; + par->fbtftops.update_display = fbtft_update_display; + par->fbtftops.request_gpios = fbtft_request_gpios; + if (display->backlight) + par->fbtftops.register_backlight = fbtft_register_backlight; + + /* use driver provided functions */ + fbtft_merge_fbtftops(&par->fbtftops, &display->fbtftops); + + return info; + +alloc_fail: + vfree(vmem); + + return NULL; +} +EXPORT_SYMBOL(fbtft_framebuffer_alloc); + +/** + * fbtft_framebuffer_release - frees up all memory used by the framebuffer + * + * @info: frame buffer info structure + * + */ +void fbtft_framebuffer_release(struct fb_info *info) +{ + fb_deferred_io_cleanup(info); + vfree(info->screen_base); + framebuffer_release(info); +} +EXPORT_SYMBOL(fbtft_framebuffer_release); + +/** + * fbtft_register_framebuffer - registers a tft frame buffer device + * @fb_info: frame buffer info structure + * + * Sets SPI driverdata if needed + * Requests needed gpios. + * Initializes display + * Updates display. + * Registers a frame buffer device @fb_info. + * + * Returns negative errno on error, or zero for success. + * + */ +int fbtft_register_framebuffer(struct fb_info *fb_info) +{ + int ret; + char text1[50] = ""; + char text2[50] = ""; + struct fbtft_par *par = fb_info->par; + struct spi_device *spi = par->spi; + + /* sanity checks */ + if (!par->fbtftops.init_display) { + dev_err(fb_info->device, "missing fbtftops.init_display()\n"); + return -EINVAL; + } + + if (spi) + spi_set_drvdata(spi, fb_info); + if (par->pdev) + platform_set_drvdata(par->pdev, fb_info); + + ret = par->fbtftops.request_gpios(par); + if (ret < 0) + goto reg_fail; + + if (par->fbtftops.verify_gpios) { + ret = par->fbtftops.verify_gpios(par); + if (ret < 0) + goto reg_fail; + } + + ret = par->fbtftops.init_display(par); + if (ret < 0) + goto reg_fail; + if (par->fbtftops.set_var) { + ret = par->fbtftops.set_var(par); + if (ret < 0) + goto reg_fail; + } + + /* update the entire display */ + par->fbtftops.update_display(par, 0, par->info->var.yres - 1); + + if (par->fbtftops.set_gamma && par->gamma.curves) { + ret = par->fbtftops.set_gamma(par, par->gamma.curves); + if (ret) + goto reg_fail; + } + + if (par->fbtftops.register_backlight) + par->fbtftops.register_backlight(par); + + ret = register_framebuffer(fb_info); + if (ret < 0) + goto reg_fail; + + fbtft_sysfs_init(par); + + if (par->txbuf.buf) + sprintf(text1, ", %d KiB %sbuffer memory", + par->txbuf.len >> 10, par->txbuf.dma ? "DMA " : ""); + if (spi) + sprintf(text2, ", spi%d.%d at %d MHz", spi->master->bus_num, + spi->chip_select, spi->max_speed_hz/1000000); + dev_info(fb_info->dev, + "%s frame buffer, %dx%d, %d KiB video memory%s, fps=%lu%s\n", + fb_info->fix.id, fb_info->var.xres, fb_info->var.yres, + fb_info->fix.smem_len >> 10, text1, + HZ/fb_info->fbdefio->delay, text2); + +#ifdef CONFIG_FB_BACKLIGHT + /* Turn on backlight if available */ + if (fb_info->bl_dev) { + fb_info->bl_dev->props.power = FB_BLANK_UNBLANK; + fb_info->bl_dev->ops->update_status(fb_info->bl_dev); + } +#endif + + return 0; + +reg_fail: + if (par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight(par); + if (spi) + spi_set_drvdata(spi, NULL); + if (par->pdev) + platform_set_drvdata(par->pdev, NULL); + + return ret; +} +EXPORT_SYMBOL(fbtft_register_framebuffer); + +/** + * fbtft_unregister_framebuffer - releases a tft frame buffer device + * @fb_info: frame buffer info structure + * + * Frees SPI driverdata if needed + * Frees gpios. + * Unregisters frame buffer device. + * + */ +int fbtft_unregister_framebuffer(struct fb_info *fb_info) +{ + struct fbtft_par *par = fb_info->par; + struct spi_device *spi = par->spi; + int ret; + + if (spi) + spi_set_drvdata(spi, NULL); + if (par->pdev) + platform_set_drvdata(par->pdev, NULL); + if (par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight(par); + fbtft_sysfs_exit(par); + ret = unregister_framebuffer(fb_info); + return ret; +} +EXPORT_SYMBOL(fbtft_unregister_framebuffer); + +#ifdef CONFIG_OF +/** + * fbtft_init_display_dt() - Device Tree init_display() function + * @par: Driver data + * + * Return: 0 if successful, negative if error + */ +static int fbtft_init_display_dt(struct fbtft_par *par) +{ + struct device_node *node = par->info->device->of_node; + struct property *prop; + const __be32 *p; + u32 val; + int buf[64], i, j; + char msg[128]; + char str[16]; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + if (!node) + return -EINVAL; + + prop = of_find_property(node, "init", NULL); + p = of_prop_next_u32(prop, NULL, &val); + if (!p) + return -EINVAL; + while (p) { + if (val & FBTFT_OF_INIT_CMD) { + val &= 0xFFFF; + i = 0; + while (p && !(val & 0xFFFF0000)) { + if (i > 63) { + dev_err(par->info->device, + "%s: Maximum register values exceeded\n", + __func__); + return -EINVAL; + } + buf[i++] = val; + p = of_prop_next_u32(prop, p, &val); + } + /* make debug message */ + msg[0] = '\0'; + for (j = 0; j < i; j++) { + snprintf(str, 128, " %02X", buf[j]); + strcat(msg, str); + } + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "init: write_register:%s\n", msg); + + par->fbtftops.write_register(par, i, + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7], + buf[8], buf[9], buf[10], buf[11], + buf[12], buf[13], buf[14], buf[15], + buf[16], buf[17], buf[18], buf[19], + buf[20], buf[21], buf[22], buf[23], + buf[24], buf[25], buf[26], buf[27], + buf[28], buf[29], buf[30], buf[31], + buf[32], buf[33], buf[34], buf[35], + buf[36], buf[37], buf[38], buf[39], + buf[40], buf[41], buf[42], buf[43], + buf[44], buf[45], buf[46], buf[47], + buf[48], buf[49], buf[50], buf[51], + buf[52], buf[53], buf[54], buf[55], + buf[56], buf[57], buf[58], buf[59], + buf[60], buf[61], buf[62], buf[63]); + } else if (val & FBTFT_OF_INIT_DELAY) { + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "init: msleep(%u)\n", val & 0xFFFF); + msleep(val & 0xFFFF); + p = of_prop_next_u32(prop, p, &val); + } else { + dev_err(par->info->device, "illegal init value 0x%X\n", + val); + return -EINVAL; + } + } + + return 0; +} +#endif + +/** + * fbtft_init_display() - Generic init_display() function + * @par: Driver data + * + * Uses par->init_sequence to do the initialization + * + * Return: 0 if successful, negative if error + */ +int fbtft_init_display(struct fbtft_par *par) +{ + int buf[64]; + char msg[128]; + char str[16]; + int i = 0; + int j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* sanity check */ + if (!par->init_sequence) { + dev_err(par->info->device, + "error: init_sequence is not set\n"); + return -EINVAL; + } + + /* make sure stop marker exists */ + for (i = 0; i < FBTFT_MAX_INIT_SEQUENCE; i++) + if (par->init_sequence[i] == -3) + break; + if (i == FBTFT_MAX_INIT_SEQUENCE) { + dev_err(par->info->device, + "missing stop marker at end of init sequence\n"); + return -EINVAL; + } + + par->fbtftops.reset(par); + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + i = 0; + while (i < FBTFT_MAX_INIT_SEQUENCE) { + if (par->init_sequence[i] == -3) { + /* done */ + return 0; + } + if (par->init_sequence[i] >= 0) { + dev_err(par->info->device, + "missing delimiter at position %d\n", i); + return -EINVAL; + } + if (par->init_sequence[i+1] < 0) { + dev_err(par->info->device, + "missing value after delimiter %d at position %d\n", + par->init_sequence[i], i); + return -EINVAL; + } + switch (par->init_sequence[i]) { + case -1: + i++; + /* make debug message */ + strcpy(msg, ""); + j = i + 1; + while (par->init_sequence[j] >= 0) { + sprintf(str, "0x%02X ", par->init_sequence[j]); + strcat(msg, str); + j++; + } + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "init: write(0x%02X) %s\n", + par->init_sequence[i], msg); + + /* Write */ + j = 0; + while (par->init_sequence[i] >= 0) { + if (j > 63) { + dev_err(par->info->device, + "%s: Maximum register values exceeded\n", + __func__); + return -EINVAL; + } + buf[j++] = par->init_sequence[i++]; + } + par->fbtftops.write_register(par, j, + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7], + buf[8], buf[9], buf[10], buf[11], + buf[12], buf[13], buf[14], buf[15], + buf[16], buf[17], buf[18], buf[19], + buf[20], buf[21], buf[22], buf[23], + buf[24], buf[25], buf[26], buf[27], + buf[28], buf[29], buf[30], buf[31], + buf[32], buf[33], buf[34], buf[35], + buf[36], buf[37], buf[38], buf[39], + buf[40], buf[41], buf[42], buf[43], + buf[44], buf[45], buf[46], buf[47], + buf[48], buf[49], buf[50], buf[51], + buf[52], buf[53], buf[54], buf[55], + buf[56], buf[57], buf[58], buf[59], + buf[60], buf[61], buf[62], buf[63]); + break; + case -2: + i++; + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "init: mdelay(%d)\n", par->init_sequence[i]); + mdelay(par->init_sequence[i++]); + break; + default: + dev_err(par->info->device, + "unknown delimiter %d at position %d\n", + par->init_sequence[i], i); + return -EINVAL; + } + } + + dev_err(par->info->device, + "%s: something is wrong. Shouldn't get here.\n", __func__); + return -EINVAL; +} +EXPORT_SYMBOL(fbtft_init_display); + +/** + * fbtft_verify_gpios() - Generic verify_gpios() function + * @par: Driver data + * + * Uses @spi, @pdev and @buswidth to determine which GPIOs is needed + * + * Return: 0 if successful, negative if error + */ +int fbtft_verify_gpios(struct fbtft_par *par) +{ + struct fbtft_platform_data *pdata; + int i; + + fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__); + + pdata = par->info->device->platform_data; + if (pdata->display.buswidth != 9 && par->startbyte == 0 && \ + par->gpio.dc < 0) { + dev_err(par->info->device, + "Missing info about 'dc' gpio. Aborting.\n"); + return -EINVAL; + } + + if (!par->pdev) + return 0; + + if (par->gpio.wr < 0) { + dev_err(par->info->device, "Missing 'wr' gpio. Aborting.\n"); + return -EINVAL; + } + for (i = 0; i < pdata->display.buswidth; i++) { + if (par->gpio.db[i] < 0) { + dev_err(par->info->device, + "Missing 'db%02d' gpio. Aborting.\n", i); + return -EINVAL; + } + } + + return 0; +} + +#ifdef CONFIG_OF +/* returns 0 if the property is not present */ +static u32 fbtft_of_value(struct device_node *node, const char *propname) +{ + int ret; + u32 val = 0; + + ret = of_property_read_u32(node, propname, &val); + if (ret == 0) + pr_info("%s: %s = %u\n", __func__, propname, val); + + return val; +} + +static struct fbtft_platform_data *fbtft_probe_dt(struct device *dev) +{ + struct device_node *node = dev->of_node; + struct fbtft_platform_data *pdata; + + if (!node) { + dev_err(dev, "Missing platform data or DT\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + pdata->display.width = fbtft_of_value(node, "width"); + pdata->display.height = fbtft_of_value(node, "height"); + pdata->display.regwidth = fbtft_of_value(node, "regwidth"); + pdata->display.buswidth = fbtft_of_value(node, "buswidth"); + pdata->display.backlight = fbtft_of_value(node, "backlight"); + pdata->display.bpp = fbtft_of_value(node, "bpp"); + pdata->display.debug = fbtft_of_value(node, "debug"); + pdata->rotate = fbtft_of_value(node, "rotate"); + pdata->bgr = of_property_read_bool(node, "bgr"); + pdata->fps = fbtft_of_value(node, "fps"); + pdata->txbuflen = fbtft_of_value(node, "txbuflen"); + pdata->startbyte = fbtft_of_value(node, "startbyte"); + of_property_read_string(node, "gamma", (const char **)&pdata->gamma); + + if (of_find_property(node, "led-gpios", NULL)) + pdata->display.backlight = 1; + if (of_find_property(node, "init", NULL)) + pdata->display.fbtftops.init_display = fbtft_init_display_dt; + pdata->display.fbtftops.request_gpios = fbtft_request_gpios_dt; + + return pdata; +} +#else +static struct fbtft_platform_data *fbtft_probe_dt(struct device *dev) +{ + dev_err(dev, "Missing platform data\n"); + return ERR_PTR(-EINVAL); +} +#endif + +/** + * fbtft_probe_common() - Generic device probe() helper function + * @display: Display properties + * @sdev: SPI device + * @pdev: Platform device + * + * Allocates, initializes and registers a framebuffer + * + * Either @sdev or @pdev should be NULL + * + * Return: 0 if successful, negative if error + */ +int fbtft_probe_common(struct fbtft_display *display, + struct spi_device *sdev, struct platform_device *pdev) +{ + struct device *dev; + struct fb_info *info; + struct fbtft_par *par; + struct fbtft_platform_data *pdata; + int ret; + + if (sdev) + dev = &sdev->dev; + else + dev = &pdev->dev; + + if (unlikely(display->debug & DEBUG_DRIVER_INIT_FUNCTIONS)) + dev_info(dev, "%s()\n", __func__); + + pdata = dev->platform_data; + if (!pdata) { + pdata = fbtft_probe_dt(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + dev->platform_data = pdata; + } + + info = fbtft_framebuffer_alloc(display, dev); + if (!info) + return -ENOMEM; + + par = info->par; + par->spi = sdev; + par->pdev = pdev; + + if (display->buswidth == 0) { + dev_err(dev, "buswidth is not set\n"); + return -EINVAL; + } + + /* write register functions */ + if (display->regwidth == 8 && display->buswidth == 8) { + par->fbtftops.write_register = fbtft_write_reg8_bus8; + } else + if (display->regwidth == 8 && display->buswidth == 9 && par->spi) { + par->fbtftops.write_register = fbtft_write_reg8_bus9; + } else if (display->regwidth == 16 && display->buswidth == 8) { + par->fbtftops.write_register = fbtft_write_reg16_bus8; + } else if (display->regwidth == 16 && display->buswidth == 16) { + par->fbtftops.write_register = fbtft_write_reg16_bus16; + } else { + dev_warn(dev, + "no default functions for regwidth=%d and buswidth=%d\n", + display->regwidth, display->buswidth); + } + + /* write_vmem() functions */ + if (display->buswidth == 8) + par->fbtftops.write_vmem = fbtft_write_vmem16_bus8; + else if (display->buswidth == 9) + par->fbtftops.write_vmem = fbtft_write_vmem16_bus9; + else if (display->buswidth == 16) + par->fbtftops.write_vmem = fbtft_write_vmem16_bus16; + + /* GPIO write() functions */ + if (par->pdev) { + if (display->buswidth == 8) + par->fbtftops.write = fbtft_write_gpio8_wr; + else if (display->buswidth == 16) + par->fbtftops.write = fbtft_write_gpio16_wr; + } + + /* 9-bit SPI setup */ + if (par->spi && display->buswidth == 9) { + par->spi->bits_per_word = 9; + ret = par->spi->master->setup(par->spi); + if (ret) { + dev_warn(&par->spi->dev, + "9-bit SPI not available, emulating using 8-bit.\n"); + par->spi->bits_per_word = 8; + ret = par->spi->master->setup(par->spi); + if (ret) + goto out_release; + /* allocate buffer with room for dc bits */ + par->extra = devm_kzalloc(par->info->device, + par->txbuf.len + (par->txbuf.len / 8) + 8, + GFP_KERNEL); + if (!par->extra) { + ret = -ENOMEM; + goto out_release; + } + par->fbtftops.write = fbtft_write_spi_emulate_9; + } + } + + if (!par->fbtftops.verify_gpios) + par->fbtftops.verify_gpios = fbtft_verify_gpios; + + /* make sure we still use the driver provided functions */ + fbtft_merge_fbtftops(&par->fbtftops, &display->fbtftops); + + /* use init_sequence if provided */ + if (par->init_sequence) + par->fbtftops.init_display = fbtft_init_display; + + /* use platform_data provided functions above all */ + fbtft_merge_fbtftops(&par->fbtftops, &pdata->display.fbtftops); + + ret = fbtft_register_framebuffer(info); + if (ret < 0) + goto out_release; + + return 0; + +out_release: + fbtft_framebuffer_release(info); + + return ret; +} +EXPORT_SYMBOL(fbtft_probe_common); + +/** + * fbtft_remove_common() - Generic device remove() helper function + * @dev: Device + * @info: Framebuffer + * + * Unregisters and releases the framebuffer + * + * Return: 0 if successful, negative if error + */ +int fbtft_remove_common(struct device *dev, struct fb_info *info) +{ + struct fbtft_par *par; + + if (!info) + return -EINVAL; + par = info->par; + if (par) + fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, par, + "%s()\n", __func__); + fbtft_unregister_framebuffer(info); + fbtft_framebuffer_release(info); + + return 0; +} +EXPORT_SYMBOL(fbtft_remove_common); + +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/fbtft/fbtft-io.c b/drivers/staging/fbtft/fbtft-io.c new file mode 100644 index 0000000..dfa2c46 --- /dev/null +++ b/drivers/staging/fbtft/fbtft-io.c @@ -0,0 +1,409 @@ +#include +#include +#include +#include +#ifdef CONFIG_ARCH_BCM2708 +#include +#endif +#include "fbtft.h" + +int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len) +{ + struct spi_transfer t = { + .tx_buf = buf, + .len = len, + }; + struct spi_message m; + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + if (!par->spi) { + dev_err(par->info->device, + "%s: par->spi is unexpectedly NULL\n", __func__); + return -1; + } + + spi_message_init(&m); + if (par->txbuf.dma && buf == par->txbuf.buf) { + t.tx_dma = par->txbuf.dma; + m.is_dma_mapped = 1; + } + spi_message_add_tail(&t, &m); + return spi_sync(par->spi, &m); +} +EXPORT_SYMBOL(fbtft_write_spi); + +/** + * fbtft_write_spi_emulate_9() - write SPI emulating 9-bit + * @par: Driver data + * @buf: Buffer to write + * @len: Length of buffer (must be divisible by 8) + * + * When 9-bit SPI is not available, this function can be used to emulate that. + * par->extra must hold a transformation buffer used for transfer. + */ +int fbtft_write_spi_emulate_9(struct fbtft_par *par, void *buf, size_t len) +{ + u16 *src = buf; + u8 *dst = par->extra; + size_t size = len / 2; + size_t added = 0; + int bits, i, j; + u64 val, dc, tmp; + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + if (!par->extra) { + dev_err(par->info->device, "%s: error: par->extra is NULL\n", + __func__); + return -EINVAL; + } + if ((len % 8) != 0) { + dev_err(par->info->device, + "%s: error: len=%d must be divisible by 8\n", + __func__, len); + return -EINVAL; + } + + for (i = 0; i < size; i += 8) { + tmp = 0; + bits = 63; + for (j = 0; j < 7; j++) { + dc = (*src & 0x0100) ? 1 : 0; + val = *src & 0x00FF; + tmp |= dc << bits; + bits -= 8; + tmp |= val << bits--; + src++; + } + tmp |= ((*src & 0x0100) ? 1 : 0); + *(u64 *)dst = cpu_to_be64(tmp); + dst += 8; + *dst++ = (u8)(*src++ & 0x00FF); + added++; + } + + return spi_write(par->spi, par->extra, size + added); +} +EXPORT_SYMBOL(fbtft_write_spi_emulate_9); + +int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len) +{ + int ret; + u8 txbuf[32] = { 0, }; + struct spi_transfer t = { + .speed_hz = 2000000, + .rx_buf = buf, + .len = len, + }; + struct spi_message m; + + if (!par->spi) { + dev_err(par->info->device, + "%s: par->spi is unexpectedly NULL\n", __func__); + return -ENODEV; + } + + if (par->startbyte) { + if (len > 32) { + dev_err(par->info->device, + "%s: len=%d can't be larger than 32 when using 'startbyte'\n", + __func__, len); + return -EINVAL; + } + txbuf[0] = par->startbyte | 0x3; + t.tx_buf = txbuf; + fbtft_par_dbg_hex(DEBUG_READ, par, par->info->device, u8, + txbuf, len, "%s(len=%d) txbuf => ", __func__, len); + } + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + ret = spi_sync(par->spi, &m); + fbtft_par_dbg_hex(DEBUG_READ, par, par->info->device, u8, buf, len, + "%s(len=%d) buf <= ", __func__, len); + + return ret; +} +EXPORT_SYMBOL(fbtft_read_spi); + + +#ifdef CONFIG_ARCH_BCM2708 + +/* + * Raspberry Pi + * - writing directly to the registers is 40-50% faster than + * optimized use of gpiolib + */ + +#define GPIOSET(no, ishigh) \ +do { \ + if (ishigh) \ + set |= (1 << (no)); \ + else \ + reset |= (1 << (no)); \ +} while (0) + +int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) +{ + unsigned int set = 0; + unsigned int reset = 0; + u8 data; + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + while (len--) { + data = *(u8 *) buf; + buf++; + + /* Set data */ + GPIOSET(par->gpio.db[0], (data&0x01)); + GPIOSET(par->gpio.db[1], (data&0x02)); + GPIOSET(par->gpio.db[2], (data&0x04)); + GPIOSET(par->gpio.db[3], (data&0x08)); + GPIOSET(par->gpio.db[4], (data&0x10)); + GPIOSET(par->gpio.db[5], (data&0x20)); + GPIOSET(par->gpio.db[6], (data&0x40)); + GPIOSET(par->gpio.db[7], (data&0x80)); + writel(set, __io_address(GPIO_BASE+0x1C)); + writel(reset, __io_address(GPIO_BASE+0x28)); + + /* Pulse /WR low */ + writel((1<gpio.wr), __io_address(GPIO_BASE+0x28)); + writel(0, __io_address(GPIO_BASE+0x28)); /* used as a delay */ + writel((1<gpio.wr), __io_address(GPIO_BASE+0x1C)); + + set = 0; + reset = 0; + } + + return 0; +} +EXPORT_SYMBOL(fbtft_write_gpio8_wr); + +int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) +{ + unsigned int set = 0; + unsigned int reset = 0; + u16 data; + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + while (len) { + len -= 2; + data = *(u16 *) buf; + buf += 2; + + /* Start writing by pulling down /WR */ + gpio_set_value(par->gpio.wr, 0); + + /* Set data */ + GPIOSET(par->gpio.db[0], (data&0x0001)); + GPIOSET(par->gpio.db[1], (data&0x0002)); + GPIOSET(par->gpio.db[2], (data&0x0004)); + GPIOSET(par->gpio.db[3], (data&0x0008)); + GPIOSET(par->gpio.db[4], (data&0x0010)); + GPIOSET(par->gpio.db[5], (data&0x0020)); + GPIOSET(par->gpio.db[6], (data&0x0040)); + GPIOSET(par->gpio.db[7], (data&0x0080)); + + GPIOSET(par->gpio.db[8], (data&0x0100)); + GPIOSET(par->gpio.db[9], (data&0x0200)); + GPIOSET(par->gpio.db[10], (data&0x0400)); + GPIOSET(par->gpio.db[11], (data&0x0800)); + GPIOSET(par->gpio.db[12], (data&0x1000)); + GPIOSET(par->gpio.db[13], (data&0x2000)); + GPIOSET(par->gpio.db[14], (data&0x4000)); + GPIOSET(par->gpio.db[15], (data&0x8000)); + + writel(set, __io_address(GPIO_BASE+0x1C)); + writel(reset, __io_address(GPIO_BASE+0x28)); + + /* Pullup /WR */ + gpio_set_value(par->gpio.wr, 1); + + set = 0; + reset = 0; + } + + return 0; +} +EXPORT_SYMBOL(fbtft_write_gpio16_wr); + +int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, void *buf, size_t len) +{ + unsigned int set = 0; + unsigned int reset = 0; + u16 data; + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + while (len) { + len -= 2; + data = *(u16 *) buf; + buf += 2; + + /* Start writing by pulling down /WR */ + gpio_set_value(par->gpio.wr, 0); + + /* Low byte */ + GPIOSET(par->gpio.db[0], (data&0x0001)); + GPIOSET(par->gpio.db[1], (data&0x0002)); + GPIOSET(par->gpio.db[2], (data&0x0004)); + GPIOSET(par->gpio.db[3], (data&0x0008)); + GPIOSET(par->gpio.db[4], (data&0x0010)); + GPIOSET(par->gpio.db[5], (data&0x0020)); + GPIOSET(par->gpio.db[6], (data&0x0040)); + GPIOSET(par->gpio.db[7], (data&0x0080)); + writel(set, __io_address(GPIO_BASE+0x1C)); + writel(reset, __io_address(GPIO_BASE+0x28)); + + /* Pulse 'latch' high */ + gpio_set_value(par->gpio.latch, 1); + gpio_set_value(par->gpio.latch, 0); + + /* High byte */ + GPIOSET(par->gpio.db[0], (data&0x0100)); + GPIOSET(par->gpio.db[1], (data&0x0200)); + GPIOSET(par->gpio.db[2], (data&0x0400)); + GPIOSET(par->gpio.db[3], (data&0x0800)); + GPIOSET(par->gpio.db[4], (data&0x1000)); + GPIOSET(par->gpio.db[5], (data&0x2000)); + GPIOSET(par->gpio.db[6], (data&0x4000)); + GPIOSET(par->gpio.db[7], (data&0x8000)); + writel(set, __io_address(GPIO_BASE+0x1C)); + writel(reset, __io_address(GPIO_BASE+0x28)); + + /* Pullup /WR */ + gpio_set_value(par->gpio.wr, 1); + + set = 0; + reset = 0; + } + + return 0; +} +EXPORT_SYMBOL(fbtft_write_gpio16_wr_latched); + +#undef GPIOSET + +#else + +/* + * Optimized use of gpiolib is twice as fast as no optimization + * only one driver can use the optimized version at a time + */ +int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) +{ + u8 data; + int i; +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + static u8 prev_data; +#endif + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + while (len--) { + data = *(u8 *) buf; + + /* Start writing by pulling down /WR */ + gpio_set_value(par->gpio.wr, 0); + + /* Set data */ +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + if (data == prev_data) { + gpio_set_value(par->gpio.wr, 0); /* used as delay */ + } else { + for (i = 0; i < 8; i++) { + if ((data & 1) != (prev_data & 1)) + gpio_set_value(par->gpio.db[i], + (data & 1)); + data >>= 1; + prev_data >>= 1; + } + } +#else + for (i = 0; i < 8; i++) { + gpio_set_value(par->gpio.db[i], (data & 1)); + data >>= 1; + } +#endif + + /* Pullup /WR */ + gpio_set_value(par->gpio.wr, 1); + +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + prev_data = *(u8 *) buf; +#endif + buf++; + } + + return 0; +} +EXPORT_SYMBOL(fbtft_write_gpio8_wr); + +int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) +{ + u16 data; + int i; +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + static u16 prev_data; +#endif + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + while (len) { + data = *(u16 *) buf; + + /* Start writing by pulling down /WR */ + gpio_set_value(par->gpio.wr, 0); + + /* Set data */ +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + if (data == prev_data) { + gpio_set_value(par->gpio.wr, 0); /* used as delay */ + } else { + for (i = 0; i < 16; i++) { + if ((data & 1) != (prev_data & 1)) + gpio_set_value(par->gpio.db[i], + (data & 1)); + data >>= 1; + prev_data >>= 1; + } + } +#else + for (i = 0; i < 16; i++) { + gpio_set_value(par->gpio.db[i], (data & 1)); + data >>= 1; + } +#endif + + /* Pullup /WR */ + gpio_set_value(par->gpio.wr, 1); + +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + prev_data = *(u16 *) buf; +#endif + buf += 2; + len -= 2; + } + + return 0; +} +EXPORT_SYMBOL(fbtft_write_gpio16_wr); + +int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, void *buf, size_t len) +{ + dev_err(par->info->device, "%s: function not implemented\n", __func__); + return -1; +} +EXPORT_SYMBOL(fbtft_write_gpio16_wr_latched); + +#endif /* CONFIG_ARCH_BCM2708 */ diff --git a/drivers/staging/fbtft/fbtft-sysfs.c b/drivers/staging/fbtft/fbtft-sysfs.c new file mode 100644 index 0000000..45f8de3 --- /dev/null +++ b/drivers/staging/fbtft/fbtft-sysfs.c @@ -0,0 +1,222 @@ +#include "fbtft.h" + + +static int get_next_ulong(char **str_p, unsigned long *val, char *sep, int base) +{ + char *p_val; + int ret; + + if (!str_p || !(*str_p)) + return -EINVAL; + + p_val = strsep(str_p, sep); + + if (!p_val) + return -EINVAL; + + ret = kstrtoul(p_val, base, val); + if (ret) + return -EINVAL; + + return 0; +} + +int fbtft_gamma_parse_str(struct fbtft_par *par, unsigned long *curves, + const char *str, int size) +{ + char *str_p, *curve_p = NULL; + char *tmp; + unsigned long val = 0; + int ret = 0; + int curve_counter, value_counter; + + fbtft_par_dbg(DEBUG_SYSFS, par, "%s() str=\n", __func__); + + if (!str || !curves) + return -EINVAL; + + fbtft_par_dbg(DEBUG_SYSFS, par, "%s\n", str); + + tmp = kmalloc(size+1, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + memcpy(tmp, str, size+1); + + /* replace optional separators */ + str_p = tmp; + while (*str_p) { + if (*str_p == ',') + *str_p = ' '; + if (*str_p == ';') + *str_p = '\n'; + str_p++; + } + + str_p = strim(tmp); + + curve_counter = 0; + while (str_p) { + if (curve_counter == par->gamma.num_curves) { + dev_err(par->info->device, "Gamma: Too many curves\n"); + ret = -EINVAL; + goto out; + } + curve_p = strsep(&str_p, "\n"); + value_counter = 0; + while (curve_p) { + if (value_counter == par->gamma.num_values) { + dev_err(par->info->device, + "Gamma: Too many values\n"); + ret = -EINVAL; + goto out; + } + ret = get_next_ulong(&curve_p, &val, " ", 16); + if (ret) + goto out; + curves[curve_counter * par->gamma.num_values + value_counter] = val; + value_counter++; + } + if (value_counter != par->gamma.num_values) { + dev_err(par->info->device, "Gamma: Too few values\n"); + ret = -EINVAL; + goto out; + } + curve_counter++; + } + if (curve_counter != par->gamma.num_curves) { + dev_err(par->info->device, "Gamma: Too few curves\n"); + ret = -EINVAL; + goto out; + } + +out: + kfree(tmp); + return ret; +} + +static ssize_t +sprintf_gamma(struct fbtft_par *par, unsigned long *curves, char *buf) +{ + ssize_t len = 0; + unsigned int i, j; + + mutex_lock(&par->gamma.lock); + for (i = 0; i < par->gamma.num_curves; i++) { + for (j = 0; j < par->gamma.num_values; j++) + len += scnprintf(&buf[len], PAGE_SIZE, + "%04lx ", curves[i*par->gamma.num_values + j]); + buf[len-1] = '\n'; + } + mutex_unlock(&par->gamma.lock); + + return len; +} + +static ssize_t store_gamma_curve(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *fb_info = dev_get_drvdata(device); + struct fbtft_par *par = fb_info->par; + unsigned long tmp_curves[FBTFT_GAMMA_MAX_VALUES_TOTAL]; + int ret; + + ret = fbtft_gamma_parse_str(par, tmp_curves, buf, count); + if (ret) + return ret; + + ret = par->fbtftops.set_gamma(par, tmp_curves); + if (ret) + return ret; + + mutex_lock(&par->gamma.lock); + memcpy(par->gamma.curves, tmp_curves, + par->gamma.num_curves * par->gamma.num_values * sizeof(tmp_curves[0])); + mutex_unlock(&par->gamma.lock); + + return count; +} + +static ssize_t show_gamma_curve(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fb_info = dev_get_drvdata(device); + struct fbtft_par *par = fb_info->par; + + return sprintf_gamma(par, par->gamma.curves, buf); +} + +static struct device_attribute gamma_device_attrs[] = { + __ATTR(gamma, 0660, show_gamma_curve, store_gamma_curve), +}; + + +void fbtft_expand_debug_value(unsigned long *debug) +{ + switch (*debug & 0b111) { + case 1: + *debug |= DEBUG_LEVEL_1; + break; + case 2: + *debug |= DEBUG_LEVEL_2; + break; + case 3: + *debug |= DEBUG_LEVEL_3; + break; + case 4: + *debug |= DEBUG_LEVEL_4; + break; + case 5: + *debug |= DEBUG_LEVEL_5; + break; + case 6: + *debug |= DEBUG_LEVEL_6; + break; + case 7: + *debug = 0xFFFFFFFF; + break; + } +} + +static ssize_t store_debug(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fb_info *fb_info = dev_get_drvdata(device); + struct fbtft_par *par = fb_info->par; + int ret; + + ret = kstrtoul(buf, 10, &par->debug); + if (ret) + return ret; + fbtft_expand_debug_value(&par->debug); + + return count; +} + +static ssize_t show_debug(struct device *device, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fb_info = dev_get_drvdata(device); + struct fbtft_par *par = fb_info->par; + + return snprintf(buf, PAGE_SIZE, "%lu\n", par->debug); +} + +static struct device_attribute debug_device_attr = \ + __ATTR(debug, 0660, show_debug, store_debug); + + +void fbtft_sysfs_init(struct fbtft_par *par) +{ + device_create_file(par->info->dev, &debug_device_attr); + if (par->gamma.curves && par->fbtftops.set_gamma) + device_create_file(par->info->dev, &gamma_device_attrs[0]); +} + +void fbtft_sysfs_exit(struct fbtft_par *par) +{ + device_remove_file(par->info->dev, &debug_device_attr); + if (par->gamma.curves && par->fbtftops.set_gamma) + device_remove_file(par->info->dev, &gamma_device_attrs[0]); +} diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h new file mode 100644 index 0000000..0dbf3f9 --- /dev/null +++ b/drivers/staging/fbtft/fbtft.h @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __LINUX_FBTFT_H +#define __LINUX_FBTFT_H + +#include +#include +#include +#include + + +#define FBTFT_NOP 0x00 +#define FBTFT_SWRESET 0x01 +#define FBTFT_RDDID 0x04 +#define FBTFT_RDDST 0x09 +#define FBTFT_CASET 0x2A +#define FBTFT_RASET 0x2B +#define FBTFT_RAMWR 0x2C + +#define FBTFT_ONBOARD_BACKLIGHT 2 + +#define FBTFT_GPIO_NO_MATCH 0xFFFF +#define FBTFT_GPIO_NAME_SIZE 32 +#define FBTFT_MAX_INIT_SEQUENCE 512 +#define FBTFT_GAMMA_MAX_VALUES_TOTAL 128 + +#define FBTFT_OF_INIT_CMD BIT(24) +#define FBTFT_OF_INIT_DELAY BIT(25) + +/** + * struct fbtft_gpio - Structure that holds one pinname to gpio mapping + * @name: pinname (reset, dc, etc.) + * @gpio: GPIO number + * + */ +struct fbtft_gpio { + char name[FBTFT_GPIO_NAME_SIZE]; + unsigned gpio; +}; + +struct fbtft_par; + +/** + * struct fbtft_ops - FBTFT operations structure + * @write: Writes to interface bus + * @read: Reads from interface bus + * @write_vmem: Writes video memory to display + * @write_reg: Writes to controller register + * @set_addr_win: Set the GRAM update window + * @reset: Reset the LCD controller + * @mkdirty: Marks display lines for update + * @update_display: Updates the display + * @init_display: Initializes the display + * @blank: Blank the display (optional) + * @request_gpios_match: Do pinname to gpio matching + * @request_gpios: Request gpios from the kernel + * @free_gpios: Free previously requested gpios + * @verify_gpios: Verify that necessary gpios is present (optional) + * @register_backlight: Used to register backlight device (optional) + * @unregister_backlight: Unregister backlight device (optional) + * @set_var: Configure LCD with values from variables like @rotate and @bgr + * (optional) + * @set_gamma: Set Gamma curve (optional) + * + * Most of these operations have default functions assigned to them in + * fbtft_framebuffer_alloc() + */ +struct fbtft_ops { + int (*write)(struct fbtft_par *par, void *buf, size_t len); + int (*read)(struct fbtft_par *par, void *buf, size_t len); + int (*write_vmem)(struct fbtft_par *par, size_t offset, size_t len); + void (*write_register)(struct fbtft_par *par, int len, ...); + + void (*set_addr_win)(struct fbtft_par *par, + int xs, int ys, int xe, int ye); + void (*reset)(struct fbtft_par *par); + void (*mkdirty)(struct fb_info *info, int from, int to); + void (*update_display)(struct fbtft_par *par, + unsigned start_line, unsigned end_line); + int (*init_display)(struct fbtft_par *par); + int (*blank)(struct fbtft_par *par, bool on); + + unsigned long (*request_gpios_match)(struct fbtft_par *par, + const struct fbtft_gpio *gpio); + int (*request_gpios)(struct fbtft_par *par); + int (*verify_gpios)(struct fbtft_par *par); + + void (*register_backlight)(struct fbtft_par *par); + void (*unregister_backlight)(struct fbtft_par *par); + + int (*set_var)(struct fbtft_par *par); + int (*set_gamma)(struct fbtft_par *par, unsigned long *curves); +}; + +/** + * struct fbtft_display - Describes the display properties + * @width: Width of display in pixels + * @height: Height of display in pixels + * @regwidth: LCD Controller Register width in bits + * @buswidth: Display interface bus width in bits + * @backlight: Backlight type. + * @fbtftops: FBTFT operations provided by driver or device (platform_data) + * @bpp: Bits per pixel + * @fps: Frames per second + * @txbuflen: Size of transmit buffer + * @init_sequence: Pointer to LCD initialization array + * @gamma: String representation of Gamma curve(s) + * @gamma_num: Number of Gamma curves + * @gamma_len: Number of values per Gamma curve + * @debug: Initial debug value + * + * This structure is not stored by FBTFT except for init_sequence. + */ +struct fbtft_display { + unsigned width; + unsigned height; + unsigned regwidth; + unsigned buswidth; + unsigned backlight; + struct fbtft_ops fbtftops; + unsigned bpp; + unsigned fps; + int txbuflen; + int *init_sequence; + char *gamma; + int gamma_num; + int gamma_len; + unsigned long debug; +}; + +/** + * struct fbtft_platform_data - Passes display specific data to the driver + * @display: Display properties + * @gpios: Pointer to an array of piname to gpio mappings + * @rotate: Display rotation angle + * @bgr: LCD Controller BGR bit + * @fps: Frames per second (this will go away, use @fps in @fbtft_display) + * @txbuflen: Size of transmit buffer + * @startbyte: When set, enables use of Startbyte in transfers + * @gamma: String representation of Gamma curve(s) + * @extra: A way to pass extra info + */ +struct fbtft_platform_data { + struct fbtft_display display; + const struct fbtft_gpio *gpios; + unsigned rotate; + bool bgr; + unsigned fps; + int txbuflen; + u8 startbyte; + char *gamma; + void *extra; +}; + +/** + * struct fbtft_par - Main FBTFT data structure + * + * This structure holds all relevant data to operate the display + * + * See sourcefile for documentation since nested structs is not + * supported by kernel-doc. + * + */ +/* @spi: Set if it is a SPI device + * @pdev: Set if it is a platform device + * @info: Pointer to framebuffer fb_info structure + * @pdata: Pointer to platform data + * @ssbuf: Not used + * @pseudo_palette: Used by fb_set_colreg() + * @txbuf.buf: Transmit buffer + * @txbuf.len: Transmit buffer length + * @buf: Small buffer used when writing init data over SPI + * @startbyte: Used by some controllers when in SPI mode. + * Format: 6 bit Device id + RS bit + RW bit + * @fbtftops: FBTFT operations provided by driver or device (platform_data) + * @dirty_lock: Protects dirty_lines_start and dirty_lines_end + * @dirty_lines_start: Where to begin updating display + * @dirty_lines_end: Where to end updating display + * @gpio.reset: GPIO used to reset display + * @gpio.dc: Data/Command signal, also known as RS + * @gpio.rd: Read latching signal + * @gpio.wr: Write latching signal + * @gpio.latch: Bus latch signal, eg. 16->8 bit bus latch + * @gpio.cs: LCD Chip Select with parallel interface bus + * @gpio.db[16]: Parallel databus + * @gpio.led[16]: Led control signals + * @gpio.aux[16]: Auxillary signals, not used by core + * @init_sequence: Pointer to LCD initialization array + * @gamma.lock: Mutex for Gamma curve locking + * @gamma.curves: Pointer to Gamma curve array + * @gamma.num_values: Number of values per Gamma curve + * @gamma.num_curves: Number of Gamma curves + * @debug: Pointer to debug value + * @current_debug: + * @first_update_done: Used to only time the first display update + * @update_time: Used to calculate 'fps' in debug output + * @bgr: BGR mode/\n + * @extra: Extra info needed by driver + */ +struct fbtft_par { + struct spi_device *spi; + struct platform_device *pdev; + struct fb_info *info; + struct fbtft_platform_data *pdata; + u16 *ssbuf; + u32 pseudo_palette[16]; + struct { + void *buf; + dma_addr_t dma; + size_t len; + } txbuf; + u8 *buf; + u8 startbyte; + struct fbtft_ops fbtftops; + spinlock_t dirty_lock; + unsigned dirty_lines_start; + unsigned dirty_lines_end; + struct { + int reset; + int dc; + int rd; + int wr; + int latch; + int cs; + int db[16]; + int led[16]; + int aux[16]; + } gpio; + int *init_sequence; + struct { + struct mutex lock; + unsigned long *curves; + int num_values; + int num_curves; + } gamma; + unsigned long debug; + bool first_update_done; + struct timespec update_time; + bool bgr; + void *extra; +}; + +#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int)) + +#define write_reg(par, ...) \ +do { \ + par->fbtftops.write_register(par, NUMARGS(__VA_ARGS__), __VA_ARGS__); \ +} while (0) + +/* fbtft-core.c */ +extern void fbtft_dbg_hex(const struct device *dev, + int groupsize, void *buf, size_t len, const char *fmt, ...); +extern struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display, + struct device *dev); +extern void fbtft_framebuffer_release(struct fb_info *info); +extern int fbtft_register_framebuffer(struct fb_info *fb_info); +extern int fbtft_unregister_framebuffer(struct fb_info *fb_info); +extern void fbtft_register_backlight(struct fbtft_par *par); +extern void fbtft_unregister_backlight(struct fbtft_par *par); +extern int fbtft_init_display(struct fbtft_par *par); +extern int fbtft_probe_common(struct fbtft_display *display, + struct spi_device *sdev, struct platform_device *pdev); +extern int fbtft_remove_common(struct device *dev, struct fb_info *info); + +/* fbtft-io.c */ +extern int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len); +extern int fbtft_write_spi_emulate_9(struct fbtft_par *par, + void *buf, size_t len); +extern int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len); +extern int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len); +extern int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len); +extern int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, + void *buf, size_t len); + +/* fbtft-bus.c */ +extern int fbtft_write_vmem8_bus8(struct fbtft_par *par, size_t offset, size_t len); +extern int fbtft_write_vmem16_bus16(struct fbtft_par *par, size_t offset, size_t len); +extern int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len); +extern int fbtft_write_vmem16_bus9(struct fbtft_par *par, size_t offset, size_t len); +extern void fbtft_write_reg8_bus8(struct fbtft_par *par, int len, ...); +extern void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...); +extern void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...); +extern void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...); + + +#define FBTFT_REGISTER_DRIVER(_name, _compatible, _display) \ + \ +static int fbtft_driver_probe_spi(struct spi_device *spi) \ +{ \ + return fbtft_probe_common(_display, spi, NULL); \ +} \ + \ +static int fbtft_driver_remove_spi(struct spi_device *spi) \ +{ \ + struct fb_info *info = spi_get_drvdata(spi); \ + \ + return fbtft_remove_common(&spi->dev, info); \ +} \ + \ +static int fbtft_driver_probe_pdev(struct platform_device *pdev) \ +{ \ + return fbtft_probe_common(_display, NULL, pdev); \ +} \ + \ +static int fbtft_driver_remove_pdev(struct platform_device *pdev) \ +{ \ + struct fb_info *info = platform_get_drvdata(pdev); \ + \ + return fbtft_remove_common(&pdev->dev, info); \ +} \ + \ +static const struct of_device_id dt_ids[] = { \ + { .compatible = _compatible }, \ + {}, \ +}; \ + \ +MODULE_DEVICE_TABLE(of, dt_ids); \ + \ + \ +static struct spi_driver fbtft_driver_spi_driver = { \ + .driver = { \ + .name = _name, \ + .owner = THIS_MODULE, \ + .of_match_table = of_match_ptr(dt_ids), \ + }, \ + .probe = fbtft_driver_probe_spi, \ + .remove = fbtft_driver_remove_spi, \ +}; \ + \ +static struct platform_driver fbtft_driver_platform_driver = { \ + .driver = { \ + .name = _name, \ + .owner = THIS_MODULE, \ + .of_match_table = of_match_ptr(dt_ids), \ + }, \ + .probe = fbtft_driver_probe_pdev, \ + .remove = fbtft_driver_remove_pdev, \ +}; \ + \ +static int __init fbtft_driver_module_init(void) \ +{ \ + int ret; \ + \ + ret = spi_register_driver(&fbtft_driver_spi_driver); \ + if (ret < 0) \ + return ret; \ + return platform_driver_register(&fbtft_driver_platform_driver); \ +} \ + \ +static void __exit fbtft_driver_module_exit(void) \ +{ \ + spi_unregister_driver(&fbtft_driver_spi_driver); \ + platform_driver_unregister(&fbtft_driver_platform_driver); \ +} \ + \ +module_init(fbtft_driver_module_init); \ +module_exit(fbtft_driver_module_exit); + + +/* Debug macros */ + +/* shorthand debug levels */ +#define DEBUG_LEVEL_1 DEBUG_REQUEST_GPIOS +#define DEBUG_LEVEL_2 (DEBUG_LEVEL_1 | DEBUG_DRIVER_INIT_FUNCTIONS | DEBUG_TIME_FIRST_UPDATE) +#define DEBUG_LEVEL_3 (DEBUG_LEVEL_2 | DEBUG_RESET | DEBUG_INIT_DISPLAY | DEBUG_BLANK | DEBUG_REQUEST_GPIOS | DEBUG_FREE_GPIOS | DEBUG_VERIFY_GPIOS | DEBUG_BACKLIGHT | DEBUG_SYSFS) +#define DEBUG_LEVEL_4 (DEBUG_LEVEL_2 | DEBUG_FB_READ | DEBUG_FB_WRITE | DEBUG_FB_FILLRECT | DEBUG_FB_COPYAREA | DEBUG_FB_IMAGEBLIT | DEBUG_FB_BLANK) +#define DEBUG_LEVEL_5 (DEBUG_LEVEL_3 | DEBUG_UPDATE_DISPLAY) +#define DEBUG_LEVEL_6 (DEBUG_LEVEL_4 | DEBUG_LEVEL_5) +#define DEBUG_LEVEL_7 0xFFFFFFFF + +#define DEBUG_DRIVER_INIT_FUNCTIONS (1<<3) +#define DEBUG_TIME_FIRST_UPDATE (1<<4) +#define DEBUG_TIME_EACH_UPDATE (1<<5) +#define DEBUG_DEFERRED_IO (1<<6) +#define DEBUG_FBTFT_INIT_FUNCTIONS (1<<7) + +/* fbops */ +#define DEBUG_FB_READ (1<<8) +#define DEBUG_FB_WRITE (1<<9) +#define DEBUG_FB_FILLRECT (1<<10) +#define DEBUG_FB_COPYAREA (1<<11) +#define DEBUG_FB_IMAGEBLIT (1<<12) +#define DEBUG_FB_SETCOLREG (1<<13) +#define DEBUG_FB_BLANK (1<<14) + +#define DEBUG_SYSFS (1<<16) + +/* fbtftops */ +#define DEBUG_BACKLIGHT (1<<17) +#define DEBUG_READ (1<<18) +#define DEBUG_WRITE (1<<19) +#define DEBUG_WRITE_VMEM (1<<20) +#define DEBUG_WRITE_REGISTER (1<<21) +#define DEBUG_SET_ADDR_WIN (1<<22) +#define DEBUG_RESET (1<<23) +#define DEBUG_MKDIRTY (1<<24) +#define DEBUG_UPDATE_DISPLAY (1<<25) +#define DEBUG_INIT_DISPLAY (1<<26) +#define DEBUG_BLANK (1<<27) +#define DEBUG_REQUEST_GPIOS (1<<28) +#define DEBUG_FREE_GPIOS (1<<29) +#define DEBUG_REQUEST_GPIOS_MATCH (1<<30) +#define DEBUG_VERIFY_GPIOS (1<<31) + + +#define fbtft_init_dbg(dev, format, arg...) \ +do { \ + if (unlikely((dev)->platform_data && \ + (((struct fbtft_platform_data *)(dev)->platform_data)->display.debug & DEBUG_DRIVER_INIT_FUNCTIONS))) \ + dev_info(dev, format, ##arg); \ +} while (0) + +#define fbtft_par_dbg(level, par, format, arg...) \ +do { \ + if (unlikely(par->debug & level)) \ + dev_info(par->info->device, format, ##arg); \ +} while (0) + +#define fbtft_dev_dbg(level, par, dev, format, arg...) \ +do { \ + if (unlikely(par->debug & level)) \ + dev_info(dev, format, ##arg); \ +} while (0) + +#define fbtft_par_dbg_hex(level, par, dev, type, buf, num, format, arg...) \ +do { \ + if (unlikely(par->debug & level)) \ + fbtft_dbg_hex(dev, sizeof(type), buf, num * sizeof(type), format, ##arg); \ +} while (0) + +#endif /* __LINUX_FBTFT_H */ -- cgit v0.10.2 From b2ebd4be6fa1d2329b63531b044f9e25474981cb Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:10 +0100 Subject: staging: fbtft: add fb_agm1264k-fl driver This commit adds the fb_agm1264k-fl driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 3d6598b..d552af6 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -7,3 +7,9 @@ menuconfig FB_TFT select FB_SYS_FOPS select FB_DEFERRED_IO select FB_BACKLIGHT + +config FB_TFT_AGM1264K_FL + tristate "FB driver for the AGM1264K-FL LCD display" + depends on FB_TFT + help + Framebuffer support for the AGM1264K-FL LCD display (two Samsung KS0108 compatable chips) diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 9132dde..eb13cc5 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -1,3 +1,6 @@ # Core module obj-$(CONFIG_FB_TFT) += fbtft.o fbtft-y += fbtft-core.o fbtft-sysfs.o fbtft-bus.o fbtft-io.o + +# drivers +obj-$(CONFIG_FB_TFT_AGM1264K_FL) += fb_agm1264k-fl.o diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c new file mode 100644 index 0000000..7fe4fa0 --- /dev/null +++ b/drivers/staging/fbtft/fb_agm1264k-fl.c @@ -0,0 +1,462 @@ +/* + * FB driver for Two KS0108 LCD controllers in AGM1264K-FL display + * + * Copyright (C) 2014 ololoshka2871 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +#include "fbtft.h" + +/* Uncomment text line to use negative image on display */ +/*#define NEGATIVE*/ + +#define WHITE 0xff +#define BLACK 0 + +#define DRVNAME "fb_agm1264k-fl" +#define WIDTH 64 +#define HEIGHT 64 +#define TOTALWIDTH (WIDTH * 2) /* because 2 x ks0108 in one display */ +#define FPS 20 + +#define EPIN gpio.wr +#define RS gpio.dc +#define RW gpio.aux[2] +#define CS0 gpio.aux[0] +#define CS1 gpio.aux[1] + + +/* diffusing error (“Floyd-Steinberg”) */ +#define DIFFUSING_MATRIX_WIDTH 2 +#define DIFFUSING_MATRIX_HEIGHT 2 + +static const signed char +diffusing_matrix[DIFFUSING_MATRIX_WIDTH][DIFFUSING_MATRIX_HEIGHT] = { + {-1, 3}, + {3, 2}, +}; + +static const unsigned char gamma_correction_table[] = { +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, +6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, +13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, +22, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, +33, 33, 34, 35, 35, 36, 37, 38, 39, 39, 40, 41, 42, 43, 43, 44, 45, +46, 47, 48, 49, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, +62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 81, +82, 83, 84, 85, 87, 88, 89, 90, 91, 93, 94, 95, 97, 98, 99, 100, 102, +103, 105, 106, 107, 109, 110, 111, 113, 114, 116, 117, 119, 120, 121, +123, 124, 126, 127, 129, 130, 132, 133, 135, 137, 138, 140, 141, 143, +145, 146, 148, 149, 151, 153, 154, 156, 158, 159, 161, 163, 165, 166, +168, 170, 172, 173, 175, 177, 179, 181, 182, 184, 186, 188, 190, 192, +194, 196, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, +221, 223, 225, 227, 229, 231, 234, 236, 238, 240, 242, 244, 246, 248, +251, 253, 255 +}; + +static int init_display(struct fbtft_par *par) +{ + u8 i; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + for (i = 0; i < 2; ++i) { + write_reg(par, i, 0x3f); /* display on */ + write_reg(par, i, 0x40); /* set x to 0 */ + write_reg(par, i, 0xb0); /* set page to 0 */ + write_reg(par, i, 0xc0); /* set start line to 0 */ + } + + return 0; +} + +void reset(struct fbtft_par *par) +{ + if (par->gpio.reset == -1) + return; + + fbtft_dev_dbg(DEBUG_RESET, par, par->info->device, "%s()\n", __func__); + + gpio_set_value(par->gpio.reset, 0); + udelay(20); + gpio_set_value(par->gpio.reset, 1); + mdelay(120); +} + +/* Check if all necessary GPIOS defined */ +static int verify_gpios(struct fbtft_par *par) +{ + int i; + + fbtft_dev_dbg(DEBUG_VERIFY_GPIOS, par, par->info->device, + "%s()\n", __func__); + + if (par->EPIN < 0) { + dev_err(par->info->device, + "Missing info about 'wr' (aka E) gpio. Aborting.\n"); + return -EINVAL; + } + for (i = 0; i < 8; ++i) { + if (par->gpio.db[i] < 0) { + dev_err(par->info->device, + "Missing info about 'db[%i]' gpio. Aborting.\n", + i); + return -EINVAL; + } + } + if (par->CS0 < 0) { + dev_err(par->info->device, + "Missing info about 'cs0' gpio. Aborting.\n"); + return -EINVAL; + } + if (par->CS1 < 0) { + dev_err(par->info->device, + "Missing info about 'cs1' gpio. Aborting.\n"); + return -EINVAL; + } + if (par->RW < 0) { + dev_err(par->info->device, + "Missing info about 'rw' gpio. Aborting.\n"); + return -EINVAL; + } + + return 0; +} + +static unsigned long +request_gpios_match(struct fbtft_par *par, const struct fbtft_gpio *gpio) +{ + fbtft_dev_dbg(DEBUG_REQUEST_GPIOS_MATCH, par, par->info->device, + "%s('%s')\n", __func__, gpio->name); + + if (strcasecmp(gpio->name, "wr") == 0) { + /* left ks0108 E pin */ + par->EPIN = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } else if (strcasecmp(gpio->name, "cs0") == 0) { + /* left ks0108 controller pin */ + par->CS0 = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } else if (strcasecmp(gpio->name, "cs1") == 0) { + /* right ks0108 controller pin */ + par->CS1 = gpio->gpio; + return GPIOF_OUT_INIT_HIGH; + } + + /* if write (rw = 0) e(1->0) perform write */ + /* if read (rw = 1) e(0->1) set data on D0-7*/ + else if (strcasecmp(gpio->name, "rw") == 0) { + par->RW = gpio->gpio; + return GPIOF_OUT_INIT_LOW; + } + + return FBTFT_GPIO_NO_MATCH; +} + +/* This function oses to enter commands + * first byte - destination controller 0 or 1 + * folowing - commands + */ +static void write_reg8_bus8(struct fbtft_par *par, int len, ...) +{ + va_list args; + int i, ret; + u8 *buf = (u8 *)par->buf; + + if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { + va_start(args, len); + for (i = 0; i < len; i++) + buf[i] = (u8)va_arg(args, unsigned int); + + va_end(args); + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, + par->info->device, u8, buf, len, "%s: ", __func__); + } + + va_start(args, len); + + *buf = (u8)va_arg(args, unsigned int); + + if (*buf > 1) { + va_end(args); + dev_err(par->info->device, "%s: Incorrect chip sellect request (%d)\n", + __func__, *buf); + return; + } + + /* select chip */ + if (*buf) { + /* cs1 */ + gpio_set_value(par->CS0, 1); + gpio_set_value(par->CS1, 0); + } else { + /* cs0 */ + gpio_set_value(par->CS0, 0); + gpio_set_value(par->CS1, 1); + } + + gpio_set_value(par->RS, 0); /* RS->0 (command mode) */ + len--; + + if (len) { + i = len; + while (i--) + *buf++ = (u8)va_arg(args, unsigned int); + ret = par->fbtftops.write(par, par->buf, len * (sizeof(u8))); + if (ret < 0) { + va_end(args); + dev_err(par->info->device, "%s: write() failed and returned %d\n", + __func__, ret); + return; + } + } + + va_end(args); +} + +static struct +{ + int xs, ys_page, xe, ye_page; +} addr_win; + +/* save display writing zone */ +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + addr_win.xs = xs; + addr_win.ys_page = ys / 8; + addr_win.xe = xe; + addr_win.ye_page = ye / 8; + + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys_page=%d, xe=%d, ye_page=%d)\n", __func__, + addr_win.xs, addr_win.ys_page, addr_win.xe, addr_win.ye_page); +} + +static void +construct_line_bitmap(struct fbtft_par *par, u8 *dest, signed short *src, + int xs, int xe, int y) +{ + int x, i; + + for (x = xs; x < xe; ++x) { + u8 res = 0; + + for (i = 0; i < 8; i++) + if (src[(y * 8 + i) * par->info->var.xres + x]) + res |= 1 << i; +#ifdef NEGATIVE + *dest++ = res; +#else + *dest++ = ~res; +#endif + } +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16 = (u16 *)par->info->screen_base; + u8 *buf = par->txbuf.buf; + int x, y; + int ret = 0; + + /* buffer to convert RGB565 -> grayscale16 -> Ditherd image 1bpp */ + signed short *convert_buf = kmalloc(par->info->var.xres * + par->info->var.yres * sizeof(signed short), GFP_NOIO); + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + /* converting to grayscale16 */ + for (x = 0; x < par->info->var.xres; ++x) + for (y = 0; y < par->info->var.yres; ++y) { + u16 pixel = vmem16[y * par->info->var.xres + x]; + u16 b = pixel & 0x1f; + u16 g = (pixel & (0x3f << 5)) >> 5; + u16 r = (pixel & (0x1f << (5 + 6))) >> (5 + 6); + + pixel = (299 * r + 587 * g + 114 * b) / 200; + if (pixel > 255) + pixel = 255; + + /* gamma-correction by table */ + convert_buf[y * par->info->var.xres + x] = + (signed short)gamma_correction_table[pixel]; + } + + /* Image Dithering */ + for (x = 0; x < par->info->var.xres; ++x) + for (y = 0; y < par->info->var.yres; ++y) { + signed short pixel = + convert_buf[y * par->info->var.xres + x]; + signed short error_b = pixel - BLACK; + signed short error_w = pixel - WHITE; + signed short error; + u16 i, j; + + /* what color close? */ + if (abs(error_b) >= abs(error_w)) { + /* white */ + error = error_w; + pixel = 0xff; + } else { + /* black */ + error = error_b; + pixel = 0; + } + + error /= 8; + + /* diffusion matrix row */ + for (i = 0; i < DIFFUSING_MATRIX_WIDTH; ++i) + /* diffusion matrix column */ + for (j = 0; j < DIFFUSING_MATRIX_HEIGHT; ++j) { + signed short *write_pos; + signed char coeff; + + /* skip pixels out of zone */ + if (x + i < 0 || + x + i >= par->info->var.xres + || y + j >= par->info->var.yres) + continue; + write_pos = &convert_buf[ + (y + j) * par->info->var.xres + + x + i]; + coeff = diffusing_matrix[i][j]; + if (coeff == -1) + /* pixel itself */ + *write_pos = pixel; + else { + signed short p = *write_pos + + error * coeff; + + if (p > WHITE) + p = WHITE; + if (p < BLACK) + p = BLACK; + *write_pos = p; + } + } + } + + /* 1 string = 2 pages */ + for (y = addr_win.ys_page; y <= addr_win.ye_page; ++y) { + /* left half of display */ + if (addr_win.xs < par->info->var.xres / 2) { + construct_line_bitmap(par, buf, convert_buf, + addr_win.xs, par->info->var.xres / 2, y); + + len = par->info->var.xres / 2 - addr_win.xs; + + /* select left side (sc0) + * set addr + */ + write_reg(par, 0x00, (1 << 6) | (u8)addr_win.xs); + write_reg(par, 0x00, (0x17 << 3) | (u8)y); + + /* write bitmap */ + gpio_set_value(par->RS, 1); /* RS->1 (data mode) */ + ret = par->fbtftops.write(par, buf, len); + if (ret < 0) + dev_err(par->info->device, + "%s: write failed and returned: %d\n", + __func__, ret); + } + /* right half of display */ + if (addr_win.xe >= par->info->var.xres / 2) { + construct_line_bitmap(par, buf, + convert_buf, par->info->var.xres / 2, + addr_win.xe + 1, y); + + len = addr_win.xe + 1 - par->info->var.xres / 2; + + /* select right side (sc1) + * set addr + */ + write_reg(par, 0x01, (1 << 6)); + write_reg(par, 0x01, (0x17 << 3) | (u8)y); + + /* write bitmap */ + gpio_set_value(par->RS, 1); /* RS->1 (data mode) */ + par->fbtftops.write(par, buf, len); + if (ret < 0) + dev_err(par->info->device, + "%s: write failed and returned: %d\n", + __func__, ret); + } + } + kfree(convert_buf); + + gpio_set_value(par->CS0, 1); + gpio_set_value(par->CS1, 1); + + return ret; +} + +static int write(struct fbtft_par *par, void *buf, size_t len) +{ + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + gpio_set_value(par->RW, 0); /* set write mode */ + + + while (len--) { + u8 i, data; + + data = *(u8 *) buf++; + + /* set data bus */ + for (i = 0; i < 8; ++i) + gpio_set_value(par->gpio.db[i], data & (1 << i)); + /* set E */ + gpio_set_value(par->EPIN, 1); + udelay(5); + /* unset E - write */ + gpio_set_value(par->EPIN, 0); + udelay(1); + } + + return 0; +} + +static struct fbtft_display display = { + .regwidth = 8, + .width = TOTALWIDTH, + .height = HEIGHT, + .fps = FPS, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .verify_gpios = verify_gpios, + .request_gpios_match = request_gpios_match, + .reset = reset, + .write = write, + .write_register = write_reg8_bus8, + .write_vmem = write_vmem, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "displaytronic,fb_agm1264k-fl", &display); + +MODULE_ALIAS("platform:" DRVNAME); + +MODULE_DESCRIPTION("Two KS0108 LCD controllers in AGM1264K-FL display"); +MODULE_AUTHOR("ololoshka2871"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 959d049f009b112baa9e772b10d10e49e0288a28 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:11 +0100 Subject: staging: fbtft: add fb_bd663474 driver This commit adds the fb_bd663474 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index d552af6..400492a 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -13,3 +13,9 @@ config FB_TFT_AGM1264K_FL depends on FB_TFT help Framebuffer support for the AGM1264K-FL LCD display (two Samsung KS0108 compatable chips) + +config FB_TFT_BD663474 + tristate "FB driver for the BD663474 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for BD663474 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index eb13cc5..9f80a6e 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -4,3 +4,4 @@ fbtft-y += fbtft-core.o fbtft-sysfs.o fbtft-bus.o fbtft # drivers obj-$(CONFIG_FB_TFT_AGM1264K_FL) += fb_agm1264k-fl.o +obj-$(CONFIG_FB_TFT_BD663474) += fb_bd663474.o diff --git a/drivers/staging/fbtft/fb_bd663474.c b/drivers/staging/fbtft/fb_bd663474.c new file mode 100644 index 0000000..7e00c60 --- /dev/null +++ b/drivers/staging/fbtft/fb_bd663474.c @@ -0,0 +1,193 @@ +/* + * FB driver for the uPD161704 LCD Controller + * + * Copyright (C) 2014 Seong-Woo Kim + * + * Based on fb_ili9325.c by Noralf Tronnes + * Based on ili9325.c by Jeroen Domburg + * Init code from UTFT library by Henning Karlsen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_bd663474" +#define WIDTH 240 +#define HEIGHT 320 +#define BPP 16 + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + par->fbtftops.reset(par); + + /* Initialization sequence from Lib_UTFT */ + + /* oscillator start */ + write_reg(par, 0x000,0x0001); /*oscillator 0: stop, 1: operation */ + mdelay(10); + + /* Power settings */ + write_reg(par, 0x100, 0x0000 ); /* power supply setup */ + write_reg(par, 0x101, 0x0000 ); + write_reg(par, 0x102, 0x3110 ); + write_reg(par, 0x103, 0xe200 ); + write_reg(par, 0x110, 0x009d ); + write_reg(par, 0x111, 0x0022 ); + write_reg(par, 0x100, 0x0120 ); + mdelay( 20 ); + + write_reg(par, 0x100, 0x3120 ); + mdelay( 80 ); + /* Display control */ + write_reg(par, 0x001, 0x0100 ); + write_reg(par, 0x002, 0x0000 ); + write_reg(par, 0x003, 0x1230 ); + write_reg(par, 0x006, 0x0000 ); + write_reg(par, 0x007, 0x0101 ); + write_reg(par, 0x008, 0x0808 ); + write_reg(par, 0x009, 0x0000 ); + write_reg(par, 0x00b, 0x0000 ); + write_reg(par, 0x00c, 0x0000 ); + write_reg(par, 0x00d, 0x0018 ); + /* LTPS control settings */ + write_reg(par, 0x012, 0x0000 ); + write_reg(par, 0x013, 0x0000 ); + write_reg(par, 0x018, 0x0000 ); + write_reg(par, 0x019, 0x0000 ); + + write_reg(par, 0x203, 0x0000 ); + write_reg(par, 0x204, 0x0000 ); + + write_reg(par, 0x210, 0x0000 ); + write_reg(par, 0x211, 0x00ef ); + write_reg(par, 0x212, 0x0000 ); + write_reg(par, 0x213, 0x013f ); + write_reg(par, 0x214, 0x0000 ); + write_reg(par, 0x215, 0x0000 ); + write_reg(par, 0x216, 0x0000 ); + write_reg(par, 0x217, 0x0000 ); + + /* Gray scale settings */ + write_reg(par, 0x300, 0x5343); + write_reg(par, 0x301, 0x1021); + write_reg(par, 0x302, 0x0003); + write_reg(par, 0x303, 0x0011); + write_reg(par, 0x304, 0x050a); + write_reg(par, 0x305, 0x4342); + write_reg(par, 0x306, 0x1100); + write_reg(par, 0x307, 0x0003); + write_reg(par, 0x308, 0x1201); + write_reg(par, 0x309, 0x050a); + + /* RAM access settings */ + write_reg(par, 0x400, 0x4027 ); + write_reg(par, 0x401, 0x0000 ); + write_reg(par, 0x402, 0x0000 ); /* First screen drive position (1) */ + write_reg(par, 0x403, 0x013f ); /* First screen drive position (2) */ + write_reg(par, 0x404, 0x0000 ); + + write_reg(par, 0x200, 0x0000 ); + write_reg(par, 0x201, 0x0000 ); + write_reg(par, 0x100, 0x7120 ); + write_reg(par, 0x007, 0x0103 ); + mdelay( 10 ); + write_reg(par, 0x007, 0x0113 ); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + switch (par->info->var.rotate) { + /* R200h = Horizontal GRAM Start Address */ + /* R201h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0200, xs); + write_reg(par, 0x0201, ys); + break; + case 180: + write_reg(par, 0x0200, WIDTH - 1 - xs); + write_reg(par, 0x0201, HEIGHT - 1 - ys); + break; + case 270: + write_reg(par, 0x0200, WIDTH - 1 - ys); + write_reg(par, 0x0201, xs); + break; + case 90: + write_reg(par, 0x0200, ys); + write_reg(par, 0x0201, HEIGHT - 1 - xs); + break; + } + write_reg(par, 0x202); /* Write Data to GRAM */ +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + /* AM: GRAM update direction */ + case 0: + write_reg(par, 0x003, 0x1230); + break; + case 180: + write_reg(par, 0x003, 0x1200); + break; + case 270: + write_reg(par, 0x003, 0x1228); + break; + case 90: + write_reg(par, 0x003, 0x1218); + break; + } + + return 0; +} + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .bpp = BPP, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "hitachi,bd663474", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:bd663474"); +MODULE_ALIAS("platform:bd663474"); + +MODULE_DESCRIPTION("FB driver for the uPD161704 LCD Controller"); +MODULE_AUTHOR("Seong-Woo Kim"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 39e3d67f8e839f06eacda53fe40da99ac137e094 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:12 +0100 Subject: staging: fbtft: add fb_hx8340bn driver This commit adds the fb_hx8340bn driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 400492a..e6c23d5e 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -19,3 +19,9 @@ config FB_TFT_BD663474 depends on FB_TFT help Generic Framebuffer support for BD663474 + +config FB_TFT_HX8340BN + tristate "FB driver for the HX8340BN LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for HX8340BN diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 9f80a6e..7d89af7 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -5,3 +5,4 @@ fbtft-y += fbtft-core.o fbtft-sysfs.o fbtft-bus.o fbtft # drivers obj-$(CONFIG_FB_TFT_AGM1264K_FL) += fb_agm1264k-fl.o obj-$(CONFIG_FB_TFT_BD663474) += fb_bd663474.o +obj-$(CONFIG_FB_TFT_HX8340BN) += fb_hx8340bn.o diff --git a/drivers/staging/fbtft/fb_hx8340bn.c b/drivers/staging/fbtft/fb_hx8340bn.c new file mode 100644 index 0000000..3939502 --- /dev/null +++ b/drivers/staging/fbtft/fb_hx8340bn.c @@ -0,0 +1,229 @@ +/* + * FB driver for the HX8340BN LCD Controller + * + * This display uses 9-bit SPI: Data/Command bit + 8 data bits + * For platforms that doesn't support 9-bit, the driver is capable + * of emulating this using 8-bit transfer. + * This is done by transfering eight 9-bit words in 9 bytes. + * + * Copyright (C) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_hx8340bn" +#define WIDTH 176 +#define HEIGHT 220 +#define TXBUFLEN (4 * PAGE_SIZE) +#define DEFAULT_GAMMA "1 3 0E 5 0 2 09 0 6 1 7 1 0 2 2\n" \ + "3 3 17 8 4 7 05 7 6 0 3 1 6 0 0 " + + +static bool emulate; +module_param(emulate, bool, 0); +MODULE_PARM_DESC(emulate, "Force emulation in 9-bit mode"); + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* BTL221722-276L startup sequence, from datasheet */ + + /* SETEXTCOM: Set extended command set (C1h) + This command is used to set extended command set access enable. + Enable: After command (C1h), must write: ffh,83h,40h */ + write_reg(par, 0xC1, 0xFF, 0x83, 0x40); + + /* Sleep out + This command turns off sleep mode. + In this mode the DC/DC converter is enabled, Internal oscillator + is started, and panel scanning is started. */ + write_reg(par, 0x11); + mdelay(150); + + /* Undoc'd register? */ + write_reg(par, 0xCA, 0x70, 0x00, 0xD9); + + /* SETOSC: Set Internal Oscillator (B0h) + This command is used to set internal oscillator related settings */ + /* OSC_EN: Enable internal oscillator */ + /* Internal oscillator frequency: 125% x 2.52MHz */ + write_reg(par, 0xB0, 0x01, 0x11); + + /* Drive ability setting */ + write_reg(par, 0xC9, 0x90, 0x49, 0x10, 0x28, 0x28, 0x10, 0x00, 0x06); + mdelay(20); + + /* SETPWCTR5: Set Power Control 5(B5h) + This command is used to set VCOM Low and VCOM High Voltage */ + /* VCOMH 0110101 : 3.925 */ + /* VCOML 0100000 : -1.700 */ + /* 45h=69 VCOMH: "VMH" + 5d VCOML: "VMH" + 5d */ + write_reg(par, 0xB5, 0x35, 0x20, 0x45); + + /* SETPWCTR4: Set Power Control 4(B4h) + VRH[4:0]: Specify the VREG1 voltage adjusting. + VREG1 voltage is for gamma voltage setting. + BT[2:0]: Switch the output factor of step-up circuit 2 + for VGH and VGL voltage generation. */ + write_reg(par, 0xB4, 0x33, 0x25, 0x4C); + mdelay(10); + + /* Interface Pixel Format (3Ah) + This command is used to define the format of RGB picture data, + which is to be transfer via the system and RGB interface. */ + /* RGB interface: 16 Bit/Pixel */ + write_reg(par, 0x3A, 0x05); + + /* Display on (29h) + This command is used to recover from DISPLAY OFF mode. + Output from the Frame Memory is enabled. */ + write_reg(par, 0x29); + mdelay(10); + + return 0; +} + +void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + write_reg(par, FBTFT_CASET, 0x00, xs, 0x00, xe); + write_reg(par, FBTFT_RASET, 0x00, ys, 0x00, ye); + write_reg(par, FBTFT_RAMWR); +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* MADCTL - Memory data access control */ + /* RGB/BGR can be set with H/W pin SRGB and MADCTL BGR bit */ +#define MY (1 << 7) +#define MX (1 << 6) +#define MV (1 << 5) + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, (par->bgr << 3)); + break; + case 270: + write_reg(par, 0x36, MX | MV | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, MX | MY | (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, MY | MV | (par->bgr << 3)); + break; + } + + return 0; +} + +/* + Gamma Curve selection, GC (only GC0 can be customized): + 0 = 2.2, 1 = 1.8, 2 = 2.5, 3 = 1.0 + Gamma string format: + OP0 OP1 CP0 CP1 CP2 CP3 CP4 MP0 MP1 MP2 MP3 MP4 MP5 CGM0 CGM1 + ON0 ON1 CN0 CN1 CN2 CN3 CN4 MN0 MN1 MN2 MN3 MN4 MN5 XXXX GC +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b1111, 0b1111, 0b11111, 0b1111, 0b1111, 0b1111, 0b11111, + 0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b11, 0b11, + 0b1111, 0b1111, 0b11111, 0b1111, 0b1111, 0b1111, 0b11111, + 0b111, 0b111, 0b111, 0b111, 0b111, 0b111, 0b0, 0b0 }; + int i, j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < par->gamma.num_curves; i++) + for (j = 0; j < par->gamma.num_values; j++) + CURVE(i, j) &= mask[i * par->gamma.num_values + j]; + + write_reg(par, 0x26, 1 << CURVE(1, 14)); /* Gamma Set (26h) */ + + if (CURVE(1, 14)) + return 0; /* only GC0 can be customized */ + + write_reg(par, 0xC2, + (CURVE(0, 8) << 4) | CURVE(0, 7), + (CURVE(0, 10) << 4) | CURVE(0, 9), + (CURVE(0, 12) << 4) | CURVE(0, 11), + CURVE(0, 2), + (CURVE(0, 4) << 4) | CURVE(0, 3), + CURVE(0, 5), + CURVE(0, 6), + (CURVE(0, 1) << 4) | CURVE(0, 0), + (CURVE(0, 14) << 2) | CURVE(0, 13)); + + write_reg(par, 0xC3, + (CURVE(1, 8) << 4) | CURVE(1, 7), + (CURVE(1, 10) << 4) | CURVE(1, 9), + (CURVE(1, 12) << 4) | CURVE(1, 11), + CURVE(1, 2), + (CURVE(1, 4) << 4) | CURVE(1, 3), + CURVE(1, 5), + CURVE(1, 6), + (CURVE(1, 1) << 4) | CURVE(1, 0)); + + mdelay(10); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .txbuflen = TXBUFLEN, + .gamma_num = 2, + .gamma_len = 15, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8340bn", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:hx8340bn"); +MODULE_ALIAS("platform:hx8340bn"); + +MODULE_DESCRIPTION("FB driver for the HX8340BN LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 66c06c837993ec9f11d0f71e2e7eb3ac4c5f1956 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:13 +0100 Subject: staging: fbtft: add fb_hx8347d driver This commit adds the fb_hx8347d driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index e6c23d5e..9bb6e7b 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -25,3 +25,9 @@ config FB_TFT_HX8340BN depends on FB_TFT help Generic Framebuffer support for HX8340BN + +config FB_TFT_HX8347D + tristate "FB driver for the HX8347D LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for HX8347D diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 7d89af7..de68bf8 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -6,3 +6,4 @@ fbtft-y += fbtft-core.o fbtft-sysfs.o fbtft-bus.o fbtft obj-$(CONFIG_FB_TFT_AGM1264K_FL) += fb_agm1264k-fl.o obj-$(CONFIG_FB_TFT_BD663474) += fb_bd663474.o obj-$(CONFIG_FB_TFT_HX8340BN) += fb_hx8340bn.o +obj-$(CONFIG_FB_TFT_HX8347D) += fb_hx8347d.o diff --git a/drivers/staging/fbtft/fb_hx8347d.c b/drivers/staging/fbtft/fb_hx8347d.c new file mode 100644 index 0000000..8139a8f --- /dev/null +++ b/drivers/staging/fbtft/fb_hx8347d.c @@ -0,0 +1,181 @@ +/* + * FB driver for the HX8347D LCD Controller + * + * Copyright (C) 2013 Christian Vogelgsang + * + * Based on driver code found here: https://github.com/watterott/r61505u-Adapter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_hx8347d" +#define WIDTH 320 +#define HEIGHT 240 +#define DEFAULT_GAMMA "0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" \ + "0 0 0 0 0 0 0 0 0 0 0 0 0 0" + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* driving ability */ + write_reg(par, 0xEA, 0x00); + write_reg(par, 0xEB, 0x20); + write_reg(par, 0xEC, 0x0C); + write_reg(par, 0xED, 0xC4); + write_reg(par, 0xE8, 0x40); + write_reg(par, 0xE9, 0x38); + write_reg(par, 0xF1, 0x01); + write_reg(par, 0xF2, 0x10); + write_reg(par, 0x27, 0xA3); + + /* power voltage */ + write_reg(par, 0x1B, 0x1B); + write_reg(par, 0x1A, 0x01); + write_reg(par, 0x24, 0x2F); + write_reg(par, 0x25, 0x57); + + /* VCOM offset */ + write_reg(par, 0x23, 0x8D); /* for flicker adjust */ + + /* power on */ + write_reg(par, 0x18, 0x36); + write_reg(par, 0x19, 0x01); /* start osc */ + write_reg(par, 0x01, 0x00); /* wakeup */ + write_reg(par, 0x1F, 0x88); + mdelay(5); + write_reg(par, 0x1F, 0x80); + mdelay(5); + write_reg(par, 0x1F, 0x90); + mdelay(5); + write_reg(par, 0x1F, 0xD0); + mdelay(5); + + /* color selection */ + write_reg(par, 0x17, 0x05); /* 65k */ + + /*panel characteristic */ + write_reg(par, 0x36, 0x00); + + /*display on */ + write_reg(par, 0x28, 0x38); + mdelay(40); + write_reg(par, 0x28, 0x3C); + + /* orientation */ + write_reg(par, 0x16, 0x60 | (par->bgr << 3)); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + write_reg(par, 0x02, (xs >> 8) & 0xFF); + write_reg(par, 0x03, xs & 0xFF); + write_reg(par, 0x04, (xe >> 8) & 0xFF); + write_reg(par, 0x05, xe & 0xFF); + write_reg(par, 0x06, (ys >> 8) & 0xFF); + write_reg(par, 0x07, ys & 0xFF); + write_reg(par, 0x08, (ye >> 8) & 0xFF); + write_reg(par, 0x09, ye & 0xFF); + write_reg(par, 0x22); +} + +/* + Gamma string format: + VRP0 VRP1 VRP2 VRP3 VRP4 VRP5 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 CGM + VRN0 VRN1 VRN2 VRN3 VRN4 VRN5 PRN0 PRN1 PKN0 PKN1 PKN2 PKN3 PKN4 CGM +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, + 0b1111111, 0b1111111, + 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, + 0b1111}; + int i, j; + int acc = 0; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < par->gamma.num_curves; i++) + for (j = 0; j < par->gamma.num_values; j++) { + acc += CURVE(i, j); + CURVE(i, j) &= mask[j]; + } + + if (acc == 0) /* skip if all values are zero */ + return 0; + + for (i = 0; i < par->gamma.num_curves; i++) { + write_reg(par, 0x40 + (i * 0x10), CURVE(i, 0)); + write_reg(par, 0x41 + (i * 0x10), CURVE(i, 1)); + write_reg(par, 0x42 + (i * 0x10), CURVE(i, 2)); + write_reg(par, 0x43 + (i * 0x10), CURVE(i, 3)); + write_reg(par, 0x44 + (i * 0x10), CURVE(i, 4)); + write_reg(par, 0x45 + (i * 0x10), CURVE(i, 5)); + write_reg(par, 0x46 + (i * 0x10), CURVE(i, 6)); + write_reg(par, 0x47 + (i * 0x10), CURVE(i, 7)); + write_reg(par, 0x48 + (i * 0x10), CURVE(i, 8)); + write_reg(par, 0x49 + (i * 0x10), CURVE(i, 9)); + write_reg(par, 0x4A + (i * 0x10), CURVE(i, 10)); + write_reg(par, 0x4B + (i * 0x10), CURVE(i, 11)); + write_reg(par, 0x4C + (i * 0x10), CURVE(i, 12)); + } + write_reg(par, 0x5D, (CURVE(1, 0) << 4) | CURVE(0, 0)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = 2, + .gamma_len = 14, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8347d", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:hx8347d"); +MODULE_ALIAS("platform:hx8347d"); + +MODULE_DESCRIPTION("FB driver for the HX8347D LCD Controller"); +MODULE_AUTHOR("Christian Vogelgsang"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 5a714d33080f9c9afb61f6ebd108b56f11ff6c48 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:14 +0100 Subject: staging: fbtft: add fb_hx8353d driver This commit adds the fb_hx8353d driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 9bb6e7b..015429b 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -31,3 +31,9 @@ config FB_TFT_HX8347D depends on FB_TFT help Generic Framebuffer support for HX8347D + +config FB_TFT_HX8353D + tristate "FB driver for the HX8353D LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for HX8353D diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index de68bf8..766e285 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_FB_TFT_AGM1264K_FL) += fb_agm1264k-fl.o obj-$(CONFIG_FB_TFT_BD663474) += fb_bd663474.o obj-$(CONFIG_FB_TFT_HX8340BN) += fb_hx8340bn.o obj-$(CONFIG_FB_TFT_HX8347D) += fb_hx8347d.o +obj-$(CONFIG_FB_TFT_HX8353D) += fb_hx8353d.o diff --git a/drivers/staging/fbtft/fb_hx8353d.c b/drivers/staging/fbtft/fb_hx8353d.c new file mode 100644 index 0000000..c9512dc --- /dev/null +++ b/drivers/staging/fbtft/fb_hx8353d.c @@ -0,0 +1,166 @@ +/* + * FB driver for the HX8353D LCD Controller + * + * Copyright (c) 2014 Petr Olivka + * Copyright (c) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_hx8353d" +#define DEFAULT_GAMMA "50 77 40 08 BF 00 03 0F 00 01 73 00 72 03 B0 0F 08 00 0F" + +static int init_display(struct fbtft_par *par) +{ + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + mdelay(150); + + /* SETEXTC */ + write_reg(par, 0xB9, 0xFF, 0x83, 0x53); + + /* RADJ */ + write_reg(par, 0xB0, 0x3C, 0x01); + + /* VCOM */ + write_reg(par, 0xB6, 0x94, 0x6C, 0x50); + + /* PWR */ + write_reg(par, 0xB1, 0x00, 0x01, 0x1B, 0x03, 0x01, 0x08, 0x77, 0x89); + + /* COLMOD */ + write_reg(par, 0x3A, 0x05); + + /* MEM ACCESS */ + write_reg(par, 0x36, 0xC0); + + /* SLPOUT - Sleep out & booster on */ + write_reg(par, 0x11); + mdelay(150); + + /* DISPON - Display On */ + write_reg(par, 0x29); + + /* RGBSET */ + write_reg(par, 0x2D, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62); + + return 0; +}; + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* column address */ + write_reg(par, 0x2a, xs >> 8, xs & 0xff, xe >> 8, xe & 0xff); + + /* row adress */ + write_reg(par, 0x2b, ys >> 8, ys & 0xff, ye >> 8, ye & 0xff); + + /* memory write */ + write_reg(par, 0x2c); +} + +#define my (1 << 7) +#define mx (1 << 6) +#define mv (1 << 5) +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* madctl - memory data access control + rgb/bgr: + 1. mode selection pin srgb + rgb h/w pin for color filter setting: 0=rgb, 1=bgr + 2. madctl rgb bit + rgb-bgr order color filter panel: 0=rgb, 1=bgr */ + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, mx | my | (par->bgr << 3)); + break; + case 270: + write_reg(par, 0x36, my | mv | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, mx | mv | (par->bgr << 3)); + break; + } + + return 0; +} + +/* + gamma string format: +*/ +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + write_reg(par, 0xE0, + curves[0], curves[1], curves[2], curves[3], + curves[4], curves[5], curves[6], curves[7], + curves[8], curves[9], curves[10], curves[11], + curves[12], curves[13], curves[14], curves[15], + curves[16], curves[17], curves[18]); + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = 128, + .height = 160, + .gamma_num = 1, + .gamma_len = 19, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "himax,hx8353d", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:hx8353d"); +MODULE_ALIAS("platform:hx8353d"); + +MODULE_DESCRIPTION("FB driver for the HX8353D LCD Controller"); +MODULE_AUTHOR("Petr Olivka"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 69e6089d206d4ab35f92e371e36fb58ace424015 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:15 +0100 Subject: staging: fbtft: add fb_ili9320 driver This commit adds the fb_ili9320 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 015429b..eb57f19 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -37,3 +37,9 @@ config FB_TFT_HX8353D depends on FB_TFT help Generic Framebuffer support for HX8353D + +config FB_TFT_ILI9320 + tristate "FB driver for the ILI9320 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9320 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 766e285..e101cb6 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_FB_TFT_BD663474) += fb_bd663474.o obj-$(CONFIG_FB_TFT_HX8340BN) += fb_hx8340bn.o obj-$(CONFIG_FB_TFT_HX8347D) += fb_hx8347d.o obj-$(CONFIG_FB_TFT_HX8353D) += fb_hx8353d.o +obj-$(CONFIG_FB_TFT_ILI9320) += fb_ili9320.o diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c new file mode 100644 index 0000000..b26d893 --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9320.c @@ -0,0 +1,234 @@ +/* + * FB driver for the ILI9320 LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_ili9320" +#define WIDTH 240 +#define HEIGHT 320 +#define DEFAULT_GAMMA "07 07 6 0 0 0 5 5 4 0\n" \ + "07 08 4 7 5 1 2 0 7 7" + + +static unsigned read_devicecode(struct fbtft_par *par) +{ + int ret; + u8 rxbuf[8] = {0, }; + + write_reg(par, 0x0000); + ret = par->fbtftops.read(par, rxbuf, 4); + return (rxbuf[2] << 8) | rxbuf[3]; +} + +static int init_display(struct fbtft_par *par) +{ + unsigned devcode; + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + devcode = read_devicecode(par); + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "Device code: 0x%04X\n", + devcode); + if ((devcode != 0x0000) && (devcode != 0x9320)) + dev_warn(par->info->device, + "Unrecognized Device code: 0x%04X (expected 0x9320)\n", + devcode); + + /* Initialization sequence from ILI9320 Application Notes */ + + /* *********** Start Initial Sequence ********* */ + write_reg(par, 0x00E5, 0x8000); /* Set the Vcore voltage and this setting is must. */ + write_reg(par, 0x0000, 0x0001); /* Start internal OSC. */ + write_reg(par, 0x0001, 0x0100); /* set SS and SM bit */ + write_reg(par, 0x0002, 0x0700); /* set 1 line inversion */ + write_reg(par, 0x0004, 0x0000); /* Resize register */ + write_reg(par, 0x0008, 0x0202); /* set the back and front porch */ + write_reg(par, 0x0009, 0x0000); /* set non-display area refresh cycle */ + write_reg(par, 0x000A, 0x0000); /* FMARK function */ + write_reg(par, 0x000C, 0x0000); /* RGB interface setting */ + write_reg(par, 0x000D, 0x0000); /* Frame marker Position */ + write_reg(par, 0x000F, 0x0000); /* RGB interface polarity */ + + /* ***********Power On sequence *************** */ + write_reg(par, 0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + write_reg(par, 0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */ + write_reg(par, 0x0012, 0x0000); /* VREG1OUT voltage */ + write_reg(par, 0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */ + mdelay(200); /* Dis-charge capacitor power voltage */ + write_reg(par, 0x0010, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + write_reg(par, 0x0011, 0x0031); /* R11h=0x0031 at VCI=3.3V DC1[2:0], DC0[2:0], VC[2:0] */ + mdelay(50); + write_reg(par, 0x0012, 0x0138); /* R12h=0x0138 at VCI=3.3V VREG1OUT voltage */ + mdelay(50); + write_reg(par, 0x0013, 0x1800); /* R13h=0x1800 at VCI=3.3V VDV[4:0] for VCOM amplitude */ + write_reg(par, 0x0029, 0x0008); /* R29h=0x0008 at VCI=3.3V VCM[4:0] for VCOMH */ + mdelay(50); + write_reg(par, 0x0020, 0x0000); /* GRAM horizontal Address */ + write_reg(par, 0x0021, 0x0000); /* GRAM Vertical Address */ + + /* ------------------ Set GRAM area --------------- */ + write_reg(par, 0x0050, 0x0000); /* Horizontal GRAM Start Address */ + write_reg(par, 0x0051, 0x00EF); /* Horizontal GRAM End Address */ + write_reg(par, 0x0052, 0x0000); /* Vertical GRAM Start Address */ + write_reg(par, 0x0053, 0x013F); /* Vertical GRAM Start Address */ + write_reg(par, 0x0060, 0x2700); /* Gate Scan Line */ + write_reg(par, 0x0061, 0x0001); /* NDL,VLE, REV */ + write_reg(par, 0x006A, 0x0000); /* set scrolling line */ + + /* -------------- Partial Display Control --------- */ + write_reg(par, 0x0080, 0x0000); + write_reg(par, 0x0081, 0x0000); + write_reg(par, 0x0082, 0x0000); + write_reg(par, 0x0083, 0x0000); + write_reg(par, 0x0084, 0x0000); + write_reg(par, 0x0085, 0x0000); + + /* -------------- Panel Control ------------------- */ + write_reg(par, 0x0090, 0x0010); + write_reg(par, 0x0092, 0x0000); + write_reg(par, 0x0093, 0x0003); + write_reg(par, 0x0095, 0x0110); + write_reg(par, 0x0097, 0x0000); + write_reg(par, 0x0098, 0x0000); + write_reg(par, 0x0007, 0x0173); /* 262K color and display ON */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + switch (par->info->var.rotate) { + /* R20h = Horizontal GRAM Start Address */ + /* R21h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0020, xs); + write_reg(par, 0x0021, ys); + break; + case 180: + write_reg(par, 0x0020, WIDTH - 1 - xs); + write_reg(par, 0x0021, HEIGHT - 1 - ys); + break; + case 270: + write_reg(par, 0x0020, WIDTH - 1 - ys); + write_reg(par, 0x0021, xs); + break; + case 90: + write_reg(par, 0x0020, ys); + write_reg(par, 0x0021, HEIGHT - 1 - xs); + break; + } + write_reg(par, 0x0022); /* Write Data to GRAM */ +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x3, (par->bgr << 12) | 0x30); + break; + case 270: + write_reg(par, 0x3, (par->bgr << 12) | 0x28); + break; + case 180: + write_reg(par, 0x3, (par->bgr << 12) | 0x00); + break; + case 90: + write_reg(par, 0x3, (par->bgr << 12) | 0x18); + break; + } + return 0; +} + +/* + Gamma string format: + VRP0 VRP1 RP0 RP1 KP0 KP1 KP2 KP3 KP4 KP5 + VRN0 VRN1 RN0 RN1 KN0 KN1 KN2 KN3 KN4 KN5 +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111, + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111 }; + int i, j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < 2; i++) + for (j = 0; j < 10; j++) + CURVE(i, j) &= mask[i*par->gamma.num_values + j]; + + write_reg(par, 0x0030, CURVE(0, 5) << 8 | CURVE(0, 4)); + write_reg(par, 0x0031, CURVE(0, 7) << 8 | CURVE(0, 6)); + write_reg(par, 0x0032, CURVE(0, 9) << 8 | CURVE(0, 8)); + write_reg(par, 0x0035, CURVE(0, 3) << 8 | CURVE(0, 2)); + write_reg(par, 0x0036, CURVE(0, 1) << 8 | CURVE(0, 0)); + + write_reg(par, 0x0037, CURVE(1, 5) << 8 | CURVE(1, 4)); + write_reg(par, 0x0038, CURVE(1, 7) << 8 | CURVE(1, 6)); + write_reg(par, 0x0039, CURVE(1, 9) << 8 | CURVE(1, 8)); + write_reg(par, 0x003C, CURVE(1, 3) << 8 | CURVE(1, 2)); + write_reg(par, 0x003D, CURVE(1, 1) << 8 | CURVE(1, 0)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = 2, + .gamma_len = 10, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9320", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9320"); +MODULE_ALIAS("platform:ili9320"); + +MODULE_DESCRIPTION("FB driver for the ILI9320 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 2fc51f76cf28e42a73b3c1748d7628e03a1d0e11 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:16 +0100 Subject: staging: fbtft: add fb_ili9325 driver This commit adds the fb_ili9325 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index eb57f19..24b9d91 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -43,3 +43,9 @@ config FB_TFT_ILI9320 depends on FB_TFT help Generic Framebuffer support for ILI9320 + +config FB_TFT_ILI9325 + tristate "FB driver for the ILI9325 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9325 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index e101cb6..09d4697 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_FB_TFT_HX8340BN) += fb_hx8340bn.o obj-$(CONFIG_FB_TFT_HX8347D) += fb_hx8347d.o obj-$(CONFIG_FB_TFT_HX8353D) += fb_hx8353d.o obj-$(CONFIG_FB_TFT_ILI9320) += fb_ili9320.o +obj-$(CONFIG_FB_TFT_ILI9325) += fb_ili9325.o diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c new file mode 100644 index 0000000..5f88145 --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -0,0 +1,291 @@ +/* + * FB driver for the ILI9325 LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * Based on ili9325.c by Jeroen Domburg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_ili9325" +#define WIDTH 240 +#define HEIGHT 320 +#define BPP 16 +#define FPS 20 +#define DEFAULT_GAMMA "0F 00 7 2 0 0 6 5 4 1\n" \ + "04 16 2 7 6 3 2 1 7 7" + + +static unsigned bt = 6; /* VGL=Vci*4 , VGH=Vci*4 */ +module_param(bt, uint, 0); +MODULE_PARM_DESC(bt, "Sets the factor used in the step-up circuits"); + +static unsigned vc = 0b011; /* Vci1=Vci*0.80 */ +module_param(vc, uint, 0); +MODULE_PARM_DESC(vc, +"Sets the ratio factor of Vci to generate the reference voltages Vci1"); + +static unsigned vrh = 0b1101; /* VREG1OUT=Vci*1.85 */ +module_param(vrh, uint, 0); +MODULE_PARM_DESC(vrh, +"Set the amplifying rate (1.6 ~ 1.9) of Vci applied to output the VREG1OUT"); + +static unsigned vdv = 0b10010; /* VCOMH amplitude=VREG1OUT*0.98 */ +module_param(vdv, uint, 0); +MODULE_PARM_DESC(vdv, +"Select the factor of VREG1OUT to set the amplitude of Vcom"); + +static unsigned vcm = 0b001010; /* VCOMH=VREG1OUT*0.735 */ +module_param(vcm, uint, 0); +MODULE_PARM_DESC(vcm, "Set the internal VcomH voltage"); + + +/* +Verify that this configuration is within the Voltage limits + +Display module configuration: Vcc = IOVcc = Vci = 3.3V + + Voltages +---------- +Vci = 3.3 +Vci1 = Vci * 0.80 = 2.64 +DDVDH = Vci1 * 2 = 5.28 +VCL = -Vci1 = -2.64 +VREG1OUT = Vci * 1.85 = 4.88 +VCOMH = VREG1OUT * 0.735 = 3.59 +VCOM amplitude = VREG1OUT * 0.98 = 4.79 +VGH = Vci * 4 = 13.2 +VGL = -Vci * 4 = -13.2 + + Limits +-------- +Power supplies +1.65 < IOVcc < 3.30 => 1.65 < 3.3 < 3.30 +2.40 < Vcc < 3.30 => 2.40 < 3.3 < 3.30 +2.50 < Vci < 3.30 => 2.50 < 3.3 < 3.30 + +Source/VCOM power supply voltage + 4.50 < DDVDH < 6.0 => 4.50 < 5.28 < 6.0 +-3.0 < VCL < -2.0 => -3.0 < -2.64 < -2.0 +VCI - VCL < 6.0 => 5.94 < 6.0 + +Gate driver output voltage + 10 < VGH < 20 => 10 < 13.2 < 20 +-15 < VGL < -5 => -15 < -13.2 < -5 +VGH - VGL < 32 => 26.4 < 32 + +VCOM driver output voltage +VCOMH - VCOML < 6.0 => 4.79 < 6.0 +*/ + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + bt &= 0b111; + vc &= 0b111; + vrh &= 0b1111; + vdv &= 0b11111; + vcm &= 0b111111; + + /* Initialization sequence from ILI9325 Application Notes */ + + /* ----------- Start Initial Sequence ----------- */ + write_reg(par, 0x00E3, 0x3008); /* Set internal timing */ + write_reg(par, 0x00E7, 0x0012); /* Set internal timing */ + write_reg(par, 0x00EF, 0x1231); /* Set internal timing */ + write_reg(par, 0x0001, 0x0100); /* set SS and SM bit */ + write_reg(par, 0x0002, 0x0700); /* set 1 line inversion */ + write_reg(par, 0x0004, 0x0000); /* Resize register */ + write_reg(par, 0x0008, 0x0207); /* set the back porch and front porch */ + write_reg(par, 0x0009, 0x0000); /* set non-display area refresh cycle */ + write_reg(par, 0x000A, 0x0000); /* FMARK function */ + write_reg(par, 0x000C, 0x0000); /* RGB interface setting */ + write_reg(par, 0x000D, 0x0000); /* Frame marker Position */ + write_reg(par, 0x000F, 0x0000); /* RGB interface polarity */ + + /* ----------- Power On sequence ----------- */ + write_reg(par, 0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + write_reg(par, 0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */ + write_reg(par, 0x0012, 0x0000); /* VREG1OUT voltage */ + write_reg(par, 0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */ + mdelay(200); /* Dis-charge capacitor power voltage */ + write_reg(par, 0x0010, /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + (1 << 12) | (bt << 8) | (1 << 7) | (0b001 << 4)); + write_reg(par, 0x0011, 0x220 | vc); /* DC1[2:0], DC0[2:0], VC[2:0] */ + mdelay(50); /* Delay 50ms */ + write_reg(par, 0x0012, vrh); /* Internal reference voltage= Vci; */ + mdelay(50); /* Delay 50ms */ + write_reg(par, 0x0013, vdv << 8); /* Set VDV[4:0] for VCOM amplitude */ + write_reg(par, 0x0029, vcm); /* Set VCM[5:0] for VCOMH */ + write_reg(par, 0x002B, 0x000C); /* Set Frame Rate */ + mdelay(50); /* Delay 50ms */ + write_reg(par, 0x0020, 0x0000); /* GRAM horizontal Address */ + write_reg(par, 0x0021, 0x0000); /* GRAM Vertical Address */ + + /*------------------ Set GRAM area --------------- */ + write_reg(par, 0x0050, 0x0000); /* Horizontal GRAM Start Address */ + write_reg(par, 0x0051, 0x00EF); /* Horizontal GRAM End Address */ + write_reg(par, 0x0052, 0x0000); /* Vertical GRAM Start Address */ + write_reg(par, 0x0053, 0x013F); /* Vertical GRAM Start Address */ + write_reg(par, 0x0060, 0xA700); /* Gate Scan Line */ + write_reg(par, 0x0061, 0x0001); /* NDL,VLE, REV */ + write_reg(par, 0x006A, 0x0000); /* set scrolling line */ + + /*-------------- Partial Display Control --------- */ + write_reg(par, 0x0080, 0x0000); + write_reg(par, 0x0081, 0x0000); + write_reg(par, 0x0082, 0x0000); + write_reg(par, 0x0083, 0x0000); + write_reg(par, 0x0084, 0x0000); + write_reg(par, 0x0085, 0x0000); + + /*-------------- Panel Control ------------------- */ + write_reg(par, 0x0090, 0x0010); + write_reg(par, 0x0092, 0x0600); + write_reg(par, 0x0007, 0x0133); /* 262K color and display ON */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + switch (par->info->var.rotate) { + /* R20h = Horizontal GRAM Start Address */ + /* R21h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0020, xs); + write_reg(par, 0x0021, ys); + break; + case 180: + write_reg(par, 0x0020, WIDTH - 1 - xs); + write_reg(par, 0x0021, HEIGHT - 1 - ys); + break; + case 270: + write_reg(par, 0x0020, WIDTH - 1 - ys); + write_reg(par, 0x0021, xs); + break; + case 90: + write_reg(par, 0x0020, ys); + write_reg(par, 0x0021, HEIGHT - 1 - xs); + break; + } + write_reg(par, 0x0022); /* Write Data to GRAM */ +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + /* AM: GRAM update direction */ + case 0: + write_reg(par, 0x03, 0x0030 | (par->bgr << 12)); + break; + case 180: + write_reg(par, 0x03, 0x0000 | (par->bgr << 12)); + break; + case 270: + write_reg(par, 0x03, 0x0028 | (par->bgr << 12)); + break; + case 90: + write_reg(par, 0x03, 0x0018 | (par->bgr << 12)); + break; + } + + return 0; +} + +/* + Gamma string format: + VRP0 VRP1 RP0 RP1 KP0 KP1 KP2 KP3 KP4 KP5 + VRN0 VRN1 RN0 RN1 KN0 KN1 KN2 KN3 KN4 KN5 +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111, + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111 }; + int i, j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < 2; i++) + for (j = 0; j < 10; j++) + CURVE(i, j) &= mask[i*par->gamma.num_values + j]; + + write_reg(par, 0x0030, CURVE(0, 5) << 8 | CURVE(0, 4)); + write_reg(par, 0x0031, CURVE(0, 7) << 8 | CURVE(0, 6)); + write_reg(par, 0x0032, CURVE(0, 9) << 8 | CURVE(0, 8)); + write_reg(par, 0x0035, CURVE(0, 3) << 8 | CURVE(0, 2)); + write_reg(par, 0x0036, CURVE(0, 1) << 8 | CURVE(0, 0)); + + write_reg(par, 0x0037, CURVE(1, 5) << 8 | CURVE(1, 4)); + write_reg(par, 0x0038, CURVE(1, 7) << 8 | CURVE(1, 6)); + write_reg(par, 0x0039, CURVE(1, 9) << 8 | CURVE(1, 8)); + write_reg(par, 0x003C, CURVE(1, 3) << 8 | CURVE(1, 2)); + write_reg(par, 0x003D, CURVE(1, 1) << 8 | CURVE(1, 0)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .bpp = BPP, + .fps = FPS, + .gamma_num = 2, + .gamma_len = 10, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9325", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9325"); +MODULE_ALIAS("platform:ili9325"); + +MODULE_DESCRIPTION("FB driver for the ILI9325 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 8f7fdaaffff4946fc1aebf496c982216cfebb484 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:17 +0100 Subject: staging: fbtft: add fb_ili9340 driver This commit adds the fb_ili9340 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 24b9d91..6295acf 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -49,3 +49,9 @@ config FB_TFT_ILI9325 depends on FB_TFT help Generic Framebuffer support for ILI9325 + +config FB_TFT_ILI9340 + tristate "FB driver for the ILI9340 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9340 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 09d4697..aa65da8 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_FB_TFT_HX8347D) += fb_hx8347d.o obj-$(CONFIG_FB_TFT_HX8353D) += fb_hx8353d.o obj-$(CONFIG_FB_TFT_ILI9320) += fb_ili9320.o obj-$(CONFIG_FB_TFT_ILI9325) += fb_ili9325.o +obj-$(CONFIG_FB_TFT_ILI9340) += fb_ili9340.o diff --git a/drivers/staging/fbtft/fb_ili9340.c b/drivers/staging/fbtft/fb_ili9340.c new file mode 100644 index 0000000..985687d --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9340.c @@ -0,0 +1,163 @@ +/* + * FB driver for the ILI9340 LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_ili9340" +#define WIDTH 240 +#define HEIGHT 320 + + +/* Init sequence taken from: Arduino Library for the Adafruit 2.2" display */ +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + write_reg(par, 0xEF, 0x03, 0x80, 0x02); + write_reg(par, 0xCF, 0x00 , 0XC1 , 0X30); + write_reg(par, 0xED, 0x64 , 0x03 , 0X12 , 0X81); + write_reg(par, 0xE8, 0x85 , 0x00 , 0x78); + write_reg(par, 0xCB, 0x39 , 0x2C , 0x00 , 0x34 , 0x02); + write_reg(par, 0xF7, 0x20); + write_reg(par, 0xEA, 0x00 , 0x00); + + /* Power Control 1 */ + write_reg(par, 0xC0, 0x23); + + /* Power Control 2 */ + write_reg(par, 0xC1, 0x10); + + /* VCOM Control 1 */ + write_reg(par, 0xC5, 0x3e, 0x28); + + /* VCOM Control 2 */ + write_reg(par, 0xC7, 0x86); + + /* COLMOD: Pixel Format Set */ + /* 16 bits/pixel */ + write_reg(par, 0x3A, 0x55); + + /* Frame Rate Control */ + /* Division ratio = fosc, Frame Rate = 79Hz */ + write_reg(par, 0xB1, 0x00, 0x18); + + /* Display Function Control */ + write_reg(par, 0xB6, 0x08, 0x82, 0x27); + + /* Gamma Function Disable */ + write_reg(par, 0xF2, 0x00); + + /* Gamma curve selected */ + write_reg(par, 0x26, 0x01); + + /* Positive Gamma Correction */ + write_reg(par, 0xE0, + 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, + 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00); + + /* Negative Gamma Correction */ + write_reg(par, 0xE1, + 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, + 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F); + + /* Sleep OUT */ + write_reg(par, 0x11); + + mdelay(120); + + /* Display ON */ + write_reg(par, 0x29); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address */ + write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF); + + /* Row adress */ + write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +#define ILI9340_MADCTL_MV 0x20 +#define ILI9340_MADCTL_MX 0x40 +#define ILI9340_MADCTL_MY 0x80 +static int set_var(struct fbtft_par *par) +{ + u8 val; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 270: + val = ILI9340_MADCTL_MV; + break; + case 180: + val = ILI9340_MADCTL_MY; + break; + case 90: + val = ILI9340_MADCTL_MV | ILI9340_MADCTL_MY | ILI9340_MADCTL_MX; + break; + default: + val = ILI9340_MADCTL_MX; + break; + } + /* Memory Access Control */ + write_reg(par, 0x36, val | (par->bgr << 3)); + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9340", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9340"); +MODULE_ALIAS("platform:ili9340"); + +MODULE_DESCRIPTION("FB driver for the ILI9340 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 9b78e456a7526755f7c58fb6a249735a4fe0288b Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:18 +0100 Subject: staging: fbtft: add fb_ili9341 driver This commit adds the fb_ili9341 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 6295acf..ee09e9d 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -55,3 +55,9 @@ config FB_TFT_ILI9340 depends on FB_TFT help Generic Framebuffer support for ILI9340 + +config FB_TFT_ILI9341 + tristate "FB driver for the ILI9341 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9341 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index aa65da8..a83a685 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_FB_TFT_HX8353D) += fb_hx8353d.o obj-$(CONFIG_FB_TFT_ILI9320) += fb_ili9320.o obj-$(CONFIG_FB_TFT_ILI9325) += fb_ili9325.o obj-$(CONFIG_FB_TFT_ILI9340) += fb_ili9340.o +obj-$(CONFIG_FB_TFT_ILI9341) += fb_ili9341.o diff --git a/drivers/staging/fbtft/fb_ili9341.c b/drivers/staging/fbtft/fb_ili9341.c new file mode 100644 index 0000000..225b2d8 --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9341.c @@ -0,0 +1,179 @@ +/* + * FB driver for the ILI9341 LCD display controller + * + * This display uses 9-bit SPI: Data/Command bit + 8 data bits + * For platforms that doesn't support 9-bit, the driver is capable + * of emulating this using 8-bit transfer. + * This is done by transfering eight 9-bit words in 9 bytes. + * + * Copyright (C) 2013 Christian Vogelgsang + * Based on adafruit22fb.c by Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_ili9341" +#define WIDTH 240 +#define HEIGHT 320 +#define TXBUFLEN (4 * PAGE_SIZE) +#define DEFAULT_GAMMA "1F 1A 18 0A 0F 06 45 87 32 0A 07 02 07 05 00\n" \ + "00 25 27 05 10 09 3A 78 4D 05 18 0D 38 3A 1F" + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* startup sequence for MI0283QT-9A */ + write_reg(par, 0x01); /* software reset */ + mdelay(5); + write_reg(par, 0x28); /* display off */ + /* --------------------------------------------------------- */ + write_reg(par, 0xCF, 0x00, 0x83, 0x30); + write_reg(par, 0xED, 0x64, 0x03, 0x12, 0x81); + write_reg(par, 0xE8, 0x85, 0x01, 0x79); + write_reg(par, 0xCB, 0x39, 0X2C, 0x00, 0x34, 0x02); + write_reg(par, 0xF7, 0x20); + write_reg(par, 0xEA, 0x00, 0x00); + /* ------------power control-------------------------------- */ + write_reg(par, 0xC0, 0x26); + write_reg(par, 0xC1, 0x11); + /* ------------VCOM --------- */ + write_reg(par, 0xC5, 0x35, 0x3E); + write_reg(par, 0xC7, 0xBE); + /* ------------memory access control------------------------ */ + write_reg(par, 0x3A, 0x55); /* 16bit pixel */ + /* ------------frame rate----------------------------------- */ + write_reg(par, 0xB1, 0x00, 0x1B); + /* ------------Gamma---------------------------------------- */ + /* write_reg(par, 0xF2, 0x08); */ /* Gamma Function Disable */ + write_reg(par, 0x26, 0x01); + /* ------------display-------------------------------------- */ + write_reg(par, 0xB7, 0x07); /* entry mode set */ + write_reg(par, 0xB6, 0x0A, 0x82, 0x27, 0x00); + write_reg(par, 0x11); /* sleep out */ + mdelay(100); + write_reg(par, 0x29); /* display on */ + mdelay(20); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address set */ + write_reg(par, 0x2A, + (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF); + + /* Row adress set */ + write_reg(par, 0x2B, + (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +#define MEM_Y (7) /* MY row address order */ +#define MEM_X (6) /* MX column address order */ +#define MEM_V (5) /* MV row / column exchange */ +#define MEM_L (4) /* ML vertical refresh order */ +#define MEM_H (2) /* MH horizontal refresh order */ +#define MEM_BGR (3) /* RGB-BGR Order */ +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, (1 << MEM_X) | (par->bgr << MEM_BGR)); + break; + case 270: + write_reg(par, 0x36, + (1<bgr << MEM_BGR)); + break; + case 180: + write_reg(par, 0x36, (1 << MEM_Y) | (par->bgr << MEM_BGR)); + break; + case 90: + write_reg(par, 0x36, (1 << MEM_Y) | (1 << MEM_X) | + (1 << MEM_V) | (par->bgr << MEM_BGR)); + break; + } + + return 0; +} + +/* + Gamma string format: + Positive: Par1 Par2 [...] Par15 + Negative: Par1 Par2 [...] Par15 +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + int i; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + for (i = 0; i < par->gamma.num_curves; i++) + write_reg(par, 0xE0 + i, + CURVE(i, 0), CURVE(i, 1), CURVE(i, 2), + CURVE(i, 3), CURVE(i, 4), CURVE(i, 5), + CURVE(i, 6), CURVE(i, 7), CURVE(i, 8), + CURVE(i, 9), CURVE(i, 10), CURVE(i, 11), + CURVE(i, 12), CURVE(i, 13), CURVE(i, 14)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .txbuflen = TXBUFLEN, + .gamma_num = 2, + .gamma_len = 15, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9341", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9341"); +MODULE_ALIAS("platform:ili9341"); + +MODULE_DESCRIPTION("FB driver for the ILI9341 LCD display controller"); +MODULE_AUTHOR("Christian Vogelgsang"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From d416d5c02fe7156fe061f1bde178a18c181ad432 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:19 +0100 Subject: staging: fbtft: add fb_ili9481 driver This commit adds the fb_ili9481 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index ee09e9d..86a1bee 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -61,3 +61,9 @@ config FB_TFT_ILI9341 depends on FB_TFT help Generic Framebuffer support for ILI9341 + +config FB_TFT_ILI9481 + tristate "FB driver for the ILI9481 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9481 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index a83a685..0740641 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_FB_TFT_ILI9320) += fb_ili9320.o obj-$(CONFIG_FB_TFT_ILI9325) += fb_ili9325.o obj-$(CONFIG_FB_TFT_ILI9340) += fb_ili9340.o obj-$(CONFIG_FB_TFT_ILI9341) += fb_ili9341.o +obj-$(CONFIG_FB_TFT_ILI9481) += fb_ili9481.o diff --git a/drivers/staging/fbtft/fb_ili9481.c b/drivers/staging/fbtft/fb_ili9481.c new file mode 100644 index 0000000..725157a --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9481.c @@ -0,0 +1,117 @@ +/* + * FB driver for the ILI9481 LCD Controller + * + * Copyright (c) 2014 Petr Olivka + * Copyright (c) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_ili9481" +#define WIDTH 320 +#define HEIGHT 480 + +static int default_init_sequence[] = { + + /* SLP_OUT - Sleep out */ + -1, 0x11, + -2, 50, + /* Power setting */ + -1, 0xD0, 0x07, 0x42, 0x18, + /* VCOM */ + -1, 0xD1, 0x00, 0x07, 0x10, + /* Power setting for norm. mode */ + -1, 0xD2, 0x01, 0x02, + /* Panel driving setting */ + -1, 0xC0, 0x10, 0x3B, 0x00, 0x02, 0x11, + /* Frame rate & inv. */ + -1, 0xC5, 0x03, + /* Pixel format */ + -1, 0x3A, 0x55, + /* Gamma */ + -1, 0xC8, 0x00, 0x32, 0x36, 0x45, 0x06, 0x16, + 0x37, 0x75, 0x77, 0x54, 0x0C, 0x00, + /* DISP_ON */ + -1, 0x29, + -3 +}; + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* column address */ + write_reg(par, 0x2a, xs >> 8, xs & 0xff, xe >> 8, xe & 0xff); + + /* row adress */ + write_reg(par, 0x2b, ys >> 8, ys & 0xff, ye >> 8, ye & 0xff); + + /* memory write */ + write_reg(par, 0x2c); +} + +#define HFLIP 0x01 +#define VFLIP 0x02 +#define ROWxCOL 0x20 +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 270: + write_reg(par, 0x36, ROWxCOL | HFLIP | VFLIP | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, VFLIP | (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, ROWxCOL | (par->bgr << 3)); + break; + default: + write_reg(par, 0x36, HFLIP | (par->bgr << 3)); + break; + } + + return 0; +} + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .init_sequence = default_init_sequence, + .fbtftops = { + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9481", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9481"); +MODULE_ALIAS("platform:ili9481"); + +MODULE_DESCRIPTION("FB driver for the ILI9481 LCD Controller"); +MODULE_AUTHOR("Petr Olivka"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 8d64b032aa71963da8e69ab2780947207c36a799 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:20 +0100 Subject: staging: fbtft: add fb_ili9486 driver This commit adds the fb_ili9486 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 86a1bee..ca73537 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -67,3 +67,9 @@ config FB_TFT_ILI9481 depends on FB_TFT help Generic Framebuffer support for ILI9481 + +config FB_TFT_ILI9486 + tristate "FB driver for the ILI9486 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ILI9486 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 0740641..8e633cf 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_FB_TFT_ILI9325) += fb_ili9325.o obj-$(CONFIG_FB_TFT_ILI9340) += fb_ili9340.o obj-$(CONFIG_FB_TFT_ILI9341) += fb_ili9341.o obj-$(CONFIG_FB_TFT_ILI9481) += fb_ili9481.o +obj-$(CONFIG_FB_TFT_ILI9486) += fb_ili9486.o diff --git a/drivers/staging/fbtft/fb_ili9486.c b/drivers/staging/fbtft/fb_ili9486.c new file mode 100644 index 0000000..95b8999 --- /dev/null +++ b/drivers/staging/fbtft/fb_ili9486.c @@ -0,0 +1,121 @@ +/* + * FB driver for the ILI9486 LCD Controller + * + * Copyright (C) 2014 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_ili9486" +#define WIDTH 320 +#define HEIGHT 480 + + +/* this init sequence matches PiScreen */ +static int default_init_sequence[] = { + /* Interface Mode Control */ + -1, 0xb0, 0x0, + /* Sleep OUT */ + -1, 0x11, + -2, 250, + /* Interface Pixel Format */ + -1, 0x3A, 0x55, + /* Power Control 3 */ + -1, 0xC2, 0x44, + /* VCOM Control 1 */ + -1, 0xC5, 0x00, 0x00, 0x00, 0x00, + /* PGAMCTRL(Positive Gamma Control) */ + -1, 0xE0, 0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, + 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00, + /* NGAMCTRL(Negative Gamma Control) */ + -1, 0xE1, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, + 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00, + /* Digital Gamma Control 1 */ + -1, 0xE2, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, + 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00, + /* Sleep OUT */ + -1, 0x11, + /* Display ON */ + -1, 0x29, + /* end marker */ + -3 +}; + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address */ + write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF); + + /* Row adress */ + write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, 0x80 | (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, 0x20 | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, 0x40 | (par->bgr << 3)); + break; + case 270: + write_reg(par, 0x36, 0xE0 | (par->bgr << 3)); + break; + default: + break; + } + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .init_sequence = default_init_sequence, + .fbtftops = { + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9486", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ili9486"); +MODULE_ALIAS("platform:ili9486"); + +MODULE_DESCRIPTION("FB driver for the ILI9486 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 39c39072436f6910d5e48d97d17a1b3a4eada220 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:21 +0100 Subject: staging: fbtft: add fb_pcd8544 driver This commit adds the fb_pcd8544 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index ca73537..fc1c76a 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -73,3 +73,9 @@ config FB_TFT_ILI9486 depends on FB_TFT help Generic Framebuffer support for ILI9486 + +config FB_TFT_PCD8544 + tristate "FB driver for the PCD8544 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for PCD8544 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 8e633cf..d7b9409 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_FB_TFT_ILI9340) += fb_ili9340.o obj-$(CONFIG_FB_TFT_ILI9341) += fb_ili9341.o obj-$(CONFIG_FB_TFT_ILI9481) += fb_ili9481.o obj-$(CONFIG_FB_TFT_ILI9486) += fb_ili9486.o +obj-$(CONFIG_FB_TFT_PCD8544) += fb_pcd8544.o diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c new file mode 100644 index 0000000..678ab8e --- /dev/null +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -0,0 +1,177 @@ +/* + * FB driver for the PCD8544 LCD Controller + * + * The display is monochrome and the video memory is RGB565. + * Any pixel value except 0 turns the pixel on. + * + * Copyright (C) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_pcd8544" +#define WIDTH 84 +#define HEIGHT 48 +#define TXBUFLEN 84*6 +#define DEFAULT_GAMMA "40" /* gamma is used to control contrast in this driver */ + +static unsigned tc = 0; +module_param(tc, uint, 0); +MODULE_PARM_DESC(tc, "TC[1:0] Temperature coefficient: 0-3 (default: 0)"); + +static unsigned bs = 4; +module_param(bs, uint, 0); +MODULE_PARM_DESC(bs, "BS[2:0] Bias voltage level: 0-7 (default: 4)"); + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* Function set */ + write_reg(par, 0x21); /* 5:1 1 + 2:0 PD - Powerdown control: chip is active + 1:0 V - Entry mode: horizontal addressing + 0:1 H - Extended instruction set control: extended + */ + + /* H=1 Temperature control */ + write_reg(par, 0x04 | (tc & 0x3)); /* + 2:1 1 + 1:x TC1 - Temperature Coefficient: 0x10 + 0:x TC0 + */ + + /* H=1 Bias system */ + write_reg(par, 0x10 | (bs & 0x7)); /* + 4:1 1 + 3:0 0 + 2:x BS2 - Bias System + 1:x BS1 + 0:x BS0 + */ + + /* Function set */ + write_reg(par, 0x22); /* 5:1 1 + 2:0 PD - Powerdown control: chip is active + 1:1 V - Entry mode: vertical addressing + 0:0 H - Extended instruction set control: basic + */ + + /* H=0 Display control */ + write_reg(par, 0x08 | 4); /* + 3:1 1 + 2:1 D - DE: 10=normal mode + 1:0 0 + 0:0 E + */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* H=0 Set X address of RAM */ + write_reg(par, 0x80); /* 7:1 1 + 6-0: X[6:0] - 0x00 + */ + + /* H=0 Set Y address of RAM */ + write_reg(par, 0x40); /* 7:0 0 + 6:1 1 + 2-0: Y[2:0] - 0x0 + */ +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16 = (u16 *)par->info->screen_base; + u8 *buf = par->txbuf.buf; + int x, y, i; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + for (x=0;x<84;x++) { + for (y=0;y<6;y++) { + *buf = 0x00; + for (i=0;i<8;i++) { + *buf |= (vmem16[(y*8+i)*84+x] ? 1 : 0) << i; + } + buf++; + } + } + + /* Write data */ + gpio_set_value(par->gpio.dc, 1); + ret = par->fbtftops.write(par, par->txbuf.buf, 6*84); + if (ret < 0) + dev_err(par->info->device, "%s: write failed and returned: %d\n", __func__, ret); + + return ret; +} + +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + curves[0] &= 0x7F; + + write_reg(par, 0x23); /* turn on extended instruction set */ + write_reg(par, 0x80 | curves[0]); + write_reg(par, 0x22); /* turn off extended instruction set */ + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .txbuflen = TXBUFLEN, + .gamma_num = 1, + .gamma_len = 1, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .write_vmem = write_vmem, + .set_gamma = set_gamma, + }, + .backlight = 1, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "philips,pdc8544", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("spi:pdc8544"); + +MODULE_DESCRIPTION("FB driver for the PCD8544 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From d8a53a9d0b4fa1ba0eb37a09341f74b0295ffd67 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:22 +0100 Subject: staging: fbtft: add fb_ra8875 driver This commit adds the fb_ra8875 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index fc1c76a..d66281e 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -79,3 +79,9 @@ config FB_TFT_PCD8544 depends on FB_TFT help Generic Framebuffer support for PCD8544 + +config FB_TFT_RA8875 + tristate "FB driver for the RA8875 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for RA8875 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index d7b9409..d9aa2b3 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_FB_TFT_ILI9341) += fb_ili9341.o obj-$(CONFIG_FB_TFT_ILI9481) += fb_ili9481.o obj-$(CONFIG_FB_TFT_ILI9486) += fb_ili9486.o obj-$(CONFIG_FB_TFT_PCD8544) += fb_pcd8544.o +obj-$(CONFIG_FB_TFT_RA8875) += fb_ra8875.o diff --git a/drivers/staging/fbtft/fb_ra8875.c b/drivers/staging/fbtft/fb_ra8875.c new file mode 100644 index 0000000..c323c06 --- /dev/null +++ b/drivers/staging/fbtft/fb_ra8875.c @@ -0,0 +1,331 @@ +/****************************************************************************** + + ProjectName: FBTFT driver ***** ***** + for the RA8875 LCD Controller * * ************ + * ** ** * * + Copyright © by Pf@nne & NOTRO * * * * * **** * + * * * * * * * + Last modification by: * * * * **** * + - Pf@nne (pf@nne-mail.de) * * ***** * + * * * ******* + ***** * * + Date : 10.06.2014 * * + Version : V1.13 ***** + Revison : 5 + +******************************************************************************* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include +#include "fbtft.h" + +#define DRVNAME "fb_ra8875" + +static int write_spi(struct fbtft_par *par, void *buf, size_t len) +{ + struct spi_transfer t = { + .tx_buf = buf, + .len = len, + .speed_hz = 1000000, + }; + struct spi_message m; + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + if (!par->spi) { + dev_err(par->info->device, + "%s: par->spi is unexpectedly NULL\n", __func__); + return -1; + } + + spi_message_init(&m); + if (par->txbuf.dma && buf == par->txbuf.buf) { + t.tx_dma = par->txbuf.dma; + m.is_dma_mapped = 1; + } + spi_message_add_tail(&t, &m); + return spi_sync(par->spi, &m); +} + +static int init_display(struct fbtft_par *par) +{ + gpio_set_value(par->gpio.dc, 1); + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "%s()\n", __func__); + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "display size %dx%d\n", par->info->var.xres, par->info->var.yres); + + par->fbtftops.reset(par); + + if ((par->info->var.xres == 320) && (par->info->var.yres == 240)) { + /* PLL clock frequency */ + write_reg(par, 0x88 , 0x0A); + write_reg(par, 0x89 , 0x02); + mdelay(10); + /* color deep / MCU Interface */ + write_reg(par, 0x10 , 0x0C); + /* pixel clock period */ + write_reg(par, 0x04 , 0x03); + mdelay(1); + /* horizontal settings */ + write_reg(par, 0x14 , 0x27); + write_reg(par, 0x15 , 0x00); + write_reg(par, 0x16 , 0x05); + write_reg(par, 0x17 , 0x04); + write_reg(par, 0x18 , 0x03); + /* vertical settings */ + write_reg(par, 0x19 , 0xEF); + write_reg(par, 0x1A , 0x00); + write_reg(par, 0x1B , 0x05); + write_reg(par, 0x1C , 0x00); + write_reg(par, 0x1D , 0x0E); + write_reg(par, 0x1E , 0x00); + write_reg(par, 0x1F , 0x02); + } else if ((par->info->var.xres == 480) && (par->info->var.yres == 272)) { + /* PLL clock frequency */ + write_reg(par, 0x88 , 0x0A); + write_reg(par, 0x89 , 0x02); + mdelay(10); + /* color deep / MCU Interface */ + write_reg(par, 0x10 , 0x0C); + /* pixel clock period */ + write_reg(par, 0x04 , 0x82); + mdelay(1); + /* horizontal settings */ + write_reg(par, 0x14 , 0x3B); + write_reg(par, 0x15 , 0x00); + write_reg(par, 0x16 , 0x01); + write_reg(par, 0x17 , 0x00); + write_reg(par, 0x18 , 0x05); + /* vertical settings */ + write_reg(par, 0x19 , 0x0F); + write_reg(par, 0x1A , 0x01); + write_reg(par, 0x1B , 0x02); + write_reg(par, 0x1C , 0x00); + write_reg(par, 0x1D , 0x07); + write_reg(par, 0x1E , 0x00); + write_reg(par, 0x1F , 0x09); + } else if ((par->info->var.xres == 640) && (par->info->var.yres == 480)) { + /* PLL clock frequency */ + write_reg(par, 0x88 , 0x0B); + write_reg(par, 0x89 , 0x02); + mdelay(10); + /* color deep / MCU Interface */ + write_reg(par, 0x10 , 0x0C); + /* pixel clock period */ + write_reg(par, 0x04 , 0x01); + mdelay(1); + /* horizontal settings */ + write_reg(par, 0x14 , 0x4F); + write_reg(par, 0x15 , 0x05); + write_reg(par, 0x16 , 0x0F); + write_reg(par, 0x17 , 0x01); + write_reg(par, 0x18 , 0x00); + /* vertical settings */ + write_reg(par, 0x19 , 0xDF); + write_reg(par, 0x1A , 0x01); + write_reg(par, 0x1B , 0x0A); + write_reg(par, 0x1C , 0x00); + write_reg(par, 0x1D , 0x0E); + write_reg(par, 0x1E , 0x00); + write_reg(par, 0x1F , 0x01); + } else if ((par->info->var.xres == 800) && (par->info->var.yres == 480)) { + /* PLL clock frequency */ + write_reg(par, 0x88 , 0x0B); + write_reg(par, 0x89 , 0x02); + mdelay(10); + /* color deep / MCU Interface */ + write_reg(par, 0x10 , 0x0C); + /* pixel clock period */ + write_reg(par, 0x04 , 0x81); + mdelay(1); + /* horizontal settings */ + write_reg(par, 0x14 , 0x63); + write_reg(par, 0x15 , 0x03); + write_reg(par, 0x16 , 0x03); + write_reg(par, 0x17 , 0x02); + write_reg(par, 0x18 , 0x00); + /* vertical settings */ + write_reg(par, 0x19 , 0xDF); + write_reg(par, 0x1A , 0x01); + write_reg(par, 0x1B , 0x14); + write_reg(par, 0x1C , 0x00); + write_reg(par, 0x1D , 0x06); + write_reg(par, 0x1E , 0x00); + write_reg(par, 0x1F , 0x01); + } else { + dev_err(par->info->device, "display size is not supported!!"); + return -1; + } + + /* PWM clock */ + write_reg(par, 0x8a , 0x81); + write_reg(par, 0x8b , 0xFF); + mdelay(10); + + /* Display ON */ + write_reg(par, 0x01 , 0x80); + mdelay(10); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Set_Active_Window */ + write_reg(par, 0x30 , xs & 0x00FF); + write_reg(par, 0x31 , (xs & 0xFF00) >> 8); + write_reg(par, 0x32 , ys & 0x00FF); + write_reg(par, 0x33 , (ys & 0xFF00) >> 8); + write_reg(par, 0x34 , (xs+xe) & 0x00FF); + write_reg(par, 0x35 , ((xs+xe) & 0xFF00) >> 8); + write_reg(par, 0x36 , (ys+ye) & 0x00FF); + write_reg(par, 0x37 , ((ys+ye) & 0xFF00) >> 8); + + /* Set_Memory_Write_Cursor */ + write_reg(par, 0x46, xs & 0xff); + write_reg(par, 0x47, (xs >> 8) & 0x03); + write_reg(par, 0x48, ys & 0xff); + write_reg(par, 0x49, (ys >> 8) & 0x01); + + write_reg(par, 0x02); +} + +static void write_reg8_bus8(struct fbtft_par *par, int len, ...) +{ + va_list args; + int i, ret; + u8 *buf = (u8 *)par->buf; + + /* slow down spi-speed for writing registers */ + par->fbtftops.write = write_spi; + + if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { + va_start(args, len); + for (i = 0; i < len; i++) + buf[i] = (u8)va_arg(args, unsigned int); + va_end(args); + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, par->info->device, + u8, buf, len, "%s: ", __func__); + } + + va_start(args, len); + *buf++ = 0x80; + *buf = (u8)va_arg(args, unsigned int); + ret = par->fbtftops.write(par, par->buf, 2); + if (ret < 0) { + va_end(args); + dev_err(par->info->device, "%s: write() failed and returned %dn", + __func__, ret); + return; + } + len--; + + udelay(100); + + if (len) { + buf = (u8 *)par->buf; + *buf++ = 0x00; + i = len; + while (i--) + *buf++ = (u8)va_arg(args, unsigned int); + + ret = par->fbtftops.write(par, par->buf, len + 1); + if (ret < 0) { + va_end(args); + dev_err(par->info->device, "%s: write() failed and returned %dn", + __func__, ret); + return; + } + } + va_end(args); + + /* restore user spi-speed */ + par->fbtftops.write = fbtft_write_spi; + udelay(100); +} + +static int write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16; + u16 *txbuf16 = (u16 *)par->txbuf.buf; + size_t remain; + size_t to_copy; + size_t tx_array_size; + int i; + int ret = 0; + size_t startbyte_size = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", + __func__, offset, len); + + remain = len / 2; + vmem16 = (u16 *)(par->info->screen_base + offset); + tx_array_size = par->txbuf.len / 2; + txbuf16 = (u16 *)(par->txbuf.buf + 1); + tx_array_size -= 2; + *(u8 *)(par->txbuf.buf) = 0x00; + startbyte_size = 1; + + while (remain) { + to_copy = remain > tx_array_size ? tx_array_size : remain; + dev_dbg(par->info->device, " to_copy=%zu, remain=%zu\n", + to_copy, remain - to_copy); + + for (i = 0; i < to_copy; i++) + txbuf16[i] = cpu_to_be16(vmem16[i]); + + vmem16 = vmem16 + to_copy; + ret = par->fbtftops.write(par, par->txbuf.buf, + startbyte_size + to_copy * 2); + if (ret < 0) + return ret; + remain -= to_copy; + } + + return ret; +} + +static struct fbtft_display display = { + .regwidth = 8, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .write_register = write_reg8_bus8, + .write_vmem = write_vmem16_bus8, + .write = write_spi, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "raio,ra8875", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ra8875"); +MODULE_ALIAS("platform:ra8875"); + +MODULE_DESCRIPTION("FB driver for the RA8875 LCD Controller"); +MODULE_AUTHOR("Pf@nne"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 910968f7123156fc862b246ec3d5b5fb4038f6e4 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:23 +0100 Subject: staging: fbtft: add fb_s6d02a1 driver This commit adds the fb_s6d02a1 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index d66281e..34676db 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -85,3 +85,9 @@ config FB_TFT_RA8875 depends on FB_TFT help Generic Framebuffer support for RA8875 + +config FB_TFT_S6D02A1 + tristate "FB driver for the S6D02A1 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for S6D02A1 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index d9aa2b3..e349e7f 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_FB_TFT_ILI9481) += fb_ili9481.o obj-$(CONFIG_FB_TFT_ILI9486) += fb_ili9486.o obj-$(CONFIG_FB_TFT_PCD8544) += fb_pcd8544.o obj-$(CONFIG_FB_TFT_RA8875) += fb_ra8875.o +obj-$(CONFIG_FB_TFT_S6D02A1) += fb_s6d02a1.o diff --git a/drivers/staging/fbtft/fb_s6d02a1.c b/drivers/staging/fbtft/fb_s6d02a1.c new file mode 100644 index 0000000..e412a42 --- /dev/null +++ b/drivers/staging/fbtft/fb_s6d02a1.c @@ -0,0 +1,168 @@ +/* + * FB driver for the S6D02A1 LCD Controller + * + * Based on fb_st7735r.c by Noralf Tronnes + * Init code from UTFT library by Henning Karlsen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_s6d02a1" + +static int default_init_sequence[] = { + + -1, 0xf0, 0x5a, 0x5a, + + -1, 0xfc, 0x5a, 0x5a, + + -1, 0xfa, 0x02, 0x1f, 0x00, 0x10, 0x22, 0x30, 0x38, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3d, 0x02, 0x01, + + -1, 0xfb, 0x21, 0x00, 0x02, 0x04, 0x07, 0x0a, 0x0b, 0x0c, 0x0c, 0x16, 0x1e, 0x30, 0x3f, 0x01, 0x02, + + /* power setting sequence */ + -1, 0xfd, 0x00, 0x00, 0x00, 0x17, 0x10, 0x00, 0x01, 0x01, 0x00, 0x1f, 0x1f, + + -1, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x07, 0x00, 0x3C, 0x36, 0x00, 0x3C, 0x36, 0x00, + + -1, 0xf5, 0x00, 0x70, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x66, 0x06, + + -1, 0xf6, 0x02, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x01, 0x00, + + -1, 0xf2, 0x00, 0x01, 0x03, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x08, 0x08, + + -1, 0xf8, 0x11, + + -1, 0xf7, 0xc8, 0x20, 0x00, 0x00, + + -1, 0xf3, 0x00, 0x00, + + -1, 0x11, + -2, 50, + + -1, 0xf3, 0x00, 0x01, + -2, 50, + -1, 0xf3, 0x00, 0x03, + -2, 50, + -1, 0xf3, 0x00, 0x07, + -2, 50, + -1, 0xf3, 0x00, 0x0f, + -2, 50, + + -1, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x07, 0x00, 0x3C, 0x36, 0x00, 0x3C, 0x36, 0x00, + -2, 50, + + -1, 0xf3, 0x00, 0x1f, + -2, 50, + -1, 0xf3, 0x00, 0x7f, + -2, 50, + + -1, 0xf3, 0x00, 0xff, + -2, 50, + + -1, 0xfd, 0x00, 0x00, 0x00, 0x17, 0x10, 0x00, 0x00, 0x01, 0x00, 0x16, 0x16, + + -1, 0xf4, 0x00, 0x09, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x07, 0x00, 0x3C, 0x36, 0x00, 0x3C, 0x36, 0x00, + + /* initializing sequence */ + + -1, 0x36, 0x08, + + -1, 0x35, 0x00, + + -1, 0x3a, 0x05, + + /* gamma setting sequence */ + -1, 0x26, 0x01, /* preset gamma curves, possible values 0x01, 0x02, 0x04, 0x08 */ + + -2, 150, + -1, 0x29, + -1, 0x2c, + /* end marker */ + -3 + +}; + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address */ + write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF); + + /* Row adress */ + write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +#define MY (1 << 7) +#define MX (1 << 6) +#define MV (1 << 5) +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* MADCTL - Memory data access control + RGB/BGR: + 1. Mode selection pin SRGB + RGB H/W pin for color filter setting: 0=RGB, 1=BGR + 2. MADCTL RGB bit + RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR */ + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, MX | MY | (par->bgr << 3)); + break; + case 270: + write_reg(par, 0x36, MY | MV | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, MX | MV | (par->bgr << 3)); + break; + } + + return 0; +} + +static struct fbtft_display display = { + .regwidth = 8, + .width = 128, + .height = 160, + .init_sequence = default_init_sequence, + .fbtftops = { + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "samsung,s6d02a1", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:s6d02a1"); +MODULE_ALIAS("platform:s6d02a1"); + +MODULE_DESCRIPTION("FB driver for the S6D02A1 LCD Controller"); +MODULE_AUTHOR("WOLFGANG BUENING"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 7a39e9654b1a6048f679331f121f8a1841c0e09d Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:24 +0100 Subject: staging: fbtft: add fb_s6d1121 driver This commit adds the fb_s6d1121 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 34676db..4fd9cfd 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -91,3 +91,9 @@ config FB_TFT_S6D02A1 depends on FB_TFT help Generic Framebuffer support for S6D02A1 + +config FB_TFT_S6D1121 + tristate "FB driver for the S6D1211 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for S6D1121 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index e349e7f..48b3ce1 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_FB_TFT_ILI9486) += fb_ili9486.o obj-$(CONFIG_FB_TFT_PCD8544) += fb_pcd8544.o obj-$(CONFIG_FB_TFT_RA8875) += fb_ra8875.o obj-$(CONFIG_FB_TFT_S6D02A1) += fb_s6d02a1.o +obj-$(CONFIG_FB_TFT_S6D1121) += fb_s6d1121.o diff --git a/drivers/staging/fbtft/fb_s6d1121.c b/drivers/staging/fbtft/fb_s6d1121.c new file mode 100644 index 0000000..1ef8c1a --- /dev/null +++ b/drivers/staging/fbtft/fb_s6d1121.c @@ -0,0 +1,208 @@ +/* + * FB driver for the S6D1121 LCD Controller + * + * Copyright (C) 2013 Roman Rolinsky + * + * Based on fb_ili9325.c by Noralf Tronnes + * Based on ili9325.c by Jeroen Domburg + * Init code from UTFT library by Henning Karlsen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_s6d1121" +#define WIDTH 240 +#define HEIGHT 320 +#define BPP 16 +#define FPS 20 +#define DEFAULT_GAMMA "26 09 24 2C 1F 23 24 25 22 26 25 23 0D 00\n" \ + "1C 1A 13 1D 0B 11 12 10 13 15 36 19 00 0D" + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + /* Initialization sequence from Lib_UTFT */ + + write_reg(par, 0x0011, 0x2004); + write_reg(par, 0x0013, 0xCC00); + write_reg(par, 0x0015, 0x2600); + write_reg(par, 0x0014, 0x252A); + write_reg(par, 0x0012, 0x0033); + write_reg(par, 0x0013, 0xCC04); + write_reg(par, 0x0013, 0xCC06); + write_reg(par, 0x0013, 0xCC4F); + write_reg(par, 0x0013, 0x674F); + write_reg(par, 0x0011, 0x2003); + write_reg(par, 0x0016, 0x0007); + write_reg(par, 0x0002, 0x0013); + write_reg(par, 0x0003, 0x0003); + write_reg(par, 0x0001, 0x0127); + write_reg(par, 0x0008, 0x0303); + write_reg(par, 0x000A, 0x000B); + write_reg(par, 0x000B, 0x0003); + write_reg(par, 0x000C, 0x0000); + write_reg(par, 0x0041, 0x0000); + write_reg(par, 0x0050, 0x0000); + write_reg(par, 0x0060, 0x0005); + write_reg(par, 0x0070, 0x000B); + write_reg(par, 0x0071, 0x0000); + write_reg(par, 0x0078, 0x0000); + write_reg(par, 0x007A, 0x0000); + write_reg(par, 0x0079, 0x0007); + write_reg(par, 0x0007, 0x0051); + write_reg(par, 0x0007, 0x0053); + write_reg(par, 0x0079, 0x0000); + + write_reg(par, 0x0022); /* Write Data to GRAM */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + switch (par->info->var.rotate) { + /* R20h = Horizontal GRAM Start Address */ + /* R21h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0020, xs); + write_reg(par, 0x0021, ys); + break; + case 180: + write_reg(par, 0x0020, WIDTH - 1 - xs); + write_reg(par, 0x0021, HEIGHT - 1 - ys); + break; + case 270: + write_reg(par, 0x0020, WIDTH - 1 - ys); + write_reg(par, 0x0021, xs); + break; + case 90: + write_reg(par, 0x0020, ys); + write_reg(par, 0x0021, HEIGHT - 1 - xs); + break; + } + write_reg(par, 0x0022); /* Write Data to GRAM */ +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + /* AM: GRAM update direction */ + case 0: + write_reg(par, 0x03, 0x0003 | (par->bgr << 12)); + break; + case 180: + write_reg(par, 0x03, 0x0000 | (par->bgr << 12)); + break; + case 270: + write_reg(par, 0x03, 0x000A | (par->bgr << 12)); + break; + case 90: + write_reg(par, 0x03, 0x0009 | (par->bgr << 12)); + break; + } + + return 0; +} + +/* + Gamma string format: + PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 PKP6 PKP7 PKP8 PKP9 PKP10 PKP11 VRP0 VRP1 + PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 PKN6 PKN7 PRN8 PRN9 PRN10 PRN11 VRN0 VRN1 +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, + 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, + 0b11111, 0b11111, + 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, + 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, 0b111111, + 0b11111, 0b11111 }; + int i, j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < 2; i++) + for (j = 0; j < 14; j++) + CURVE(i, j) &= mask[i*par->gamma.num_values + j]; + + write_reg(par, 0x0030, CURVE(0, 1) << 8 | CURVE(0, 0)); + write_reg(par, 0x0031, CURVE(0, 3) << 8 | CURVE(0, 2)); + write_reg(par, 0x0032, CURVE(0, 5) << 8 | CURVE(0, 3)); + write_reg(par, 0x0033, CURVE(0, 7) << 8 | CURVE(0, 6)); + write_reg(par, 0x0034, CURVE(0, 9) << 8 | CURVE(0, 8)); + write_reg(par, 0x0035, CURVE(0, 11) << 8 | CURVE(0, 10)); + + write_reg(par, 0x0036, CURVE(1, 1) << 8 | CURVE(1, 0)); + write_reg(par, 0x0037, CURVE(1, 3) << 8 | CURVE(1, 2)); + write_reg(par, 0x0038, CURVE(1, 5) << 8 | CURVE(1, 4)); + write_reg(par, 0x0039, CURVE(1, 7) << 8 | CURVE(1, 6)); + write_reg(par, 0x003A, CURVE(1, 9) << 8 | CURVE(1, 8)); + write_reg(par, 0x003B, CURVE(1, 11) << 8 | CURVE(1, 10)); + + write_reg(par, 0x003C, CURVE(0, 13) << 8 | CURVE(0, 12)); + write_reg(par, 0x003D, CURVE(1, 13) << 8 | CURVE(1, 12)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .bpp = BPP, + .fps = FPS, + .gamma_num = 2, + .gamma_len = 14, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "samsung,s6d1121", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:s6d1121"); +MODULE_ALIAS("platform:s6d1121"); + +MODULE_DESCRIPTION("FB driver for the S6D1121 LCD Controller"); +MODULE_AUTHOR("Roman Rolinsky"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 5dc5e4fb117343d321bef51e5f417fa59c593391 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:25 +0100 Subject: staging: fbtft: add fb_ssd1289 driver This commit adds the fb_ssd1289 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 4fd9cfd..05e8571 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -97,3 +97,9 @@ config FB_TFT_S6D1121 depends on FB_TFT help Generic Framebuffer support for S6D1121 + +config FB_TFT_SSD1289 + tristate "FB driver for the SSD1289 LCD Controller" + depends on FB_TFT + help + Framebuffer support for SSD1289 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 48b3ce1..ea5fa1e 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_FB_TFT_PCD8544) += fb_pcd8544.o obj-$(CONFIG_FB_TFT_RA8875) += fb_ra8875.o obj-$(CONFIG_FB_TFT_S6D02A1) += fb_s6d02a1.o obj-$(CONFIG_FB_TFT_S6D1121) += fb_s6d1121.o +obj-$(CONFIG_FB_TFT_SSD1289) += fb_ssd1289.o diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c new file mode 100644 index 0000000..ef46fbc --- /dev/null +++ b/drivers/staging/fbtft/fb_ssd1289.c @@ -0,0 +1,206 @@ +/* + * FB driver for the SSD1289 LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * Init sequence taken from ITDB02_Graph16.cpp - (C)2010-2011 Henning Karlsen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_ssd1289" +#define WIDTH 240 +#define HEIGHT 320 +#define DEFAULT_GAMMA "02 03 2 5 7 7 4 2 4 2\n" \ + "02 03 2 5 7 5 4 2 4 2" + +static unsigned reg11 = 0x6040; +module_param(reg11, uint, 0); +MODULE_PARM_DESC(reg11, "Register 11h value"); + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + write_reg(par, 0x00, 0x0001); + write_reg(par, 0x03, 0xA8A4); + write_reg(par, 0x0C, 0x0000); + write_reg(par, 0x0D, 0x080C); + write_reg(par, 0x0E, 0x2B00); + write_reg(par, 0x1E, 0x00B7); + write_reg(par, 0x01, + (1 << 13) | (par->bgr << 11) | (1 << 9) | (HEIGHT - 1)); + write_reg(par, 0x02, 0x0600); + write_reg(par, 0x10, 0x0000); + write_reg(par, 0x05, 0x0000); + write_reg(par, 0x06, 0x0000); + write_reg(par, 0x16, 0xEF1C); + write_reg(par, 0x17, 0x0003); + write_reg(par, 0x07, 0x0233); + write_reg(par, 0x0B, 0x0000); + write_reg(par, 0x0F, 0x0000); + write_reg(par, 0x41, 0x0000); + write_reg(par, 0x42, 0x0000); + write_reg(par, 0x48, 0x0000); + write_reg(par, 0x49, 0x013F); + write_reg(par, 0x4A, 0x0000); + write_reg(par, 0x4B, 0x0000); + write_reg(par, 0x44, 0xEF00); + write_reg(par, 0x45, 0x0000); + write_reg(par, 0x46, 0x013F); + write_reg(par, 0x23, 0x0000); + write_reg(par, 0x24, 0x0000); + write_reg(par, 0x25, 0x8000); + write_reg(par, 0x4f, 0x0000); + write_reg(par, 0x4e, 0x0000); + write_reg(par, 0x22); + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + switch (par->info->var.rotate) { + /* R4Eh - Set GDDRAM X address counter */ + /* R4Fh - Set GDDRAM Y address counter */ + case 0: + write_reg(par, 0x4e, xs); + write_reg(par, 0x4f, ys); + break; + case 180: + write_reg(par, 0x4e, par->info->var.xres - 1 - xs); + write_reg(par, 0x4f, par->info->var.yres - 1 - ys); + break; + case 270: + write_reg(par, 0x4e, par->info->var.yres - 1 - ys); + write_reg(par, 0x4f, xs); + break; + case 90: + write_reg(par, 0x4e, ys); + write_reg(par, 0x4f, par->info->var.xres - 1 - xs); + break; + } + + /* R22h - RAM data write */ + write_reg(par, 0x22); +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + if (par->fbtftops.init_display != init_display) { + /* don't risk messing up register 11h */ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "%s: skipping since custom init_display() is used\n", + __func__); + return 0; + } + + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x11, reg11 | 0b110000); + break; + case 270: + write_reg(par, 0x11, reg11 | 0b101000); + break; + case 180: + write_reg(par, 0x11, reg11 | 0b000000); + break; + case 90: + write_reg(par, 0x11, reg11 | 0b011000); + break; + } + + return 0; +} + +/* + Gamma string format: + VRP0 VRP1 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 PKP5 + VRN0 VRN1 PRN0 PRN1 PKN0 PKN1 PKN2 PKN3 PKN4 PKN5 +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long mask[] = { + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111, + 0b11111, 0b11111, 0b111, 0b111, 0b111, + 0b111, 0b111, 0b111, 0b111, 0b111 }; + int i, j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < 2; i++) + for (j = 0; j < 10; j++) + CURVE(i, j) &= mask[i*par->gamma.num_values + j]; + + write_reg(par, 0x0030, CURVE(0, 5) << 8 | CURVE(0, 4)); + write_reg(par, 0x0031, CURVE(0, 7) << 8 | CURVE(0, 6)); + write_reg(par, 0x0032, CURVE(0, 9) << 8 | CURVE(0, 8)); + write_reg(par, 0x0033, CURVE(0, 3) << 8 | CURVE(0, 2)); + write_reg(par, 0x0034, CURVE(1, 5) << 8 | CURVE(1, 4)); + write_reg(par, 0x0035, CURVE(1, 7) << 8 | CURVE(1, 6)); + write_reg(par, 0x0036, CURVE(1, 9) << 8 | CURVE(1, 8)); + write_reg(par, 0x0037, CURVE(1, 3) << 8 | CURVE(1, 2)); + write_reg(par, 0x003A, CURVE(0, 1) << 8 | CURVE(0, 0)); + write_reg(par, 0x003B, CURVE(1, 1) << 8 | CURVE(1, 0)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = 2, + .gamma_len = 10, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1289", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ssd1289"); +MODULE_ALIAS("platform:ssd1289"); + +MODULE_DESCRIPTION("FB driver for the SSD1289 LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 39837b91583097316a8d31f0a30aacb7bfdac89b Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:26 +0100 Subject: staging: fbtft: add fb_ssd1306 driver This commit adds the fb_ssd1306 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 05e8571..3ae8259 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -103,3 +103,9 @@ config FB_TFT_SSD1289 depends on FB_TFT help Framebuffer support for SSD1289 + +config FB_TFT_SSD1306 + tristate "FB driver for the SSD1306 OLED Controller" + depends on FB_TFT + help + Framebuffer support for SSD1306 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index ea5fa1e..b612a4d 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -19,3 +19,4 @@ obj-$(CONFIG_FB_TFT_RA8875) += fb_ra8875.o obj-$(CONFIG_FB_TFT_S6D02A1) += fb_s6d02a1.o obj-$(CONFIG_FB_TFT_S6D1121) += fb_s6d1121.o obj-$(CONFIG_FB_TFT_SSD1289) += fb_ssd1289.o +obj-$(CONFIG_FB_TFT_SSD1306) += fb_ssd1306.o diff --git a/drivers/staging/fbtft/fb_ssd1306.c b/drivers/staging/fbtft/fb_ssd1306.c new file mode 100644 index 0000000..5ea195b --- /dev/null +++ b/drivers/staging/fbtft/fb_ssd1306.c @@ -0,0 +1,229 @@ +/* + * FB driver for the SSD1306 OLED Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_ssd1306" +#define WIDTH 128 +#define HEIGHT 64 + + +/* + write_reg() caveat: + + This doesn't work because D/C has to be LOW for both values: + write_reg(par, val1, val2); + + Do it like this: + write_reg(par, val1); + write_reg(par, val2); +*/ + +/* Init sequence taken from the Adafruit SSD1306 Arduino library */ +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + if (par->gamma.curves[0] == 0) { + mutex_lock(&par->gamma.lock); + if (par->info->var.yres == 64) + par->gamma.curves[0] = 0xCF; + else + par->gamma.curves[0] = 0x8F; + mutex_unlock(&par->gamma.lock); + } + + /* Set Display OFF */ + write_reg(par, 0xAE); + + /* Set Display Clock Divide Ratio/ Oscillator Frequency */ + write_reg(par, 0xD5); + write_reg(par, 0x80); + + /* Set Multiplex Ratio */ + write_reg(par, 0xA8); + if (par->info->var.yres == 64) + write_reg(par, 0x3F); + else + write_reg(par, 0x1F); + + /* Set Display Offset */ + write_reg(par, 0xD3); + write_reg(par, 0x0); + + /* Set Display Start Line */ + write_reg(par, 0x40 | 0x0); + + /* Charge Pump Setting */ + write_reg(par, 0x8D); + /* A[2] = 1b, Enable charge pump during display on */ + write_reg(par, 0x14); + + /* Set Memory Addressing Mode */ + write_reg(par, 0x20); + /* Vertical addressing mode */ + write_reg(par, 0x01); + + /*Set Segment Re-map */ + /* column address 127 is mapped to SEG0 */ + write_reg(par, 0xA0 | 0x1); + + /* Set COM Output Scan Direction */ + /* remapped mode. Scan from COM[N-1] to COM0 */ + write_reg(par, 0xC8); + + /* Set COM Pins Hardware Configuration */ + write_reg(par, 0xDA); + if (par->info->var.yres == 64) + /* A[4]=1b, Alternative COM pin configuration */ + write_reg(par, 0x12); + else + /* A[4]=0b, Sequential COM pin configuration */ + write_reg(par, 0x02); + + /* Set Pre-charge Period */ + write_reg(par, 0xD9); + write_reg(par, 0xF1); + + /* Set VCOMH Deselect Level */ + write_reg(par, 0xDB); + /* according to the datasheet, this value is out of bounds */ + write_reg(par, 0x40); + + /* Entire Display ON */ + /* Resume to RAM content display. Output follows RAM content */ + write_reg(par, 0xA4); + + /* Set Normal Display + 0 in RAM: OFF in display panel + 1 in RAM: ON in display panel */ + write_reg(par, 0xA6); + + /* Set Display ON */ + write_reg(par, 0xAF); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Set Lower Column Start Address for Page Addressing Mode */ + write_reg(par, 0x00 | 0x0); + /* Set Higher Column Start Address for Page Addressing Mode */ + write_reg(par, 0x10 | 0x0); + /* Set Display Start Line */ + write_reg(par, 0x40 | 0x0); +} + +static int blank(struct fbtft_par *par, bool on) +{ + fbtft_par_dbg(DEBUG_BLANK, par, "%s(blank=%s)\n", + __func__, on ? "true" : "false"); + + if (on) + write_reg(par, 0xAE); + else + write_reg(par, 0xAF); + return 0; +} + +/* Gamma is used to control Contrast */ +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + curves[0] &= 0xFF; + + /* Set Contrast Control for BANK0 */ + write_reg(par, 0x81); + write_reg(par, curves[0]); + + return 0; +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16 = (u16 *)par->info->screen_base; + u8 *buf = par->txbuf.buf; + int x, y, i; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + for (x = 0; x < par->info->var.xres; x++) { + for (y = 0; y < par->info->var.yres/8; y++) { + *buf = 0x00; + for (i = 0; i < 8; i++) + *buf |= (vmem16[(y*8+i)*par->info->var.xres+x] ? 1 : 0) << i; + buf++; + } + } + + /* Write data */ + gpio_set_value(par->gpio.dc, 1); + ret = par->fbtftops.write(par, par->txbuf.buf, + par->info->var.xres*par->info->var.yres/8); + if (ret < 0) + dev_err(par->info->device, + "%s: write failed and returned: %d\n", __func__, ret); + + return ret; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = 1, + .gamma_len = 1, + .gamma = "00", + .fbtftops = { + .write_vmem = write_vmem, + .init_display = init_display, + .set_addr_win = set_addr_win, + .blank = blank, + .set_gamma = set_gamma, + }, +}; + + +FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1306", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ssd1306"); +MODULE_ALIAS("platform:ssd1306"); + +MODULE_DESCRIPTION("SSD1306 OLED Driver"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From dc746091027bf1eafcc72d295fbc34aa2376add3 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:27 +0100 Subject: staging: fbtft: add fb_ssd1331 driver This commit adds the fb_ssd1331 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 3ae8259..f1e4832 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -109,3 +109,9 @@ config FB_TFT_SSD1306 depends on FB_TFT help Framebuffer support for SSD1306 + +config FB_TFT_SSD1331 + tristate "FB driver for the SSD1331 LCD Controller" + depends on FB_TFT + help + Framebuffer support for SSD1331 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index b612a4d..8dffb75 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_FB_TFT_S6D02A1) += fb_s6d02a1.o obj-$(CONFIG_FB_TFT_S6D1121) += fb_s6d1121.o obj-$(CONFIG_FB_TFT_SSD1289) += fb_ssd1289.o obj-$(CONFIG_FB_TFT_SSD1306) += fb_ssd1306.o +obj-$(CONFIG_FB_TFT_SSD1331) += fb_ssd1331.o diff --git a/drivers/staging/fbtft/fb_ssd1331.c b/drivers/staging/fbtft/fb_ssd1331.c new file mode 100644 index 0000000..da7464f --- /dev/null +++ b/drivers/staging/fbtft/fb_ssd1331.c @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_ssd1331" +#define WIDTH 96 +#define HEIGHT 64 +#define GAMMA_NUM 1 +#define GAMMA_LEN 63 +#define DEFAULT_GAMMA "0 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2" \ + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + write_reg(par, 0xae); /* Display Off */ + write_reg(par, 0xa0, 0x70 | (par->bgr << 2)); /* Set Colour Depth */ + write_reg(par, 0x72); // RGB colour + write_reg(par, 0xa1, 0x00); /* Set Display Start Line */ + write_reg(par, 0xa2, 0x00); /* Set Display Offset */ + write_reg(par, 0xa4); /* NORMALDISPLAY */ + write_reg(par, 0xa8, 0x3f); // Set multiplex + write_reg(par, 0xad, 0x8e); // Set master + // write_reg(par, 0xb0, 0x0b); // Set power mode + write_reg(par, 0xb1, 0x31); // Precharge + write_reg(par, 0xb3, 0xf0); // Clock div + write_reg(par, 0x8a, 0x64); // Precharge A + write_reg(par, 0x8b, 0x78); // Precharge B + write_reg(par, 0x8c, 0x64); // Precharge C + write_reg(par, 0xbb, 0x3a); // Precharge level + write_reg(par, 0xbe, 0x3e); // vcomh + write_reg(par, 0x87, 0x06); // Master current + write_reg(par, 0x81, 0x91); // Contrast A + write_reg(par, 0x82, 0x50); // Contrast B + write_reg(par, 0x83, 0x7d); // Contrast C + write_reg(par, 0xaf); /* Set Sleep Mode Display On */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + write_reg(par, 0x15, xs, xe); + write_reg(par, 0x75, ys, ye); +} + +static void write_reg8_bus8(struct fbtft_par *par, int len, ...) +{ + va_list args; + int i, ret; + u8 *buf = (u8 *)par->buf; + + if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { + va_start(args, len); + for (i = 0; i < len; i++) { + buf[i] = (u8)va_arg(args, unsigned int); + } + va_end(args); + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, par->info->device, u8, buf, len, "%s: ", __func__); + } + + va_start(args, len); + + *buf = (u8)va_arg(args, unsigned int); + if (par->gpio.dc != -1) + gpio_set_value(par->gpio.dc, 0); + ret = par->fbtftops.write(par, par->buf, sizeof(u8)); + if (ret < 0) { + va_end(args); + dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret); + return; + } + len--; + + if (len) { + i = len; + while (i--) { + *buf++ = (u8)va_arg(args, unsigned int); + } + ret = par->fbtftops.write(par, par->buf, len * (sizeof(u8))); + if (ret < 0) { + va_end(args); + dev_err(par->info->device, "%s: write() failed and returned %d\n", __func__, ret); + return; + } + } + if (par->gpio.dc != -1) + gpio_set_value(par->gpio.dc, 1); + va_end(args); +} + +/* + Grayscale Lookup Table + GS1 - GS63 + The driver Gamma curve contains the relative values between the entries + in the Lookup table. + + From datasheet: + 8.8 Gray Scale Decoder + + there are total 180 Gamma Settings (Setting 0 to Setting 180) + available for the Gray Scale table. + + The gray scale is defined in incremental way, with reference + to the length of previous table entry: + Setting of GS1 has to be >= 0 + Setting of GS2 has to be > Setting of GS1 +1 + Setting of GS3 has to be > Setting of GS2 +1 + : + Setting of GS63 has to be > Setting of GS62 +1 + + +*/ +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long tmp[GAMMA_NUM * GAMMA_LEN]; + int i, acc = 0; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + for (i = 0; i < 63; i++) { + if (i > 0 && curves[i] < 2) { + dev_err(par->info->device, + "Illegal value in Grayscale Lookup Table at index %d. " \ + "Must be greater than 1\n", i); + return -EINVAL; + } + acc += curves[i]; + tmp[i] = acc; + if (acc > 180) { + dev_err(par->info->device, + "Illegal value(s) in Grayscale Lookup Table. " \ + "At index=%d, the accumulated value has exceeded 180\n", i); + return -EINVAL; + } + } + + write_reg(par, 0xB8, + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], + tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], tmp[15], + tmp[16], tmp[17], tmp[18], tmp[19], tmp[20], tmp[21], tmp[22], tmp[23], + tmp[24], tmp[25], tmp[26], tmp[27], tmp[28], tmp[29], tmp[30], tmp[31], + tmp[32], tmp[33], tmp[34], tmp[35], tmp[36], tmp[37], tmp[38], tmp[39], + tmp[40], tmp[41], tmp[42], tmp[43], tmp[44], tmp[45], tmp[46], tmp[47], + tmp[48], tmp[49], tmp[50], tmp[51], tmp[52], tmp[53], tmp[54], tmp[55], + tmp[56], tmp[57], tmp[58], tmp[59], tmp[60], tmp[61], tmp[62]); + + return 0; +} + +static int blank(struct fbtft_par *par, bool on) +{ + fbtft_par_dbg(DEBUG_BLANK, par, "%s(blank=%s)\n", + __func__, on ? "true" : "false"); + if (on) + write_reg(par, 0xAE); + else + write_reg(par, 0xAF); + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = GAMMA_NUM, + .gamma_len = GAMMA_LEN, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .write_register = write_reg8_bus8, + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_gamma = set_gamma, + .blank = blank, + }, +}; + +FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1331", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ssd1331"); +MODULE_ALIAS("platform:ssd1331"); + +MODULE_DESCRIPTION("SSD1331 OLED Driver"); +MODULE_AUTHOR("Alec Smecher (adapted from SSD1351 by James Davies)"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 883daf0a5c35c891eb9230efe2e99f92caa82a50 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:28 +0100 Subject: staging: fbtft: add fb_ssd1351 driver This commit adds the fb_ssd1351 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index f1e4832..2ba8ef7 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -115,3 +115,9 @@ config FB_TFT_SSD1331 depends on FB_TFT help Framebuffer support for SSD1331 + +config FB_TFT_SSD1351 + tristate "FB driver for the SSD1351 LCD Controller" + depends on FB_TFT + help + Framebuffer support for SSD1351 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 8dffb75..7481e34 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_FB_TFT_S6D1121) += fb_s6d1121.o obj-$(CONFIG_FB_TFT_SSD1289) += fb_ssd1289.o obj-$(CONFIG_FB_TFT_SSD1306) += fb_ssd1306.o obj-$(CONFIG_FB_TFT_SSD1331) += fb_ssd1331.o +obj-$(CONFIG_FB_TFT_SSD1351) += fb_ssd1351.o diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c new file mode 100644 index 0000000..062d986 --- /dev/null +++ b/drivers/staging/fbtft/fb_ssd1351.c @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_ssd1351" +#define WIDTH 128 +#define HEIGHT 128 +#define GAMMA_NUM 1 +#define GAMMA_LEN 63 +#define DEFAULT_GAMMA "0 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2" \ + +static void register_onboard_backlight(struct fbtft_par *par); + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + if (par->pdata + && par->pdata->display.backlight == FBTFT_ONBOARD_BACKLIGHT) { + /* module uses onboard GPIO for panel power */ + par->fbtftops.register_backlight = register_onboard_backlight; + } + + par->fbtftops.reset(par); + + write_reg(par, 0xfd, 0x12); /* Command Lock */ + write_reg(par, 0xfd, 0xb1); /* Command Lock */ + write_reg(par, 0xae); /* Display Off */ + write_reg(par, 0xb3, 0xf1); /* Front Clock Div */ + write_reg(par, 0xca, 0x7f); /* Set Mux Ratio */ + write_reg(par, 0x15, 0x00, 0x7f); /* Set Column Address */ + write_reg(par, 0x75, 0x00, 0x7f); /* Set Row Address */ + write_reg(par, 0xa1, 0x00); /* Set Display Start Line */ + write_reg(par, 0xa2, 0x00); /* Set Display Offset */ + write_reg(par, 0xb5, 0x00); /* Set GPIO */ + write_reg(par, 0xab, 0x01); /* Set Function Selection */ + write_reg(par, 0xb1, 0x32); /* Set Phase Length */ + write_reg(par, 0xb4, 0xa0, 0xb5, 0x55); /* Set Segment Low Voltage */ + write_reg(par, 0xbb, 0x17); /* Set Precharge Voltage */ + write_reg(par, 0xbe, 0x05); /* Set VComH Voltage */ + write_reg(par, 0xc1, 0xc8, 0x80, 0xc8); /* Set Contrast */ + write_reg(par, 0xc7, 0x0f); /* Set Master Contrast */ + write_reg(par, 0xb6, 0x01); /* Set Second Precharge Period */ + write_reg(par, 0xa6); /* Set Display Mode Reset */ + write_reg(par, 0xaf); /* Set Sleep Mode Display On */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + write_reg(par, 0x15, xs, xe); + write_reg(par, 0x75, ys, ye); + write_reg(par, 0x5c); +} + +static int set_var(struct fbtft_par *par) +{ + unsigned remap; + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + if (par->fbtftops.init_display != init_display) { + /* don't risk messing up register A0h */ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, + "%s: skipping since custom init_display() is used\n", + __func__); + return 0; + } + + remap = 0x60 | (par->bgr << 2); /* Set Colour Depth */ + + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0xA0, remap | 0b00 | 1<<4); + break; + case 270: + write_reg(par, 0xA0, remap | 0b11 | 1<<4); + break; + case 180: + write_reg(par, 0xA0, remap | 0b10); + break; + case 90: + write_reg(par, 0xA0, remap | 0b01); + break; + } + + return 0; +} + +/* + Grayscale Lookup Table + GS1 - GS63 + The driver Gamma curve contains the relative values between the entries + in the Lookup table. + + From datasheet: + 8.8 Gray Scale Decoder + + there are total 180 Gamma Settings (Setting 0 to Setting 180) + available for the Gray Scale table. + + The gray scale is defined in incremental way, with reference + to the length of previous table entry: + Setting of GS1 has to be >= 0 + Setting of GS2 has to be > Setting of GS1 +1 + Setting of GS3 has to be > Setting of GS2 +1 + : + Setting of GS63 has to be > Setting of GS62 +1 + + +*/ +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + unsigned long tmp[GAMMA_NUM * GAMMA_LEN]; + int i, acc = 0; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + for (i = 0; i < 63; i++) { + if (i > 0 && curves[i] < 2) { + dev_err(par->info->device, + "Illegal value in Grayscale Lookup Table at index %d. " \ + "Must be greater than 1\n", i); + return -EINVAL; + } + acc += curves[i]; + tmp[i] = acc; + if (acc > 180) { + dev_err(par->info->device, + "Illegal value(s) in Grayscale Lookup Table. " \ + "At index=%d, the accumulated value has exceeded 180\n", i); + return -EINVAL; + } + } + + write_reg(par, 0xB8, + tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], + tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14], tmp[15], + tmp[16], tmp[17], tmp[18], tmp[19], tmp[20], tmp[21], tmp[22], tmp[23], + tmp[24], tmp[25], tmp[26], tmp[27], tmp[28], tmp[29], tmp[30], tmp[31], + tmp[32], tmp[33], tmp[34], tmp[35], tmp[36], tmp[37], tmp[38], tmp[39], + tmp[40], tmp[41], tmp[42], tmp[43], tmp[44], tmp[45], tmp[46], tmp[47], + tmp[48], tmp[49], tmp[50], tmp[51], tmp[52], tmp[53], tmp[54], tmp[55], + tmp[56], tmp[57], tmp[58], tmp[59], tmp[60], tmp[61], tmp[62]); + + return 0; +} + +static int blank(struct fbtft_par *par, bool on) +{ + fbtft_par_dbg(DEBUG_BLANK, par, "%s(blank=%s)\n", + __func__, on ? "true" : "false"); + if (on) + write_reg(par, 0xAE); + else + write_reg(par, 0xAF); + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .gamma_num = GAMMA_NUM, + .gamma_len = GAMMA_LEN, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + .blank = blank, + }, +}; + +#ifdef CONFIG_FB_BACKLIGHT +static int update_onboard_backlight(struct backlight_device *bd) +{ + struct fbtft_par *par = bl_get_data(bd); + bool on; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, + "%s: power=%d, fb_blank=%d\n", + __func__, bd->props.power, bd->props.fb_blank); + + on = (bd->props.power == FB_BLANK_UNBLANK) + && (bd->props.fb_blank == FB_BLANK_UNBLANK); + /* Onboard backlight connected to GPIO0 on SSD1351, GPIO1 unused */ + write_reg(par, 0xB5, on ? 0x03 : 0x02); + + return 0; +} + +static void register_onboard_backlight(struct fbtft_par *par) +{ + struct backlight_device *bd; + struct backlight_properties bl_props = { 0, }; + struct backlight_ops *bl_ops; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, "%s()\n", __func__); + + bl_ops = devm_kzalloc(par->info->device, sizeof(struct backlight_ops), + GFP_KERNEL); + if (!bl_ops) { + dev_err(par->info->device, + "%s: could not allocate memory for backlight operations.\n", + __func__); + return; + } + + bl_ops->update_status = update_onboard_backlight; + bl_props.type = BACKLIGHT_RAW; + bl_props.power = FB_BLANK_POWERDOWN; + + bd = backlight_device_register(dev_driver_string(par->info->device), + par->info->device, par, bl_ops, &bl_props); + if (IS_ERR(bd)) { + dev_err(par->info->device, + "cannot register backlight device (%ld)\n", + PTR_ERR(bd)); + return; + } + par->info->bl_dev = bd; + + if (!par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight = fbtft_unregister_backlight; +} +#else +static void register_onboard_backlight(struct fbtft_par *par) { }; +#endif + + +FBTFT_REGISTER_DRIVER(DRVNAME, "solomon,ssd1351", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:ssd1351"); +MODULE_ALIAS("platform:ssd1351"); + +MODULE_DESCRIPTION("SSD1351 OLED Driver"); +MODULE_AUTHOR("James Davies"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 735d98cdb8e902d933ed7640ad676f2a81f2a2ec Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:29 +0100 Subject: staging: fbtft: add fb_st7735r driver This commit adds the fb_st7735r driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 2ba8ef7..6bc2121 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -121,3 +121,9 @@ config FB_TFT_SSD1351 depends on FB_TFT help Framebuffer support for SSD1351 + +config FB_TFT_ST7735R + tristate "FB driver for the ST7735R LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for ST7735R diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 7481e34..2771e60 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_FB_TFT_SSD1289) += fb_ssd1289.o obj-$(CONFIG_FB_TFT_SSD1306) += fb_ssd1306.o obj-$(CONFIG_FB_TFT_SSD1331) += fb_ssd1331.o obj-$(CONFIG_FB_TFT_SSD1351) += fb_ssd1351.o +obj-$(CONFIG_FB_TFT_ST7735R) += fb_st7735r.o diff --git a/drivers/staging/fbtft/fb_st7735r.c b/drivers/staging/fbtft/fb_st7735r.c new file mode 100644 index 0000000..b63aa38 --- /dev/null +++ b/drivers/staging/fbtft/fb_st7735r.c @@ -0,0 +1,195 @@ +/* + * FB driver for the ST7735R LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_st7735r" +#define DEFAULT_GAMMA "0F 1A 0F 18 2F 28 20 22 1F 1B 23 37 00 07 02 10\n" \ + "0F 1B 0F 17 33 2C 29 2E 30 30 39 3F 00 07 03 10" + + +static int default_init_sequence[] = { + /* SWRESET - Software reset */ + -1, 0x01, + -2, 150, /* delay */ + + /* SLPOUT - Sleep out & booster on */ + -1, 0x11, + -2, 500, /* delay */ + + /* FRMCTR1 - frame rate control: normal mode + frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */ + -1, 0xB1, 0x01, 0x2C, 0x2D, + + /* FRMCTR2 - frame rate control: idle mode + frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) */ + -1, 0xB2, 0x01, 0x2C, 0x2D, + + /* FRMCTR3 - frame rate control - partial mode + dot inversion mode, line inversion mode */ + -1, 0xB3, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, + + /* INVCTR - display inversion control + no inversion */ + -1, 0xB4, 0x07, + + /* PWCTR1 - Power Control + -4.6V, AUTO mode */ + -1, 0xC0, 0xA2, 0x02, 0x84, + + /* PWCTR2 - Power Control + VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD */ + -1, 0xC1, 0xC5, + + /* PWCTR3 - Power Control + Opamp current small, Boost frequency */ + -1, 0xC2, 0x0A, 0x00, + + /* PWCTR4 - Power Control + BCLK/2, Opamp current small & Medium low */ + -1, 0xC3,0x8A,0x2A, + + /* PWCTR5 - Power Control */ + -1, 0xC4, 0x8A, 0xEE, + + /* VMCTR1 - Power Control */ + -1, 0xC5, 0x0E, + + /* INVOFF - Display inversion off */ + -1, 0x20, + + /* COLMOD - Interface pixel format */ + -1, 0x3A, 0x05, + + /* DISPON - Display On */ + -1, 0x29, + -2, 100, /* delay */ + + /* NORON - Partial off (Normal) */ + -1, 0x13, + -2, 10, /* delay */ + + /* end marker */ + -3 +}; + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address */ + write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF); + + /* Row adress */ + write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +#define MY (1 << 7) +#define MX (1 << 6) +#define MV (1 << 5) +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* MADCTL - Memory data access control + RGB/BGR: + 1. Mode selection pin SRGB + RGB H/W pin for color filter setting: 0=RGB, 1=BGR + 2. MADCTL RGB bit + RGB-BGR ORDER color filter panel: 0=RGB, 1=BGR */ + switch (par->info->var.rotate) { + case 0: + write_reg(par, 0x36, MX | MY | (par->bgr << 3)); + break; + case 270: + write_reg(par, 0x36, MY | MV | (par->bgr << 3)); + break; + case 180: + write_reg(par, 0x36, (par->bgr << 3)); + break; + case 90: + write_reg(par, 0x36, MX | MV | (par->bgr << 3)); + break; + } + + return 0; +} + +/* + Gamma string format: + VRF0P VOS0P PK0P PK1P PK2P PK3P PK4P PK5P PK6P PK7P PK8P PK9P SELV0P SELV1P SELV62P SELV63P + VRF0N VOS0N PK0N PK1N PK2N PK3N PK4N PK5N PK6N PK7N PK8N PK9N SELV0N SELV1N SELV62N SELV63N +*/ +#define CURVE(num, idx) curves[num*par->gamma.num_values + idx] +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + int i,j; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + for (i = 0; i < par->gamma.num_curves; i++) + for (j = 0; j < par->gamma.num_values; j++) + CURVE(i,j) &= 0b111111; + + for (i = 0; i < par->gamma.num_curves; i++) + write_reg(par, 0xE0 + i, + CURVE(i, 0), CURVE(i, 1), CURVE(i, 2), CURVE(i, 3), + CURVE(i, 4), CURVE(i, 5), CURVE(i, 6), CURVE(i, 7), + CURVE(i, 8), CURVE(i, 9), CURVE(i, 10), CURVE(i, 11), + CURVE(i, 12), CURVE(i, 13), CURVE(i, 14), CURVE(i,15)); + + return 0; +} +#undef CURVE + + +static struct fbtft_display display = { + .regwidth = 8, + .width = 128, + .height = 160, + .init_sequence = default_init_sequence, + .gamma_num = 2, + .gamma_len = 16, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .set_addr_win = set_addr_win, + .set_var = set_var, + .set_gamma = set_gamma, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "sitronix,st7735r", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:st7735r"); +MODULE_ALIAS("platform:st7735r"); + +MODULE_DESCRIPTION("FB driver for the ST7735R LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From ef8f9ab5b25c2795aa2e784ca58b6e5ba243e128 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:30 +0100 Subject: staging: fbtft: add fb_tinylcd driver This commit adds the fb_tinylcd driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 6bc2121..dd740bf 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -127,3 +127,9 @@ config FB_TFT_ST7735R depends on FB_TFT help Generic Framebuffer support for ST7735R + +config FB_TFT_TINYLCD + tristate "FB driver for tinylcd.com display" + depends on FB_TFT + help + Custom Framebuffer support for tinylcd.com display diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 2771e60..a5c2d15 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_FB_TFT_SSD1306) += fb_ssd1306.o obj-$(CONFIG_FB_TFT_SSD1331) += fb_ssd1331.o obj-$(CONFIG_FB_TFT_SSD1351) += fb_ssd1351.o obj-$(CONFIG_FB_TFT_ST7735R) += fb_st7735r.o +obj-$(CONFIG_FB_TFT_TINYLCD) += fb_tinylcd.o diff --git a/drivers/staging/fbtft/fb_tinylcd.c b/drivers/staging/fbtft/fb_tinylcd.c new file mode 100644 index 0000000..ca98bfb --- /dev/null +++ b/drivers/staging/fbtft/fb_tinylcd.c @@ -0,0 +1,124 @@ +/* + * Custom FB driver for tinylcd.com display + * + * Copyright (C) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_tinylcd" +#define WIDTH 320 +#define HEIGHT 480 + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + write_reg(par, 0xB0, 0x80); + write_reg(par, 0xC0, 0x0A, 0x0A); + write_reg(par, 0xC1, 0x45, 0x07); + write_reg(par, 0xC2, 0x33); + write_reg(par, 0xC5, 0x00, 0x42, 0x80); + write_reg(par, 0xB1, 0xD0, 0x11); + write_reg(par, 0xB4, 0x02); + write_reg(par, 0xB6, 0x00, 0x22, 0x3B); + write_reg(par, 0xB7, 0x07); + write_reg(par, 0x36, 0x58); + write_reg(par, 0xF0, 0x36, 0xA5, 0xD3); + write_reg(par, 0xE5, 0x80); + write_reg(par, 0xE5, 0x01); + write_reg(par, 0xB3, 0x00); + write_reg(par, 0xE5, 0x00); + write_reg(par, 0xF0, 0x36, 0xA5, 0x53); + write_reg(par, 0xE0, 0x00, 0x35, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x35, 0x33, 0x00, 0x00, 0x00); + write_reg(par, 0x3A, 0x55); + write_reg(par, 0x11); + udelay(250); + write_reg(par, 0x29); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* Column address */ + write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF); + + /* Row adress */ + write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF); + + /* Memory write */ + write_reg(par, 0x2C); +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + case 270: + write_reg(par, 0xB6, 0x00, 0x02, 0x3B); + write_reg(par, 0x36, 0x28); + break; + case 180: + write_reg(par, 0xB6, 0x00, 0x22, 0x3B); + write_reg(par, 0x36, 0x58); + break; + case 90: + write_reg(par, 0xB6, 0x00, 0x22, 0x3B); + write_reg(par, 0x36, 0x38); + break; + default: + write_reg(par, 0xB6, 0x00, 0x22, 0x3B); + write_reg(par, 0x36, 0x08); + break; + } + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "neosec,tinylcd", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("spi:tinylcd"); + +MODULE_DESCRIPTION("Custom FB driver for tinylcd.com display"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 9518dbc0df26ca14206366b5012e84517d80f3cd Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:31 +0100 Subject: staging: fbtft: add fb_tls8204 driver This commit adds the fb_tls8204 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index dd740bf..73c181c 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -133,3 +133,9 @@ config FB_TFT_TINYLCD depends on FB_TFT help Custom Framebuffer support for tinylcd.com display + +config FB_TFT_TLS8204 + tristate "FB driver for the TLS8204 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for TLS8204 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index a5c2d15..5fa20f0 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -24,3 +24,4 @@ obj-$(CONFIG_FB_TFT_SSD1331) += fb_ssd1331.o obj-$(CONFIG_FB_TFT_SSD1351) += fb_ssd1351.o obj-$(CONFIG_FB_TFT_ST7735R) += fb_st7735r.o obj-$(CONFIG_FB_TFT_TINYLCD) += fb_tinylcd.o +obj-$(CONFIG_FB_TFT_TLS8204) += fb_tls8204.o diff --git a/drivers/staging/fbtft/fb_tls8204.c b/drivers/staging/fbtft/fb_tls8204.c new file mode 100644 index 0000000..8738c7a --- /dev/null +++ b/drivers/staging/fbtft/fb_tls8204.c @@ -0,0 +1,176 @@ +/* + * FB driver for the TLS8204 LCD Controller + * + * The display is monochrome and the video memory is RGB565. + * Any pixel value except 0 turns the pixel on. + * + * Copyright (C) 2013 Noralf Tronnes + * Copyright (C) 2014 Michael Hope (adapted for the TLS8204) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_tls8204" +#define WIDTH 84 +#define HEIGHT 48 +#define TXBUFLEN WIDTH +#define DEFAULT_GAMMA "40" /* gamma is used to control contrast in this driver */ + +static unsigned bs = 4; +module_param(bs, uint, 0); +MODULE_PARM_DESC(bs, "BS[2:0] Bias voltage level: 0-7 (default: 4)"); + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* Enter extended command mode */ + write_reg(par, 0x21); /* 5:1 1 + 2:0 PD - Powerdown control: chip is active + 1:0 V - Entry mode: horizontal addressing + 0:1 H - Extended instruction set control: extended + */ + + /* H=1 Bias system */ + write_reg(par, 0x10 | (bs & 0x7)); /* + 4:1 1 + 3:0 0 + 2:x BS2 - Bias System + 1:x BS1 + 0:x BS0 + */ + + /* Set the address of the first display line. */ + write_reg(par, 0x04 | (64 >> 6)); + write_reg(par, 0x40 | (64 & 0x3F)); + + /* Enter H=0 standard command mode */ + write_reg(par, 0x20); + + /* H=0 Display control */ + write_reg(par, 0x08 | 4); /* + 3:1 1 + 2:1 D - DE: 10=normal mode + 1:0 0 + 0:0 E + */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* H=0 Set X address of RAM */ + write_reg(par, 0x80); /* 7:1 1 + 6-0: X[6:0] - 0x00 + */ + + /* H=0 Set Y address of RAM */ + write_reg(par, 0x40); /* 7:0 0 + 6:1 1 + 2-0: Y[2:0] - 0x0 + */ +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16 = (u16 *)par->info->screen_base; + int x, y, i; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + for (y = 0; y < HEIGHT/8; y++) { + u8 *buf = par->txbuf.buf; + /* The display is 102x68 but the LCD is 84x48. Set + the write pointer at the start of each row. */ + gpio_set_value(par->gpio.dc, 0); + write_reg(par, 0x80 | 0); + write_reg(par, 0x40 | y); + + for (x = 0; x < WIDTH; x++) { + u8 ch = 0; + for (i = 0; i < 8*WIDTH; i += WIDTH) { + ch >>= 1; + if (vmem16[(y*8*WIDTH)+i+x]) + ch |= 0x80; + } + *buf++ = ch; + } + /* Write the row */ + gpio_set_value(par->gpio.dc, 1); + ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH); + if (ret < 0) { + dev_err(par->info->device, + "%s: write failed and returned: %d\n", __func__, ret); + break; + } + } + + return ret; +} + +static int set_gamma(struct fbtft_par *par, unsigned long *curves) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* apply mask */ + curves[0] &= 0x7F; + + write_reg(par, 0x21); /* turn on extended instruction set */ + write_reg(par, 0x80 | curves[0]); + write_reg(par, 0x20); /* turn off extended instruction set */ + + return 0; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .txbuflen = TXBUFLEN, + .gamma_num = 1, + .gamma_len = 1, + .gamma = DEFAULT_GAMMA, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .write_vmem = write_vmem, + .set_gamma = set_gamma, + }, + .backlight = 1, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "teralane,tls8204", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("spi:tls8204"); + +MODULE_DESCRIPTION("FB driver for the TLS8204 LCD Controller"); +MODULE_AUTHOR("Michael Hope"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 5741ecd66c8599d564f59b15ce6dc32d7922293e Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:32 +0100 Subject: staging: fbtft: add fb_uc1701 driver This commit adds the fb_uc1701 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 73c181c..fb3f4df 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -139,3 +139,9 @@ config FB_TFT_TLS8204 depends on FB_TFT help Generic Framebuffer support for TLS8204 + +config FB_TFT_UC1701 + tristate "FB driver for the UC1701 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for UC1701 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 5fa20f0..732b219 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_FB_TFT_SSD1351) += fb_ssd1351.o obj-$(CONFIG_FB_TFT_ST7735R) += fb_st7735r.o obj-$(CONFIG_FB_TFT_TINYLCD) += fb_tinylcd.o obj-$(CONFIG_FB_TFT_TLS8204) += fb_tls8204.o +obj-$(CONFIG_FB_TFT_UC1701) += fb_uc1701.o diff --git a/drivers/staging/fbtft/fb_uc1701.c b/drivers/staging/fbtft/fb_uc1701.c new file mode 100644 index 0000000..d70ac52 --- /dev/null +++ b/drivers/staging/fbtft/fb_uc1701.c @@ -0,0 +1,210 @@ +/* + * FB driver for the UC1701 LCD Controller + * + * The display is monochrome and the video memory is RGB565. + * Any pixel value except 0 turns the pixel on. + * + * Copyright (C) 2014 Juergen Holzmann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_uc1701" +#define WIDTH 102 +#define HEIGHT 64 +#define PAGES (HEIGHT/8) + +/* 1: Display on/off */ +#define LCD_DISPLAY_ENABLE 0xAE +/* 2: display start line set */ +#define LCD_START_LINE 0x40 +/* 3: Page address set (lower 4 bits select one of the pages) */ +#define LCD_PAGE_ADDRESS 0xB0 +/* 4: column address */ +#define LCD_COL_ADDRESS 0x10 +/* 8: select orientation */ +#define LCD_BOTTOMVIEW 0xA0 +/* 9: inverted display */ +#define LCD_DISPLAY_INVERT 0xA6 +/* 10: show memory content or switch all pixels on */ +#define LCD_ALL_PIXEL 0xA4 +/* 11: lcd bias set */ +#define LCD_BIAS 0xA2 +/* 14: Reset Controller */ +#define LCD_RESET_CMD 0xE2 +/* 15: output mode select (turns display upside-down) */ +#define LCD_SCAN_DIR 0xC0 +/* 16: power control set */ +#define LCD_POWER_CONTROL 0x28 +/* 17: voltage regulator resistor ratio set */ +#define LCD_VOLTAGE 0x20 +/* 18: Volume mode set */ +#define LCD_VOLUME_MODE 0x81 +/* 22: NOP command */ +#define LCD_NO_OP 0xE3 +/* 25: advanced program control */ +#define LCD_ADV_PROG_CTRL 0xFA +/* 25: advanced program control2 */ +#define LCD_ADV_PROG_CTRL2 0x10 +#define LCD_TEMPCOMP_HIGH 0x80 +/* column offset for normal orientation */ +#define SHIFT_ADDR_NORMAL 0 +/* column offset for bottom view orientation */ +#define SHIFT_ADDR_TOPVIEW 30 + + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + /* softreset of LCD */ + write_reg(par, LCD_RESET_CMD); + mdelay(10); + + /* set startpoint */ + /* LCD_START_LINE | (pos & 0x3F) */ + write_reg(par, LCD_START_LINE); + + /* select orientation BOTTOMVIEW */ + write_reg(par, LCD_BOTTOMVIEW | 1); + /* output mode select (turns display upside-down) */ + write_reg(par, LCD_SCAN_DIR | 0x00); + + /* Normal Pixel mode */ + write_reg(par, LCD_ALL_PIXEL | 0); + + /* positive display */ + write_reg(par, LCD_DISPLAY_INVERT | 0); + + /* bias 1/9 */ + write_reg(par, LCD_BIAS | 0); + + /* power control mode: all features on */ + /* LCD_POWER_CONTROL | (val&0x07) */ + write_reg(par, LCD_POWER_CONTROL | 0x07); + + /* set voltage regulator R/R */ + /* LCD_VOLTAGE | (val&0x07) */ + write_reg(par, LCD_VOLTAGE | 0x07); + + /* volume mode set */ + /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ + write_reg(par, LCD_VOLUME_MODE); + /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ + write_reg(par, 0x09); + /* ???? */ + /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ + write_reg(par, LCD_NO_OP); + + /* advanced program control */ + write_reg(par, LCD_ADV_PROG_CTRL); + write_reg(par, LCD_ADV_PROG_CTRL2|LCD_TEMPCOMP_HIGH); + + /* enable display */ + write_reg(par, LCD_DISPLAY_ENABLE | 1); + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + /* goto address */ + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, LCD_PAGE_ADDRESS); + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, 0x00); + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, LCD_COL_ADDRESS); +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + u16 *vmem16 = (u16 *)par->info->screen_base; + u8 *buf = par->txbuf.buf; + int x, y, i; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + for (y = 0; y < PAGES; y++) { + buf = par->txbuf.buf; + for (x = 0; x < WIDTH; x++) { + *buf = 0x00; + for (i = 0; i < 8; i++) + *buf |= (vmem16[((y*8*WIDTH)+(i*WIDTH))+x] ? 1 : 0) << i; + buf++; + } + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, LCD_PAGE_ADDRESS|(u8)y); + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, 0x00); + /* LCD_PAGE_ADDRESS | ((page) & 0x1F), + (((col)+SHIFT_ADDR_NORMAL) & 0x0F), + LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, LCD_COL_ADDRESS); + gpio_set_value(par->gpio.dc, 1); + ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH); + gpio_set_value(par->gpio.dc, 0); + } + + if (ret < 0) + dev_err(par->info->device, "%s: write failed and returned: %d\n", __func__, ret); + + return ret; +} + + +static struct fbtft_display display = { + .regwidth = 8, + .width = WIDTH, + .height = HEIGHT, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .write_vmem = write_vmem, + }, + .backlight = 1, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "UltraChip,uc1701", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("spi:uc1701"); + +MODULE_DESCRIPTION("FB driver for the UC1701 LCD Controller"); +MODULE_AUTHOR("Juergen Holzmann"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From ef0459c7f4101e3ac0fda6e29385613b22998aca Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:33 +0100 Subject: staging: fbtft: add fb_upd161704 driver This commit adds the fb_upd161704 driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index fb3f4df..886a48c 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -145,3 +145,9 @@ config FB_TFT_UC1701 depends on FB_TFT help Generic Framebuffer support for UC1701 + +config FB_TFT_UPD161704 + tristate "FB driver for the uPD161704 LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for uPD161704 diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 732b219..dca2a45 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -26,3 +26,4 @@ obj-$(CONFIG_FB_TFT_ST7735R) += fb_st7735r.o obj-$(CONFIG_FB_TFT_TINYLCD) += fb_tinylcd.o obj-$(CONFIG_FB_TFT_TLS8204) += fb_tls8204.o obj-$(CONFIG_FB_TFT_UC1701) += fb_uc1701.o +obj-$(CONFIG_FB_TFT_UPD161704) += fb_upd161704.o diff --git a/drivers/staging/fbtft/fb_upd161704.c b/drivers/staging/fbtft/fb_upd161704.c new file mode 100644 index 0000000..fff57b3 --- /dev/null +++ b/drivers/staging/fbtft/fb_upd161704.c @@ -0,0 +1,206 @@ +/* + * FB driver for the uPD161704 LCD Controller + * + * Copyright (C) 2014 Seong-Woo Kim + * + * Based on fb_ili9325.c by Noralf Tronnes + * Based on ili9325.c by Jeroen Domburg + * Init code from UTFT library by Henning Karlsen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_upd161704" +#define WIDTH 240 +#define HEIGHT 320 +#define BPP 16 + +static int init_display(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + par->fbtftops.reset(par); + + if (par->gpio.cs != -1) + gpio_set_value(par->gpio.cs, 0); /* Activate chip */ + + /* Initialization sequence from Lib_UTFT */ + + /* register reset */ + write_reg(par, 0x0003,0x0001); /* Soft reset */ + + /* oscillator start */ + write_reg(par, 0x003A,0x0001); /*Oscillator 0: stop, 1: operation */ + udelay(100); + + /* y-setting */ + write_reg(par, 0x0024,0x007B); /* amplitude setting */ + udelay(10); + write_reg(par, 0x0025,0x003B); /* amplitude setting */ + write_reg(par, 0x0026,0x0034); /* amplitude setting */ + udelay(10); + write_reg(par, 0x0027,0x0004); /* amplitude setting */ + write_reg(par, 0x0052,0x0025); /* circuit setting 1 */ + udelay(10); + write_reg(par, 0x0053,0x0033); /* circuit setting 2 */ + write_reg(par, 0x0061,0x001C); /* adjustment V10 positive polarity */ + udelay(10); + write_reg(par, 0x0062,0x002C); /* adjustment V9 negative polarity */ + write_reg(par, 0x0063,0x0022); /* adjustment V34 positive polarity */ + udelay(10); + write_reg(par, 0x0064,0x0027); /* adjustment V31 negative polarity */ + udelay(10); + write_reg(par, 0x0065,0x0014); /* adjustment V61 negative polarity */ + udelay(10); + write_reg(par, 0x0066,0x0010); /* adjustment V61 negative polarity */ + + /* Basical clock for 1 line (BASECOUNT[7:0]) number specified */ + write_reg(par, 0x002E,0x002D); + + /* Power supply setting */ + write_reg(par, 0x0019,0x0000); /* DC/DC output setting */ + udelay(200); + write_reg(par, 0x001A,0x1000); /* DC/DC frequency setting */ + write_reg(par, 0x001B,0x0023); /* DC/DC rising setting */ + write_reg(par, 0x001C,0x0C01); /* Regulator voltage setting */ + write_reg(par, 0x001D,0x0000); /* Regulator current setting */ + write_reg(par, 0x001E,0x0009); /* VCOM output setting */ + write_reg(par, 0x001F,0x0035); /* VCOM amplitude setting */ + write_reg(par, 0x0020,0x0015); /* VCOMM cencter setting */ + write_reg(par, 0x0018,0x1E7B); /* DC/DC operation setting */ + + /* windows setting */ + write_reg(par, 0x0008,0x0000); /* Minimum X address */ + write_reg(par, 0x0009,0x00EF); /* Maximum X address */ + write_reg(par, 0x000a,0x0000); /* Minimum Y address */ + write_reg(par, 0x000b,0x013F); /* Maximum Y address */ + + /* LCD display area setting */ + write_reg(par, 0x0029,0x0000); /* [LCDSIZE] X MIN. size set */ + write_reg(par, 0x002A,0x0000); /* [LCDSIZE] Y MIN. size set */ + write_reg(par, 0x002B,0x00EF); /* [LCDSIZE] X MAX. size set */ + write_reg(par, 0x002C,0x013F); /* [LCDSIZE] Y MAX. size set */ + + /* Gate scan setting */ + write_reg(par, 0x0032,0x0002); + + /* n line inversion line number */ + write_reg(par, 0x0033,0x0000); + + /* Line inversion/frame inversion/interlace setting */ + write_reg(par, 0x0037,0x0000); + + /* Gate scan operation setting register */ + write_reg(par, 0x003B,0x0001); + + /* Color mode */ + /*GS = 0: 260-k color (64 gray scale), GS = 1: 8 color (2 gray scale) */ + write_reg(par, 0x0004,0x0000); + + /* RAM control register */ + write_reg(par, 0x0005,0x0000); /*Window access 00:Normal, 10:Window */ + + /* Display setting register 2 */ + write_reg(par, 0x0001,0x0000); + + /* display setting */ + write_reg(par, 0x0000,0x0000); /* display on */ + + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + switch (par->info->var.rotate) { + /* R20h = Horizontal GRAM Start Address */ + /* R21h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0006, xs); + write_reg(par, 0x0007, ys); + break; + case 180: + write_reg(par, 0x0006, WIDTH - 1 - xs); + write_reg(par, 0x0007, HEIGHT - 1 - ys); + break; + case 270: + write_reg(par, 0x0006, WIDTH - 1 - ys); + write_reg(par, 0x0007, xs); + break; + case 90: + write_reg(par, 0x0006, ys); + write_reg(par, 0x0007, HEIGHT - 1 - xs); + break; + } + + write_reg(par, 0x0e); /* Write Data to GRAM */ +} + +static int set_var(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + switch (par->info->var.rotate) { + /* AM: GRAM update direction */ + case 0: + write_reg(par, 0x01, 0x0000); + write_reg(par, 0x05, 0x0000); + break; + case 180: + write_reg(par, 0x01, 0x00C0); + write_reg(par, 0x05, 0x0000); + break; + case 270: + write_reg(par, 0x01, 0x0080); + write_reg(par, 0x05, 0x0001); + break; + case 90: + write_reg(par, 0x01, 0x0040); + write_reg(par, 0x05, 0x0001); + break; + } + + return 0; +} + +static struct fbtft_display display = { + .regwidth = 16, + .width = WIDTH, + .height = HEIGHT, + .fbtftops = { + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "nec,upd161704", &display); + +MODULE_ALIAS("spi:" DRVNAME); +MODULE_ALIAS("platform:" DRVNAME); +MODULE_ALIAS("spi:upd161704"); +MODULE_ALIAS("platform:upd161704"); + +MODULE_DESCRIPTION("FB driver for the uPD161704 LCD Controller"); +MODULE_AUTHOR("Seong-Woo Kim"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 1e7d51c6850b8a6d840b9865d06fec51c1c3aa83 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:34 +0100 Subject: staging: fbtft: add fb_watterott driver This commit adds the fb_watterott driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 886a48c..8edec90 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -151,3 +151,9 @@ config FB_TFT_UPD161704 depends on FB_TFT help Generic Framebuffer support for uPD161704 + +config FB_TFT_WATTEROTT + tristate "FB driver for the WATTEROTT LCD Controller" + depends on FB_TFT + help + Generic Framebuffer support for WATTEROTT diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index dca2a45..78008c3 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -27,3 +27,4 @@ obj-$(CONFIG_FB_TFT_TINYLCD) += fb_tinylcd.o obj-$(CONFIG_FB_TFT_TLS8204) += fb_tls8204.o obj-$(CONFIG_FB_TFT_UC1701) += fb_uc1701.o obj-$(CONFIG_FB_TFT_UPD161704) += fb_upd161704.o +obj-$(CONFIG_FB_TFT_WATTEROTT) += fb_watterott.o diff --git a/drivers/staging/fbtft/fb_watterott.c b/drivers/staging/fbtft/fb_watterott.c new file mode 100644 index 0000000..975b579 --- /dev/null +++ b/drivers/staging/fbtft/fb_watterott.c @@ -0,0 +1,324 @@ +/* + * FB driver for the Watterott LCD Controller + * + * Copyright (C) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fb_watterott" +#define WIDTH 320 +#define HEIGHT 240 +#define FPS 5 +#define TXBUFLEN 1024 +#define DEFAULT_BRIGHTNESS 50 + +#define CMD_VERSION 0x01 +#define CMD_LCD_LED 0x10 +#define CMD_LCD_RESET 0x11 +#define CMD_LCD_ORIENTATION 0x20 +#define CMD_LCD_DRAWIMAGE 0x27 +#define COLOR_RGB323 8 +#define COLOR_RGB332 9 +#define COLOR_RGB233 10 +#define COLOR_RGB565 16 + + +static short mode = 565; +module_param(mode, short, 0); +MODULE_PARM_DESC(mode, "RGB color transfer mode: 332, 565 (default)"); + +static void write_reg8_bus8(struct fbtft_par *par, int len, ...) +{ + va_list args; + int i, ret; + u8 *buf = par->buf; + + va_start(args, len); + for (i = 0; i < len; i++) + *buf++ = (u8)va_arg(args, unsigned int); + va_end(args); + + fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, + par->info->device, u8, par->buf, len, "%s: ", __func__); + + ret = par->fbtftops.write(par, par->buf, len); + if (ret < 0) { + dev_err(par->info->device, + "%s: write() failed and returned %d\n", __func__, ret); + return; + } +} + +static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) +{ + unsigned start_line, end_line; + u16 *vmem16 = (u16 *)(par->info->screen_base + offset); + u16 *pos = par->txbuf.buf + 1; + u16 *buf16 = par->txbuf.buf + 10; + int i, j; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + start_line = offset / par->info->fix.line_length; + end_line = start_line + (len / par->info->fix.line_length) - 1; + + /* Set command header. pos: x, y, w, h */ + ((u8 *)par->txbuf.buf)[0] = CMD_LCD_DRAWIMAGE; + pos[0] = 0; + pos[2] = cpu_to_be16(par->info->var.xres); + pos[3] = cpu_to_be16(1); + ((u8 *)par->txbuf.buf)[9] = COLOR_RGB565; + + for (i = start_line; i <= end_line; i++) { + pos[1] = cpu_to_be16(i); + for (j = 0; j < par->info->var.xres; j++) + buf16[j] = cpu_to_be16(*vmem16++); + ret = par->fbtftops.write(par, + par->txbuf.buf, 10 + par->info->fix.line_length); + if (ret < 0) + return ret; + udelay(300); + } + + return 0; +} + +#define RGB565toRGB323(c) (((c&0xE000)>>8) | ((c&0600)>>6) | ((c&0x001C)>>2)) +#define RGB565toRGB332(c) (((c&0xE000)>>8) | ((c&0700)>>6) | ((c&0x0018)>>3)) +#define RGB565toRGB233(c) (((c&0xC000)>>8) | ((c&0700)>>5) | ((c&0x001C)>>2)) + +static int write_vmem_8bit(struct fbtft_par *par, size_t offset, size_t len) +{ + unsigned start_line, end_line; + u16 *vmem16 = (u16 *)(par->info->screen_base + offset); + u16 *pos = par->txbuf.buf + 1; + u8 *buf8 = par->txbuf.buf + 10; + int i, j; + int ret = 0; + + fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); + + start_line = offset / par->info->fix.line_length; + end_line = start_line + (len / par->info->fix.line_length) - 1; + + /* Set command header. pos: x, y, w, h */ + ((u8 *)par->txbuf.buf)[0] = CMD_LCD_DRAWIMAGE; + pos[0] = 0; + pos[2] = cpu_to_be16(par->info->var.xres); + pos[3] = cpu_to_be16(1); + ((u8 *)par->txbuf.buf)[9] = COLOR_RGB332; + + for (i = start_line; i <= end_line; i++) { + pos[1] = cpu_to_be16(i); + for (j = 0; j < par->info->var.xres; j++) { + buf8[j] = RGB565toRGB332(*vmem16); + vmem16++; + } + ret = par->fbtftops.write(par, + par->txbuf.buf, 10 + par->info->var.xres); + if (ret < 0) + return ret; + udelay(700); + } + + return 0; +} + +static unsigned firmware_version(struct fbtft_par *par) +{ + u8 rxbuf[4] = {0, }; + + write_reg(par, CMD_VERSION); + par->fbtftops.read(par, rxbuf, 4); + if (rxbuf[1] != '.') + return 0; + + return (rxbuf[0] - '0') << 8 | (rxbuf[2] - '0') << 4 | (rxbuf[3] - '0'); +} + +static int init_display(struct fbtft_par *par) +{ + int ret; + unsigned version; + u8 save_mode; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* enable SPI interface by having CS and MOSI low during reset */ + save_mode = par->spi->mode; + par->spi->mode |= SPI_CS_HIGH; + ret = par->spi->master->setup(par->spi); /* set CS inactive low */ + if (ret) { + dev_err(par->info->device, "Could not set SPI_CS_HIGH\n"); + return ret; + } + write_reg(par, 0x00); /* make sure mode is set */ + + mdelay(50); + par->fbtftops.reset(par); + mdelay(1000); + par->spi->mode = save_mode; + ret = par->spi->master->setup(par->spi); + if (ret) { + dev_err(par->info->device, "Could not restore SPI mode\n"); + return ret; + } + write_reg(par, 0x00); + + version = firmware_version(par); + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "Firmware version: %x.%02x\n", + version >> 8, version & 0xFF); + + if (mode == 332) + par->fbtftops.write_vmem = write_vmem_8bit; + return 0; +} + +static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + /* not used on this controller */ +} + +static int set_var(struct fbtft_par *par) +{ + u8 rotate; + + fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__); + + /* this controller rotates clock wise */ + switch (par->info->var.rotate) { + case 90: + rotate = 27; + break; + case 180: + rotate = 18; + break; + case 270: + rotate = 9; + break; + default: + rotate = 0; + } + write_reg(par, CMD_LCD_ORIENTATION, rotate); + + return 0; +} + +static int verify_gpios(struct fbtft_par *par) +{ + if (par->gpio.reset < 0) { + dev_err(par->info->device, "Missing 'reset' gpio. Aborting.\n"); + return -EINVAL; + } + return 0; +} + +#ifdef CONFIG_FB_BACKLIGHT +static int backlight_chip_update_status(struct backlight_device *bd) +{ + struct fbtft_par *par = bl_get_data(bd); + int brightness = bd->props.brightness; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, + "%s: brightness=%d, power=%d, fb_blank=%d\n", + __func__, bd->props.brightness, bd->props.power, + bd->props.fb_blank); + + if (bd->props.power != FB_BLANK_UNBLANK) + brightness = 0; + + if (bd->props.fb_blank != FB_BLANK_UNBLANK) + brightness = 0; + + write_reg(par, CMD_LCD_LED, brightness); + + return 0; +} + +static void register_chip_backlight(struct fbtft_par *par) +{ + struct backlight_device *bd; + struct backlight_properties bl_props = { 0, }; + struct backlight_ops *bl_ops; + + fbtft_par_dbg(DEBUG_BACKLIGHT, par, "%s()\n", __func__); + + bl_ops = devm_kzalloc(par->info->device, sizeof(struct backlight_ops), + GFP_KERNEL); + if (!bl_ops) { + dev_err(par->info->device, + "%s: could not allocate memory for backlight operations.\n", + __func__); + return; + } + + bl_ops->update_status = backlight_chip_update_status; + bl_props.type = BACKLIGHT_RAW; + bl_props.power = FB_BLANK_POWERDOWN; + bl_props.max_brightness = 100; + bl_props.brightness = DEFAULT_BRIGHTNESS; + + bd = backlight_device_register(dev_driver_string(par->info->device), + par->info->device, par, bl_ops, &bl_props); + if (IS_ERR(bd)) { + dev_err(par->info->device, + "cannot register backlight device (%ld)\n", + PTR_ERR(bd)); + return; + } + par->info->bl_dev = bd; + + if (!par->fbtftops.unregister_backlight) + par->fbtftops.unregister_backlight = fbtft_unregister_backlight; +} +#else +#define register_chip_backlight NULL +#endif + + +static struct fbtft_display display = { + .regwidth = 8, + .buswidth = 8, + .width = WIDTH, + .height = HEIGHT, + .fps = FPS, + .txbuflen = TXBUFLEN, + .fbtftops = { + .write_register = write_reg8_bus8, + .write_vmem = write_vmem, + .init_display = init_display, + .set_addr_win = set_addr_win, + .set_var = set_var, + .verify_gpios = verify_gpios, + .register_backlight = register_chip_backlight, + }, +}; +FBTFT_REGISTER_DRIVER(DRVNAME, "watterott,openlcd", &display); + +MODULE_ALIAS("spi:" DRVNAME); + +MODULE_DESCRIPTION("FB driver for the Watterott LCD Controller"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 27837e11a67faf8aa683bde91a7879d01b3c9c14 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:35 +0100 Subject: staging: fbtft: add flexfb driver This commit adds the flexfb driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index 8edec90..d7ddd6e 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -157,3 +157,9 @@ config FB_TFT_WATTEROTT depends on FB_TFT help Generic Framebuffer support for WATTEROTT + +config FB_FLEX + tristate "Generic FB driver for TFT LCD displays" + depends on FB_TFT + help + Generic Framebuffer support for TFT LCD displays. diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 78008c3..5b3254a 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -28,3 +28,4 @@ obj-$(CONFIG_FB_TFT_TLS8204) += fb_tls8204.o obj-$(CONFIG_FB_TFT_UC1701) += fb_uc1701.o obj-$(CONFIG_FB_TFT_UPD161704) += fb_upd161704.o obj-$(CONFIG_FB_TFT_WATTEROTT) += fb_watterott.o +obj-$(CONFIG_FB_FLEX) += flexfb.o diff --git a/drivers/staging/fbtft/flexfb.c b/drivers/staging/fbtft/flexfb.c new file mode 100644 index 0000000..45574a0 --- /dev/null +++ b/drivers/staging/fbtft/flexfb.c @@ -0,0 +1,593 @@ +/* + * Generic FB driver for TFT LCD displays + * + * Copyright (C) 2013 Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "flexfb" + + +static char *chip = NULL; +module_param(chip, charp, 0); +MODULE_PARM_DESC(chip, "LCD controller"); + +static unsigned int width = 0; +module_param(width, uint, 0); +MODULE_PARM_DESC(width, "Display width"); + +static unsigned int height = 0; +module_param(height, uint, 0); +MODULE_PARM_DESC(height, "Display height"); + +static int init[512]; +static int init_num = 0; +module_param_array(init, int, &init_num, 0); +MODULE_PARM_DESC(init, "Init sequence"); + +static unsigned int setaddrwin = 0; +module_param(setaddrwin, uint, 0); +MODULE_PARM_DESC(setaddrwin, "Which set_addr_win() implementation to use"); + +static unsigned int buswidth = 8; +module_param(buswidth, uint, 0); +MODULE_PARM_DESC(buswidth, "Width of databus (default: 8)"); + +static unsigned int regwidth = 8; +module_param(regwidth, uint, 0); +MODULE_PARM_DESC(regwidth, "Width of controller register (default: 8)"); + +static bool nobacklight = false; +module_param(nobacklight, bool, 0); +MODULE_PARM_DESC(nobacklight, "Turn off backlight functionality."); + +static bool latched = false; +module_param(latched, bool, 0); +MODULE_PARM_DESC(latched, "Use with latched 16-bit databus"); + + +static int *initp = NULL; +static int initp_num = 0; + +/* default init sequences */ +static int st7735r_init[] = { \ +-1,0x01,-2,150,-1,0x11,-2,500,-1,0xB1,0x01,0x2C,0x2D,-1,0xB2,0x01,0x2C,0x2D,-1,0xB3,0x01,0x2C,0x2D,0x01,0x2C,0x2D, \ +-1,0xB4,0x07,-1,0xC0,0xA2,0x02,0x84,-1,0xC1,0xC5,-1,0xC2,0x0A,0x00,-1,0xC3,0x8A,0x2A,-1,0xC4,0x8A,0xEE,-1,0xC5,0x0E, \ +-1,0x20,-1,0x36,0xC0,-1,0x3A,0x05,-1,0xE0,0x0f,0x1a,0x0f,0x18,0x2f,0x28,0x20,0x22,0x1f,0x1b,0x23,0x37,0x00,0x07,0x02,0x10, \ +-1,0xE1,0x0f,0x1b,0x0f,0x17,0x33,0x2c,0x29,0x2e,0x30,0x30,0x39,0x3f,0x00,0x07,0x03,0x10,-1,0x29,-2,100,-1,0x13,-2,10,-3 }; + +static int ssd1289_init[] = { \ +-1,0x00,0x0001,-1,0x03,0xA8A4,-1,0x0C,0x0000,-1,0x0D,0x080C,-1,0x0E,0x2B00,-1,0x1E,0x00B7,-1,0x01,0x2B3F,-1,0x02,0x0600, \ +-1,0x10,0x0000,-1,0x11,0x6070,-1,0x05,0x0000,-1,0x06,0x0000,-1,0x16,0xEF1C,-1,0x17,0x0003,-1,0x07,0x0233,-1,0x0B,0x0000, \ +-1,0x0F,0x0000,-1,0x41,0x0000,-1,0x42,0x0000,-1,0x48,0x0000,-1,0x49,0x013F,-1,0x4A,0x0000,-1,0x4B,0x0000,-1,0x44,0xEF00, \ +-1,0x45,0x0000,-1,0x46,0x013F,-1,0x30,0x0707,-1,0x31,0x0204,-1,0x32,0x0204,-1,0x33,0x0502,-1,0x34,0x0507,-1,0x35,0x0204, \ +-1,0x36,0x0204,-1,0x37,0x0502,-1,0x3A,0x0302,-1,0x3B,0x0302,-1,0x23,0x0000,-1,0x24,0x0000,-1,0x25,0x8000,-1,0x4f,0x0000, \ +-1,0x4e,0x0000,-1,0x22,-3 }; + +static int hx8340bn_init[] = { \ +-1,0xC1,0xFF,0x83,0x40,-1,0x11,-2,150,-1,0xCA,0x70,0x00,0xD9,-1,0xB0,0x01,0x11, \ +-1,0xC9,0x90,0x49,0x10,0x28,0x28,0x10,0x00,0x06,-2,20,-1,0xC2,0x60,0x71,0x01,0x0E,0x05,0x02,0x09,0x31,0x0A, \ +-1,0xC3,0x67,0x30,0x61,0x17,0x48,0x07,0x05,0x33,-2,10,-1,0xB5,0x35,0x20,0x45,-1,0xB4,0x33,0x25,0x4C,-2,10, \ +-1,0x3A,0x05,-1,0x29,-2,10,-3 }; + +static int ili9225_init[] = { \ +-1,0x0001,0x011C,-1,0x0002,0x0100,-1,0x0003,0x1030,-1,0x0008,0x0808,-1,0x000C,0x0000,-1,0x000F,0x0A01,-1,0x0020,0x0000, \ +-1,0x0021,0x0000,-2,50,-1,0x0010,0x0A00,-1,0x0011,0x1038,-2,50,-1,0x0012,0x1121,-1,0x0013,0x004E,-1,0x0014,0x676F, \ +-1,0x0030,0x0000,-1,0x0031,0x00DB,-1,0x0032,0x0000,-1,0x0033,0x0000,-1,0x0034,0x00DB,-1,0x0035,0x0000,-1,0x0036,0x00AF, \ +-1,0x0037,0x0000,-1,0x0038,0x00DB,-1,0x0039,0x0000,-1,0x0050,0x0000,-1,0x0051,0x060A,-1,0x0052,0x0D0A,-1,0x0053,0x0303, \ +-1,0x0054,0x0A0D,-1,0x0055,0x0A06,-1,0x0056,0x0000,-1,0x0057,0x0303,-1,0x0058,0x0000,-1,0x0059,0x0000,-2,50, \ +-1,0x0007,0x1017,-2,50,-3 }; + +static int ili9320_init[] = { \ +-1,0x00E5,0x8000,-1,0x0000,0x0001,-1,0x0001,0x0100,-1,0x0002,0x0700,-1,0x0003,0x1030,-1,0x0004,0x0000,-1,0x0008,0x0202, \ +-1,0x0009,0x0000,-1,0x000A,0x0000,-1,0x000C,0x0000,-1,0x000D,0x0000,-1,0x000F,0x0000,-1,0x0010,0x0000,-1,0x0011,0x0007, \ +-1,0x0012,0x0000,-1,0x0013,0x0000,-2,200,-1,0x0010,0x17B0,-1,0x0011,0x0031,-2,50,-1,0x0012,0x0138,-2,50,-1,0x0013,0x1800, \ +-1,0x0029,0x0008,-2,50,-1,0x0020,0x0000,-1,0x0021,0x0000,-1,0x0030,0x0000,-1,0x0031,0x0505,-1,0x0032,0x0004, \ +-1,0x0035,0x0006,-1,0x0036,0x0707,-1,0x0037,0x0105,-1,0x0038,0x0002,-1,0x0039,0x0707,-1,0x003C,0x0704,-1,0x003D,0x0807, \ +-1,0x0050,0x0000,-1,0x0051,0x00EF,-1,0x0052,0x0000,-1,0x0053,0x013F,-1,0x0060,0x2700,-1,0x0061,0x0001,-1,0x006A,0x0000, \ +-1,0x0080,0x0000,-1,0x0081,0x0000,-1,0x0082,0x0000,-1,0x0083,0x0000,-1,0x0084,0x0000,-1,0x0085,0x0000,-1,0x0090,0x0010, \ +-1,0x0092,0x0000,-1,0x0093,0x0003,-1,0x0095,0x0110,-1,0x0097,0x0000,-1,0x0098,0x0000,-1,0x0007,0x0173,-3 }; + +static int ili9325_init[] = { \ +-1,0x00E3,0x3008,-1,0x00E7,0x0012,-1,0x00EF,0x1231,-1,0x0001,0x0100,-1,0x0002,0x0700,-1,0x0003,0x1030,-1,0x0004,0x0000, \ +-1,0x0008,0x0207,-1,0x0009,0x0000,-1,0x000A,0x0000,-1,0x000C,0x0000,-1,0x000D,0x0000,-1,0x000F,0x0000,-1,0x0010,0x0000, \ +-1,0x0011,0x0007,-1,0x0012,0x0000,-1,0x0013,0x0000,-2,200,-1,0x0010,0x1690,-1,0x0011,0x0223,-2,50,-1,0x0012,0x000D,-2,50, \ +-1,0x0013,0x1200,-1,0x0029,0x000A,-1,0x002B,0x000C,-2,50,-1,0x0020,0x0000,-1,0x0021,0x0000,-1,0x0030,0x0000, \ +-1,0x0031,0x0506,-1,0x0032,0x0104,-1,0x0035,0x0207,-1,0x0036,0x000F,-1,0x0037,0x0306,-1,0x0038,0x0102,-1,0x0039,0x0707, \ +-1,0x003C,0x0702,-1,0x003D,0x1604,-1,0x0050,0x0000,-1,0x0051,0x00EF,-1,0x0052,0x0000,-1,0x0053,0x013F,-1,0x0060,0xA700, \ +-1,0x0061,0x0001,-1,0x006A,0x0000,-1,0x0080,0x0000,-1,0x0081,0x0000,-1,0x0082,0x0000,-1,0x0083,0x0000,-1,0x0084,0x0000, \ +-1,0x0085,0x0000,-1,0x0090,0x0010,-1,0x0092,0x0600,-1,0x0007,0x0133,-3 }; + +static int ili9341_init[] = { \ +-1,0x28,-2,20,-1,0xCF,0x00,0x83,0x30,-1,0xED,0x64,0x03,0x12,0x81,-1,0xE8,0x85,0x01,0x79, \ +-1,0xCB,0x39,0x2c,0x00,0x34,0x02,-1,0xF7,0x20,-1,0xEA,0x00,0x00,-1,0xC0,0x26,-1,0xC1,0x11, \ +-1,0xC5,0x35,0x3E,-1,0xC7,0xBE,-1,0xB1,0x00,0x1B,-1,0xB6,0x0a,0x82,0x27,0x00,-1,0xB7,0x07, \ +-1,0x3A,0x55,-1,0x36,0x48,-1,0x11,-2,120,-1,0x29,-2,20,-3 }; + +static int ssd1351_init[] = { -1,0xfd,0x12,-1,0xfd,0xb1,-1,0xae,-1,0xb3,0xf1,-1,0xca,0x7f,-1,0xa0,0x74, \ + -1,0x15,0x00,0x7f,-1,0x75,0x00,0x7f,-1,0xa1,0x00,-1,0xa2,0x00,-1,0xb5,0x00, \ + -1,0xab,0x01,-1,0xb1,0x32,-1,0xb4,0xa0,0xb5,0x55,-1,0xbb,0x17,-1,0xbe,0x05, \ + -1,0xc1,0xc8,0x80,0xc8,-1,0xc7,0x0f,-1,0xb6,0x01,-1,0xa6,-1,0xaf,-3 }; + + +/* ili9320, ili9325 */ +static void flexfb_set_addr_win_1(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + switch (par->info->var.rotate) { + /* R20h = Horizontal GRAM Start Address */ + /* R21h = Vertical GRAM Start Address */ + case 0: + write_reg(par, 0x0020, xs); + write_reg(par, 0x0021, ys); + break; + case 180: + write_reg(par, 0x0020, width - 1 - xs); + write_reg(par, 0x0021, height - 1 - ys); + break; + case 270: + write_reg(par, 0x0020, width - 1 - ys); + write_reg(par, 0x0021, xs); + break; + case 90: + write_reg(par, 0x0020, ys); + write_reg(par, 0x0021, height - 1 - xs); + break; + } + write_reg(par, 0x0022); /* Write Data to GRAM */ +} + +/* ssd1289 */ +static void flexfb_set_addr_win_2(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + switch (par->info->var.rotate) { + /* R4Eh - Set GDDRAM X address counter */ + /* R4Fh - Set GDDRAM Y address counter */ + case 0: + write_reg(par, 0x4e, xs); + write_reg(par, 0x4f, ys); + break; + case 180: + write_reg(par, 0x4e, par->info->var.xres - 1 - xs); + write_reg(par, 0x4f, par->info->var.yres - 1 - ys); + break; + case 270: + write_reg(par, 0x4e, par->info->var.yres - 1 - ys); + write_reg(par, 0x4f, xs); + break; + case 90: + write_reg(par, 0x4e, ys); + write_reg(par, 0x4f, par->info->var.xres - 1 - xs); + break; + } + + /* R22h - RAM data write */ + write_reg(par, 0x22, 0); +} + +/* ssd1351 */ +static void set_addr_win_3(struct fbtft_par *par, int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + + write_reg(par, 0x15, xs, xe); + write_reg(par, 0x75, ys, ye); + write_reg(par, 0x5C); +} + +static int flexfb_verify_gpios_dc(struct fbtft_par *par) +{ + fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__); + + if (par->gpio.dc < 0) { + dev_err(par->info->device, "Missing info about 'dc' gpio. Aborting.\n"); + return -EINVAL; + } + + return 0; +} + +static int flexfb_verify_gpios_db(struct fbtft_par *par) +{ + int i; + int num_db = buswidth; + + fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__); + + if (par->gpio.dc < 0) { + dev_err(par->info->device, "Missing info about 'dc' gpio. Aborting.\n"); + return -EINVAL; + } + if (par->gpio.wr < 0) { + dev_err(par->info->device, "Missing info about 'wr' gpio. Aborting.\n"); + return -EINVAL; + } + if (latched && (par->gpio.latch < 0)) { + dev_err(par->info->device, "Missing info about 'latch' gpio. Aborting.\n"); + return -EINVAL; + } + if (latched) + num_db=buswidth/2; + for (i=0;i < num_db;i++) { + if (par->gpio.db[i] < 0) { + dev_err(par->info->device, "Missing info about 'db%02d' gpio. Aborting.\n", i); + return -EINVAL; + } + } + + return 0; +} + +static struct fbtft_display flex_display = { }; + +static int flexfb_probe_common(struct spi_device *sdev, struct platform_device *pdev) +{ + struct device *dev; + struct fb_info *info; + struct fbtft_par *par; + int ret; + + initp = init; + initp_num = init_num; + + if (sdev) + dev = &sdev->dev; + else + dev = &pdev->dev; + + fbtft_init_dbg(dev, "%s(%s)\n", __func__, sdev ? "'SPI device'" : "'Platform device'"); + + if (chip) { + + if (!strcmp(chip, "st7735r")) { + if (!width) + width = 128; + if (!height) + height = 160; + if (init_num == 0) { + initp = st7735r_init; + initp_num = ARRAY_SIZE(st7735r_init); + } + + + } else if (!strcmp(chip, "hx8340bn")) { + if (!width) + width = 176; + if (!height) + height = 220; + setaddrwin = 0; + if (init_num == 0) { + initp = hx8340bn_init; + initp_num = ARRAY_SIZE(hx8340bn_init); + } + + + } else if (!strcmp(chip, "ili9225")) { + if (!width) + width = 176; + if (!height) + height = 220; + setaddrwin = 0; + regwidth = 16; + if (init_num == 0) { + initp = ili9225_init; + initp_num = ARRAY_SIZE(ili9225_init); + } + + + + } else if (!strcmp(chip, "ili9320")) { + if (!width) + width = 240; + if (!height) + height = 320; + setaddrwin = 1; + regwidth = 16; + if (init_num == 0) { + initp = ili9320_init; + initp_num = ARRAY_SIZE(ili9320_init); + } + + + } else if (!strcmp(chip, "ili9325")) { + if (!width) + width = 240; + if (!height) + height = 320; + setaddrwin = 1; + regwidth = 16; + if (init_num == 0) { + initp = ili9325_init; + initp_num = ARRAY_SIZE(ili9325_init); + } + + } else if (!strcmp(chip, "ili9341")) { + if (!width) + width = 240; + if (!height) + height = 320; + setaddrwin = 0; + regwidth = 8; + if (init_num == 0) { + initp = ili9341_init; + initp_num = ARRAY_SIZE(ili9341_init); + } + + + } else if (!strcmp(chip, "ssd1289")) { + if (!width) + width = 240; + if (!height) + height = 320; + setaddrwin = 2; + regwidth = 16; + if (init_num == 0) { + initp = ssd1289_init; + initp_num = ARRAY_SIZE(ssd1289_init); + } + + + + } else if (!strcmp(chip, "ssd1351")) { + if (!width) + width = 128; + if (!height) + height = 128; + setaddrwin = 3; + if (init_num == 0) { + initp = ssd1351_init; + initp_num = ARRAY_SIZE(ssd1351_init); + } + } else { + dev_err(dev, "chip=%s is not supported\n", chip); + return -EINVAL; + } + } + + if (width == 0 || height == 0) { + dev_err(dev, "argument(s) missing: width and height has to be set.\n"); + return -EINVAL; + } + flex_display.width = width; + flex_display.height = height; + fbtft_init_dbg(dev, "Display resolution: %dx%d\n", width, height); + fbtft_init_dbg(dev, "chip = %s\n", chip ? chip : "not set"); + fbtft_init_dbg(dev, "setaddrwin = %d\n", setaddrwin); + fbtft_init_dbg(dev, "regwidth = %d\n", regwidth); + fbtft_init_dbg(dev, "buswidth = %d\n", buswidth); + + info = fbtft_framebuffer_alloc(&flex_display, dev); + if (!info) + return -ENOMEM; + + par = info->par; + if (sdev) + par->spi = sdev; + else + par->pdev = pdev; + if (!par->init_sequence) + par->init_sequence = initp; + par->fbtftops.init_display = fbtft_init_display; + + /* registerwrite functions */ + switch (regwidth) { + case 8: + par->fbtftops.write_register = fbtft_write_reg8_bus8; + break; + case 16: + par->fbtftops.write_register = fbtft_write_reg16_bus8; + break; + default: + dev_err(dev, "argument 'regwidth': %d is not supported.\n", regwidth); + return -EINVAL; + } + + /* bus functions */ + if (sdev) { + par->fbtftops.write = fbtft_write_spi; + switch (buswidth) { + case 8: + par->fbtftops.write_vmem = fbtft_write_vmem16_bus8; + if (!par->startbyte) + par->fbtftops.verify_gpios = flexfb_verify_gpios_dc; + break; + case 9: + if (regwidth == 16) { + dev_err(dev, "argument 'regwidth': %d is not supported with buswidth=%d and SPI.\n", regwidth, buswidth); + return -EINVAL; + } + par->fbtftops.write_register = fbtft_write_reg8_bus9; + par->fbtftops.write_vmem = fbtft_write_vmem16_bus9; + sdev->bits_per_word=9; + ret = sdev->master->setup(sdev); + if (ret) { + dev_warn(dev, + "9-bit SPI not available, emulating using 8-bit.\n"); + sdev->bits_per_word = 8; + ret = sdev->master->setup(sdev); + if (ret) + goto out_release; + /* allocate buffer with room for dc bits */ + par->extra = devm_kzalloc(par->info->device, + par->txbuf.len + (par->txbuf.len / 8) + 8, + GFP_KERNEL); + if (!par->extra) { + ret = -ENOMEM; + goto out_release; + } + par->fbtftops.write = fbtft_write_spi_emulate_9; + } + break; + default: + dev_err(dev, "argument 'buswidth': %d is not supported with SPI.\n", buswidth); + return -EINVAL; + } + } else { + par->fbtftops.verify_gpios = flexfb_verify_gpios_db; + switch (buswidth) { + case 8: + par->fbtftops.write = fbtft_write_gpio8_wr; + par->fbtftops.write_vmem = fbtft_write_vmem16_bus8; + break; + case 16: + par->fbtftops.write_register = fbtft_write_reg16_bus16; + if (latched) + par->fbtftops.write = fbtft_write_gpio16_wr_latched; + else + par->fbtftops.write = fbtft_write_gpio16_wr; + par->fbtftops.write_vmem = fbtft_write_vmem16_bus16; + break; + default: + dev_err(dev, "argument 'buswidth': %d is not supported with parallel.\n", buswidth); + return -EINVAL; + } + } + + /* set_addr_win function */ + switch (setaddrwin) { + case 0: + /* use default */ + break; + case 1: + par->fbtftops.set_addr_win = flexfb_set_addr_win_1; + break; + case 2: + par->fbtftops.set_addr_win = flexfb_set_addr_win_2; + break; + case 3: + par->fbtftops.set_addr_win = set_addr_win_3; + break; + default: + dev_err(dev, "argument 'setaddrwin': unknown value %d.\n", setaddrwin); + return -EINVAL; + } + + if (!nobacklight) + par->fbtftops.register_backlight = fbtft_register_backlight; + + ret = fbtft_register_framebuffer(info); + if (ret < 0) + goto out_release; + + return 0; + +out_release: + fbtft_framebuffer_release(info); + + return ret; +} + +static int flexfb_remove_common(struct device *dev, struct fb_info *info) +{ + struct fbtft_par *par; + + if (!info) + return -EINVAL; + par = info->par; + if (par) + fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, par, + "%s()\n", __func__); + fbtft_unregister_framebuffer(info); + fbtft_framebuffer_release(info); + + return 0; +} + +static int flexfb_probe_spi(struct spi_device *spi) +{ + return flexfb_probe_common(spi, NULL); +} + +static int flexfb_remove_spi(struct spi_device *spi) +{ + struct fb_info *info = spi_get_drvdata(spi); + + return flexfb_remove_common(&spi->dev, info); +} + +static int flexfb_probe_pdev(struct platform_device *pdev) +{ + return flexfb_probe_common(NULL, pdev); +} + +static int flexfb_remove_pdev(struct platform_device *pdev) +{ + struct fb_info *info = platform_get_drvdata(pdev); + + return flexfb_remove_common(&pdev->dev, info); +} + +static struct spi_driver flexfb_spi_driver = { + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, + .probe = flexfb_probe_spi, + .remove = flexfb_remove_spi, +}; + +static const struct platform_device_id flexfb_platform_ids[] = { + { "flexpfb", 0 }, + { }, +}; + +static struct platform_driver flexfb_platform_driver = { + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, + .id_table = flexfb_platform_ids, + .probe = flexfb_probe_pdev, + .remove = flexfb_remove_pdev, +}; + +static int __init flexfb_init(void) +{ + int ret, ret2; + + ret = spi_register_driver(&flexfb_spi_driver); + ret2 = platform_driver_register(&flexfb_platform_driver); + if (ret < 0) + return ret; + return ret2; +} + +static void __exit flexfb_exit(void) +{ + spi_unregister_driver(&flexfb_spi_driver); + platform_driver_unregister(&flexfb_platform_driver); +} + +/* ------------------------------------------------------------------------- */ + +module_init(flexfb_init); +module_exit(flexfb_exit); + +MODULE_DESCRIPTION("Generic FB driver for TFT LCD displays"); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 06d30f0208576f3cf2a0ee2072c1408e392038b4 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 31 Dec 2014 10:11:36 +0100 Subject: staging: fbtft: add fbtft_device driver This commit adds the fbtft_device driver from the fbtft project at https://github.com/notro/fbtft. Signed-off-by: Thomas Petazzoni Signed-off-by: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig index d7ddd6e..995a910 100644 --- a/drivers/staging/fbtft/Kconfig +++ b/drivers/staging/fbtft/Kconfig @@ -163,3 +163,7 @@ config FB_FLEX depends on FB_TFT help Generic Framebuffer support for TFT LCD displays. + +config FB_TFT_FBTFT_DEVICE + tristate "Module to for adding FBTFT devices" + depends on FB_TFT diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile index 5b3254a..e773f0f 100644 --- a/drivers/staging/fbtft/Makefile +++ b/drivers/staging/fbtft/Makefile @@ -29,3 +29,6 @@ obj-$(CONFIG_FB_TFT_UC1701) += fb_uc1701.o obj-$(CONFIG_FB_TFT_UPD161704) += fb_upd161704.o obj-$(CONFIG_FB_TFT_WATTEROTT) += fb_watterott.o obj-$(CONFIG_FB_FLEX) += flexfb.o + +# Device modules +obj-$(CONFIG_FB_TFT_FBTFT_DEVICE) += fbtft_device.o diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c new file mode 100644 index 0000000..b9f4c30 --- /dev/null +++ b/drivers/staging/fbtft/fbtft_device.c @@ -0,0 +1,1444 @@ +/* + * + * Copyright (C) 2013, Noralf Tronnes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + +#include "fbtft.h" + +#define DRVNAME "fbtft_device" + +#define MAX_GPIOS 32 + +struct spi_device *spi_device; +struct platform_device *p_device; + +static char *name; +module_param(name, charp, 0); +MODULE_PARM_DESC(name, "Devicename (required). " \ +"name=list => list all supported devices."); + +static unsigned rotate; +module_param(rotate, uint, 0); +MODULE_PARM_DESC(rotate, +"Angle to rotate display counter clockwise: 0, 90, 180, 270"); + +static unsigned busnum; +module_param(busnum, uint, 0); +MODULE_PARM_DESC(busnum, "SPI bus number (default=0)"); + +static unsigned cs; +module_param(cs, uint, 0); +MODULE_PARM_DESC(cs, "SPI chip select (default=0)"); + +static unsigned speed; +module_param(speed, uint, 0); +MODULE_PARM_DESC(speed, "SPI speed (override device default)"); + +static int mode = -1; +module_param(mode, int, 0); +MODULE_PARM_DESC(mode, "SPI mode (override device default)"); + +static char *gpios; +module_param(gpios, charp, 0); +MODULE_PARM_DESC(gpios, +"List of gpios. Comma separated with the form: reset:23,dc:24 " \ +"(when overriding the default, all gpios must be specified)"); + +static unsigned fps; +module_param(fps, uint, 0); +MODULE_PARM_DESC(fps, "Frames per second (override driver default)"); + +static char *gamma; +module_param(gamma, charp, 0); +MODULE_PARM_DESC(gamma, +"String representation of Gamma Curve(s). Driver specific."); + +static int txbuflen; +module_param(txbuflen, int, 0); +MODULE_PARM_DESC(txbuflen, "txbuflen (override driver default)"); + +static int bgr = -1; +module_param(bgr, int, 0); +MODULE_PARM_DESC(bgr, +"BGR bit (supported by some drivers)."); + +static unsigned startbyte; +module_param(startbyte, uint, 0); +MODULE_PARM_DESC(startbyte, "Sets the Start byte used by some SPI displays."); + +static bool custom; +module_param(custom, bool, 0); +MODULE_PARM_DESC(custom, "Add a custom display device. " \ +"Use speed= argument to make it a SPI device, else platform_device"); + +static unsigned width; +module_param(width, uint, 0); +MODULE_PARM_DESC(width, "Display width, used with the custom argument"); + +static unsigned height; +module_param(height, uint, 0); +MODULE_PARM_DESC(height, "Display height, used with the custom argument"); + +static unsigned buswidth = 8; +module_param(buswidth, uint, 0); +MODULE_PARM_DESC(buswidth, "Display bus width, used with the custom argument"); + +static int init[FBTFT_MAX_INIT_SEQUENCE]; +static int init_num; +module_param_array(init, int, &init_num, 0); +MODULE_PARM_DESC(init, "Init sequence, used with the custom argument"); + +static unsigned long debug; +module_param(debug, ulong , 0); +MODULE_PARM_DESC(debug, +"level: 0-7 (the remaining 29 bits is for advanced usage)"); + +static unsigned verbose = 3; +module_param(verbose, uint, 0); +MODULE_PARM_DESC(verbose, +"0 silent, >0 show gpios, >1 show devices, >2 show devices before (default=3)"); + + +struct fbtft_device_display { + char *name; + struct spi_board_info *spi; + struct platform_device *pdev; +}; + +static void fbtft_device_pdev_release(struct device *dev); + +static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len); +static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par, + int xs, int ys, int xe, int ye); + +#define ADAFRUIT18_GAMMA \ + "02 1c 07 12 37 32 29 2d 29 25 2B 39 00 01 03 10\n" \ + "03 1d 07 06 2E 2C 29 2D 2E 2E 37 3F 00 00 02 10" + +static int hy28b_init_sequence[] = { + -1,0x00e7,0x0010,-1,0x0000,0x0001,-1,0x0001,0x0100,-1,0x0002,0x0700, + -1,0x0003,0x1030,-1,0x0004,0x0000,-1,0x0008,0x0207,-1,0x0009,0x0000, + -1,0x000a,0x0000,-1,0x000c,0x0001,-1,0x000d,0x0000,-1,0x000f,0x0000, + -1,0x0010,0x0000,-1,0x0011,0x0007,-1,0x0012,0x0000,-1,0x0013,0x0000, + -2,50,-1,0x0010,0x1590,-1,0x0011,0x0227,-2,50,-1,0x0012,0x009c,-2,50, + -1,0x0013,0x1900,-1,0x0029,0x0023,-1,0x002b,0x000e,-2,50, + -1,0x0020,0x0000,-1,0x0021,0x0000,-2,50,-1,0x0050,0x0000, + -1,0x0051,0x00ef,-1,0x0052,0x0000,-1,0x0053,0x013f,-1,0x0060,0xa700, + -1,0x0061,0x0001,-1,0x006a,0x0000,-1,0x0080,0x0000,-1,0x0081,0x0000, + -1,0x0082,0x0000,-1,0x0083,0x0000,-1,0x0084,0x0000,-1,0x0085,0x0000, + -1,0x0090,0x0010,-1,0x0092,0x0000,-1,0x0093,0x0003,-1,0x0095,0x0110, + -1,0x0097,0x0000,-1,0x0098,0x0000,-1,0x0007,0x0133,-1,0x0020,0x0000, + -1,0x0021,0x0000,-2,100,-3 }; + +#define HY28B_GAMMA \ + "04 1F 4 7 7 0 7 7 6 0\n" \ + "0F 00 1 7 4 0 0 0 6 7" + +static int pitft_init_sequence[] = { + -1,0x01,-2,5,-1,0x28,-1,0xEF,0x03,0x80,0x02,-1,0xCF,0x00,0xC1,0x30, + -1,0xED,0x64,0x03,0x12,0x81,-1,0xE8,0x85,0x00,0x78, + -1,0xCB,0x39,0x2C,0x00,0x34,0x02,-1,0xF7,0x20,-1,0xEA,0x00,0x00, + -1,0xC0,0x23,-1,0xC1,0x10,-1,0xC5,0x3e,0x28,-1,0xC7,0x86,-1,0x3A,0x55, + -1,0xB1,0x00,0x18,-1,0xB6,0x08,0x82,0x27,-1,0xF2,0x00,-1,0x26,0x01, + -1,0xE0,0x0F,0x31,0x2B,0x0C,0x0E,0x08,0x4E,0xF1,0x37,0x07,0x10,0x03, + 0x0E,0x09,0x00,-1,0xE1,0x00,0x0E,0x14,0x03,0x11,0x07,0x31,0xC1,0x48, + 0x08,0x0F,0x0C,0x31,0x36,0x0F,-1,0x11,-2,100,-1,0x29,-2,20,-3 }; + +static int waveshare32b_init_sequence[] = { + -1,0xCB,0x39,0x2C,0x00,0x34,0x02,-1,0xCF,0x00,0xC1,0x30, + -1,0xE8,0x85,0x00,0x78,-1,0xEA,0x00,0x00,-1,0xED,0x64,0x03,0x12,0x81, + -1,0xF7,0x20,-1,0xC0,0x23,-1,0xC1,0x10,-1,0xC5,0x3e,0x28,-1,0xC7,0x86, + -1,0x36,0x28,-1,0x3A,0x55,-1,0xB1,0x00,0x18,-1,0xB6,0x08,0x82,0x27, + -1,0xF2,0x00,-1,0x26,0x01, + -1,0xE0,0x0F,0x31,0x2B,0x0C,0x0E,0x08,0x4E,0xF1,0x37,0x07,0x10,0x03,0x0E,0x09,0x00, + -1,0xE1,0x00,0x0E,0x14,0x03,0x11,0x07,0x31,0xC1,0x48,0x08,0x0F,0x0C,0x31,0x36,0x0F, + -1,0x11,-2,120,-1,0x29,-1,0x2c,-3 }; + +/* Supported displays in alphabetical order */ +static struct fbtft_device_display displays[] = { + { + .name = "adafruit18", + .spi = &(struct spi_board_info) { + .modalias = "fb_st7735r", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + .gamma = ADAFRUIT18_GAMMA, + } + } + }, { + .name = "adafruit18_green", + .spi = &(struct spi_board_info) { + .modalias = "fb_st7735r", + .max_speed_hz = 4000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .fbtftops.set_addr_win = \ + adafruit18_green_tab_set_addr_win, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + .gamma = ADAFRUIT18_GAMMA, + } + } + }, { + .name = "adafruit22", + .spi = &(struct spi_board_info) { + .modalias = "fb_hx8340bn", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 9, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "led", 23 }, + {}, + }, + } + } + }, { + .name = "adafruit22a", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9340", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "adafruit28", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9341", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "adafruit13m", + .spi = &(struct spi_board_info) { + .modalias = "fb_ssd1306", + .max_speed_hz = 16000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "agm1264k-fl", + .pdev = &(struct platform_device) { + .name = "fb_agm1264k-fl", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = FBTFT_ONBOARD_BACKLIGHT, + }, + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + } + } + }, { + .name = "dogs102", + .spi = &(struct spi_board_info) { + .modalias = "fb_uc1701", + .max_speed_hz = 8000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 13 }, + { "dc", 6 }, + {}, + }, + } + } + }, { + .name = "er_tftm050_2", + .spi = &(struct spi_board_info) { + .modalias = "fb_ra8875", + .max_speed_hz = 5000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .width = 480, + .height = 272, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "er_tftm070_5", + .spi = &(struct spi_board_info) { + .modalias = "fb_ra8875", + .max_speed_hz = 5000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .width = 800, + .height = 480, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "flexfb", + .spi = &(struct spi_board_info) { + .modalias = "flexfb", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "flexpfb", + .pdev = &(struct platform_device) { + .name = "flexpfb", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + { "reset", 17 }, + { "dc", 1 }, + { "wr", 0 }, + { "cs", 21 }, + { "db00", 9 }, + { "db01", 11 }, + { "db02", 18 }, + { "db03", 23 }, + { "db04", 24 }, + { "db05", 25 }, + { "db06", 8 }, + { "db07", 7 }, + { "led", 4 }, + {}, + }, + }, + } + } + }, { + .name = "freetronicsoled128", + .spi = &(struct spi_board_info) { + .modalias = "fb_ssd1351", + .max_speed_hz = 20000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = FBTFT_ONBOARD_BACKLIGHT, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 24 }, + { "dc", 25 }, + {}, + }, + } + } + }, { + .name = "hx8353d", + .spi = &(struct spi_board_info) { + .modalias = "fb_hx8353d", + .max_speed_hz = 16000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 23 }, + {}, + }, + } + } + }, { + .name = "hy28a", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9320", + .max_speed_hz = 32000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .startbyte = 0b01110000, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "hy28b", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9325", + .max_speed_hz = 48000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .init_sequence = hy28b_init_sequence, + }, + .startbyte = 0b01110000, + .bgr = true, + .fps= 50, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "led", 18 }, + {}, + }, + .gamma = HY28B_GAMMA, + } + } + }, { + .name = "ili9481", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9481", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .regwidth = 16, + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 22 }, + {}, + }, + } + } + }, { + .name = "itdb24", + .pdev = &(struct platform_device) { + .name = "fb_s6d1121", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = false, + .gpios = (const struct fbtft_gpio []) { + /* Wiring for LCD adapter kit */ + { "reset", 7 }, + { "dc", 0 }, /* rev 2: 2 */ + { "wr", 1 }, /* rev 2: 3 */ + { "cs", 8 }, + { "db00", 17 }, + { "db01", 18 }, + { "db02", 21 }, /* rev 2: 27 */ + { "db03", 22 }, + { "db04", 23 }, + { "db05", 24 }, + { "db06", 25 }, + { "db07", 4 }, + {} + }, + }, + } + } + }, { + .name = "itdb28", + .pdev = &(struct platform_device) { + .name = "fb_ili9325", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + } + } + }, { + .name = "itdb28_spi", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9325", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "mi0283qt-2", + .spi = &(struct spi_board_info) { + .modalias = "fb_hx8347d", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .startbyte = 0b01110000, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "mi0283qt-9a", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9341", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 9, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "mi0283qt-v2", + .spi = &(struct spi_board_info) { + .modalias = "fb_watterott", + .max_speed_hz = 4000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + {}, + }, + } + } + }, { + .name = "nokia3310", + .spi = &(struct spi_board_info) { + .modalias = "fb_pcd8544", + .max_speed_hz = 400000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 23 }, + {}, + }, + } + } + }, { + .name = "nokia3310a", + .spi = &(struct spi_board_info) { + .modalias = "fb_tls8204", + .max_speed_hz = 1000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 23 }, + {}, + }, + } + } + }, { + .name = "piscreen", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9486", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .regwidth = 16, + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 22 }, + {}, + }, + } + } + }, { + .name = "pitft", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9340", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .chip_select = 0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .init_sequence = pitft_init_sequence, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "dc", 25 }, + {}, + }, + } + } + }, { + .name = "pioled", + .spi = &(struct spi_board_info) { + .modalias = "fb_ssd1351", + .max_speed_hz = 20000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 24 }, + { "dc", 25 }, + {}, + }, + .gamma = "0 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 2 " \ + "2 2 2 2 2 2 2 3 " \ + "3 3 3 3 3 3 3 3 " \ + "3 3 3 3 3 3 3 3 " \ + "3 3 3 4 4 4 4 4 " \ + "4 4 4 4 4 4 4" + } + } + }, { + .name = "rpi-display", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9341", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 23 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "s6d02a1", + .spi = &(struct spi_board_info) { + .modalias = "fb_s6d02a1", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 23 }, + {}, + }, + } + } + }, { + .name = "sainsmart18", + .spi = &(struct spi_board_info) { + .modalias = "fb_st7735r", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "sainsmart32", + .pdev = &(struct platform_device) { + .name = "fb_ssd1289", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 16, + .txbuflen = -2, /* disable buffer */ + .backlight = 1, + .fbtftops.write = write_gpio16_wr_slow, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + }, + } + }, { + .name = "sainsmart32_fast", + .pdev = &(struct platform_device) { + .name = "fb_ssd1289", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 16, + .txbuflen = -2, /* disable buffer */ + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + }, + } + }, { + .name = "sainsmart32_latched", + .pdev = &(struct platform_device) { + .name = "fb_ssd1289", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 16, + .txbuflen = -2, /* disable buffer */ + .backlight = 1, + .fbtftops.write = \ + fbtft_write_gpio16_wr_latched, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + }, + } + }, { + .name = "sainsmart32_spi", + .spi = &(struct spi_board_info) { + .modalias = "fb_ssd1289", + .max_speed_hz = 16000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + {}, + }, + } + } + }, { + .name = "spidev", + .spi = &(struct spi_board_info) { + .modalias = "spidev", + .max_speed_hz = 500000, + .bus_num = 0, + .chip_select = 0, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + {}, + }, + } + } + }, { + .name = "ssd1331", + .spi = &(struct spi_board_info) { + .modalias = "fb_ssd1331", + .max_speed_hz = 20000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 24 }, + { "dc", 25 }, + {}, + }, + } + } + }, { + .name = "tinylcd35", + .spi = &(struct spi_board_info) { + .modalias = "fb_tinylcd", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "tm022hdh26", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9341", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 25 }, + { "dc", 24 }, + { "led", 18 }, + {}, + }, + } + } + }, { + .name = "tontec35_9481", /* boards before 02 July 2014 */ + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9481", + .max_speed_hz = 128000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 15 }, + { "dc", 25 }, + { "led_", 18 }, + {}, + }, + } + } + }, { + .name = "tontec35_9486", /* boards after 02 July 2014 */ + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9486", + .max_speed_hz = 128000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 15 }, + { "dc", 25 }, + { "led_", 18 }, + {}, + }, + } + } + }, { + .name = "upd161704", + .spi = &(struct spi_board_info) { + .modalias = "fb_upd161704", + .max_speed_hz = 32000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 24 }, + { "dc", 25 }, + {}, + }, + } + } + }, { + .name = "waveshare32b", + .spi = &(struct spi_board_info) { + .modalias = "fb_ili9340", + .max_speed_hz = 48000000, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + .backlight = 1, + .init_sequence = waveshare32b_init_sequence, + }, + .bgr = true, + .gpios = (const struct fbtft_gpio []) { + { "reset", 27 }, + { "dc", 22 }, + {}, + }, + } + } + }, { + .name = "waveshare22", + .spi = &(struct spi_board_info) { + .modalias = "fb_bd663474", + .max_speed_hz = 32000000, + .mode = SPI_MODE_3, + .platform_data = &(struct fbtft_platform_data) { + .display = { + .buswidth = 8, + }, + .gpios = (const struct fbtft_gpio []) { + { "reset", 24 }, + { "dc", 25 }, + {}, + }, + } + } + }, { + /* This should be the last item. + Used with the custom argument */ + .name = "", + .spi = &(struct spi_board_info) { + .modalias = "", + .max_speed_hz = 0, + .mode = SPI_MODE_0, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + {}, + }, + } + }, + .pdev = &(struct platform_device) { + .name = "", + .id = 0, + .dev = { + .release = fbtft_device_pdev_release, + .platform_data = &(struct fbtft_platform_data) { + .gpios = (const struct fbtft_gpio []) { + {}, + }, + }, + }, + }, + } +}; + +static int write_gpio16_wr_slow(struct fbtft_par *par, void *buf, size_t len) +{ + u16 data; + int i; +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + static u16 prev_data; +#endif + + fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, + "%s(len=%d): ", __func__, len); + + while (len) { + data = *(u16 *) buf; + + /* Start writing by pulling down /WR */ + gpio_set_value(par->gpio.wr, 0); + + /* Set data */ +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + if (data == prev_data) { + gpio_set_value(par->gpio.wr, 0); /* used as delay */ + } else { + for (i = 0; i < 16; i++) { + if ((data & 1) != (prev_data & 1)) + gpio_set_value(par->gpio.db[i], + (data & 1)); + data >>= 1; + prev_data >>= 1; + } + } +#else + for (i = 0; i < 16; i++) { + gpio_set_value(par->gpio.db[i], (data & 1)); + data >>= 1; + } +#endif + + /* Pullup /WR */ + gpio_set_value(par->gpio.wr, 1); + +#ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO + prev_data = *(u16 *) buf; +#endif + buf += 2; + len -= 2; + } + + return 0; +} + +static void adafruit18_green_tab_set_addr_win(struct fbtft_par *par, + int xs, int ys, int xe, int ye) +{ + fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, + "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); + write_reg(par, 0x2A, 0, xs + 2, 0, xe + 2); + write_reg(par, 0x2B, 0, ys + 1, 0, ye + 1); + write_reg(par, 0x2C); +} + +/* used if gpios parameter is present */ +static struct fbtft_gpio fbtft_device_param_gpios[MAX_GPIOS+1] = { }; + +static void fbtft_device_pdev_release(struct device *dev) +{ +/* Needed to silence this message: +Device 'xxx' does not have a release() function, it is broken and must be fixed +*/ +} + +static int spi_device_found(struct device *dev, void *data) +{ + struct spi_device *spi = container_of(dev, struct spi_device, dev); + + pr_info(DRVNAME": %s %s %dkHz %d bits mode=0x%02X\n", + spi->modalias, dev_name(dev), spi->max_speed_hz/1000, + spi->bits_per_word, spi->mode); + + return 0; +} + +static void pr_spi_devices(void) +{ + pr_info(DRVNAME": SPI devices registered:\n"); + bus_for_each_dev(&spi_bus_type, NULL, NULL, spi_device_found); +} + +static int p_device_found(struct device *dev, void *data) +{ + struct platform_device + *pdev = container_of(dev, struct platform_device, dev); + + if (strstr(pdev->name, "fb")) + pr_info(DRVNAME": %s id=%d pdata? %s\n", + pdev->name, pdev->id, + pdev->dev.platform_data ? "yes" : "no"); + + return 0; +} + +static void pr_p_devices(void) +{ + pr_info(DRVNAME": 'fb' Platform devices registered:\n"); + bus_for_each_dev(&platform_bus_type, NULL, NULL, p_device_found); +} + +#ifdef MODULE +static void fbtft_device_spi_delete(struct spi_master *master, unsigned cs) +{ + struct device *dev; + char str[32]; + + snprintf(str, sizeof(str), "%s.%u", dev_name(&master->dev), cs); + + dev = bus_find_device_by_name(&spi_bus_type, NULL, str); + if (dev) { + if (verbose) + pr_info(DRVNAME": Deleting %s\n", str); + device_del(dev); + } +} + +static int fbtft_device_spi_device_register(struct spi_board_info *spi) +{ + struct spi_master *master; + + master = spi_busnum_to_master(spi->bus_num); + if (!master) { + pr_err(DRVNAME ": spi_busnum_to_master(%d) returned NULL\n", + spi->bus_num); + return -EINVAL; + } + /* make sure it's available */ + fbtft_device_spi_delete(master, spi->chip_select); + spi_device = spi_new_device(master, spi); + put_device(&master->dev); + if (!spi_device) { + pr_err(DRVNAME ": spi_new_device() returned NULL\n"); + return -EPERM; + } + return 0; +} +#else +static int fbtft_device_spi_device_register(struct spi_board_info *spi) +{ + return spi_register_board_info(spi, 1); +} +#endif + +static int __init fbtft_device_init(void) +{ + struct spi_board_info *spi = NULL; + struct fbtft_platform_data *pdata; + const struct fbtft_gpio *gpio = NULL; + char *p_gpio, *p_name, *p_num; + bool found = false; + int i = 0; + long val; + int ret = 0; + + pr_debug("\n\n"DRVNAME": init\n"); + + if (name == NULL) { +#ifdef MODULE + pr_err(DRVNAME": missing module parameter: 'name'\n"); + return -EINVAL; +#else + return 0; +#endif + } + + if (init_num > FBTFT_MAX_INIT_SEQUENCE) { + pr_err(DRVNAME \ + ": init parameter: exceeded max array size: %d\n", + FBTFT_MAX_INIT_SEQUENCE); + return -EINVAL; + } + + /* parse module parameter: gpios */ + while ((p_gpio = strsep(&gpios, ","))) { + if (strchr(p_gpio, ':') == NULL) { + pr_err(DRVNAME \ + ": error: missing ':' in gpios parameter: %s\n", + p_gpio); + return -EINVAL; + } + p_num = p_gpio; + p_name = strsep(&p_num, ":"); + if (p_name == NULL || p_num == NULL) { + pr_err(DRVNAME \ + ": something bad happened parsing gpios parameter: %s\n", + p_gpio); + return -EINVAL; + } + ret = kstrtol(p_num, 10, &val); + if (ret) { + pr_err(DRVNAME \ + ": could not parse number in gpios parameter: %s:%s\n", + p_name, p_num); + return -EINVAL; + } + strcpy(fbtft_device_param_gpios[i].name, p_name); + fbtft_device_param_gpios[i++].gpio = (int) val; + if (i == MAX_GPIOS) { + pr_err(DRVNAME \ + ": gpios parameter: exceeded max array size: %d\n", + MAX_GPIOS); + return -EINVAL; + } + } + if (fbtft_device_param_gpios[0].name[0]) + gpio = fbtft_device_param_gpios; + + if (verbose > 2) + pr_spi_devices(); /* print list of registered SPI devices */ + + if (verbose > 2) + pr_p_devices(); /* print list of 'fb' platform devices */ + + pr_debug(DRVNAME": name='%s', busnum=%d, cs=%d\n", name, busnum, cs); + + if (rotate > 0 && rotate < 4) { + rotate = (4 - rotate) * 90; + pr_warn("argument 'rotate' should be an angle. Values 1-3 is deprecated. Setting it to %d.\n", + rotate); + } + if (rotate != 0 && rotate != 90 && rotate != 180 && rotate != 270) { + pr_warn("argument 'rotate' illegal value: %d. Setting it to 0.\n", + rotate); + rotate = 0; + } + + /* name=list lists all supported displays */ + if (strncmp(name, "list", 32) == 0) { + pr_info(DRVNAME": Supported displays:\n"); + + for (i = 0; i < ARRAY_SIZE(displays); i++) + pr_info(DRVNAME": %s\n", displays[i].name); + return -ECANCELED; + } + + if (custom) { + i = ARRAY_SIZE(displays) - 1; + displays[i].name = name; + if (speed == 0) { + displays[i].pdev->name = name; + displays[i].spi = NULL; + } else { + strncpy(displays[i].spi->modalias, name, SPI_NAME_SIZE); + displays[i].pdev = NULL; + } + } + + for (i = 0; i < ARRAY_SIZE(displays); i++) { + if (strncmp(name, displays[i].name, 32) == 0) { + if (displays[i].spi) { + spi = displays[i].spi; + spi->chip_select = cs; + spi->bus_num = busnum; + if (speed) + spi->max_speed_hz = speed; + if (mode != -1) + spi->mode = mode; + pdata = (void *)spi->platform_data; + } else if (displays[i].pdev) { + p_device = displays[i].pdev; + pdata = p_device->dev.platform_data; + } else { + pr_err(DRVNAME": broken displays array\n"); + return -EINVAL; + } + + pdata->rotate = rotate; + if (bgr == 0) + pdata->bgr = false; + else if (bgr == 1) + pdata->bgr = true; + if (startbyte) + pdata->startbyte = startbyte; + if (gamma) + pdata->gamma = gamma; + pdata->display.debug = debug; + if (fps) + pdata->fps = fps; + if (txbuflen) + pdata->txbuflen = txbuflen; + if (init_num) + pdata->display.init_sequence = init; + if (gpio) + pdata->gpios = gpio; + if (custom) { + pdata->display.width = width; + pdata->display.height = height; + pdata->display.buswidth = buswidth; + pdata->display.backlight = 1; + } + + if (displays[i].spi) { + ret = fbtft_device_spi_device_register(spi); + if (ret) { + pr_err(DRVNAME \ + ": failed to register SPI device\n"); + return ret; + } + found = true; + break; + } else { + ret = platform_device_register(p_device); + if (ret < 0) { + pr_err(DRVNAME \ + ": platform_device_register() returned %d\n", + ret); + return ret; + } + found = true; + break; + } + } + } + + if (!found) { + pr_err(DRVNAME": display not supported: '%s'\n", name); + return -EINVAL; + } + + if (verbose && pdata && pdata->gpios) { + gpio = pdata->gpios; + pr_info(DRVNAME": GPIOS used by '%s':\n", name); + found = false; + while (verbose && gpio->name[0]) { + pr_info(DRVNAME": '%s' = GPIO%d\n", + gpio->name, gpio->gpio); + gpio++; + found = true; + } + if (!found) + pr_info(DRVNAME": (none)\n"); + } + + if (spi_device && (verbose > 1)) + pr_spi_devices(); + if (p_device && (verbose > 1)) + pr_p_devices(); + + return 0; +} + +static void __exit fbtft_device_exit(void) +{ + pr_debug(DRVNAME" - exit\n"); + + if (spi_device) { + device_del(&spi_device->dev); + kfree(spi_device); + } + + if (p_device) + platform_device_unregister(p_device); + +} + +arch_initcall(fbtft_device_init); +module_exit(fbtft_device_exit); + +MODULE_DESCRIPTION("Add a FBTFT device."); +MODULE_AUTHOR("Noralf Tronnes"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From df1fad80dfa0a7644b525c4a0dd8f2be21f57358 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Fri, 9 Jan 2015 11:39:30 +0200 Subject: iio kmx61 / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM After commit b2b49ccbdd54 (PM: Kconfig: Set PM_RUNTIME if PM_SLEEP is selected) PM_RUNTIME is always set if PM is set, so #ifdef blocks depending on CONFIG_PM_RUNTIME may now be changed to depend on CONFIG_PM. Replace CONFIG_PM_RUNTIME with CONFIG_PM everywhere under drivers/iio/imu/kmx61.c Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c index b60b22d..5cc3692 100644 --- a/drivers/iio/imu/kmx61.c +++ b/drivers/iio/imu/kmx61.c @@ -747,7 +747,7 @@ static int kmx61_setup_any_motion_interrupt(struct kmx61_data *data, */ static int kmx61_set_power_state(struct kmx61_data *data, bool on, u8 device) { -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM int ret; if (device & KMX61_ACC) { @@ -1531,7 +1531,7 @@ static int kmx61_resume(struct device *dev) } #endif -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM static int kmx61_runtime_suspend(struct device *dev) { struct kmx61_data *data = i2c_get_clientdata(to_i2c_client(dev)); -- cgit v0.10.2 From e60088575bcbaf8d71a0e9f1d44fbf136f95e2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Tue, 20 Jan 2015 23:40:26 +0100 Subject: staging: fbtft: remove ARCH_BCM2708 optimization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ARCH_BCM2708 is not present in mainline so remove optimization. Signed-off-by: Noralf Trønnes Reported-by: Paul Bolle Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/fbtft-io.c b/drivers/staging/fbtft/fbtft-io.c index dfa2c46..32155a7 100644 --- a/drivers/staging/fbtft/fbtft-io.c +++ b/drivers/staging/fbtft/fbtft-io.c @@ -2,9 +2,6 @@ #include #include #include -#ifdef CONFIG_ARCH_BCM2708 -#include -#endif #include "fbtft.h" int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len) @@ -129,171 +126,6 @@ int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len) } EXPORT_SYMBOL(fbtft_read_spi); - -#ifdef CONFIG_ARCH_BCM2708 - -/* - * Raspberry Pi - * - writing directly to the registers is 40-50% faster than - * optimized use of gpiolib - */ - -#define GPIOSET(no, ishigh) \ -do { \ - if (ishigh) \ - set |= (1 << (no)); \ - else \ - reset |= (1 << (no)); \ -} while (0) - -int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) -{ - unsigned int set = 0; - unsigned int reset = 0; - u8 data; - - fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, - "%s(len=%d): ", __func__, len); - - while (len--) { - data = *(u8 *) buf; - buf++; - - /* Set data */ - GPIOSET(par->gpio.db[0], (data&0x01)); - GPIOSET(par->gpio.db[1], (data&0x02)); - GPIOSET(par->gpio.db[2], (data&0x04)); - GPIOSET(par->gpio.db[3], (data&0x08)); - GPIOSET(par->gpio.db[4], (data&0x10)); - GPIOSET(par->gpio.db[5], (data&0x20)); - GPIOSET(par->gpio.db[6], (data&0x40)); - GPIOSET(par->gpio.db[7], (data&0x80)); - writel(set, __io_address(GPIO_BASE+0x1C)); - writel(reset, __io_address(GPIO_BASE+0x28)); - - /* Pulse /WR low */ - writel((1<gpio.wr), __io_address(GPIO_BASE+0x28)); - writel(0, __io_address(GPIO_BASE+0x28)); /* used as a delay */ - writel((1<gpio.wr), __io_address(GPIO_BASE+0x1C)); - - set = 0; - reset = 0; - } - - return 0; -} -EXPORT_SYMBOL(fbtft_write_gpio8_wr); - -int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) -{ - unsigned int set = 0; - unsigned int reset = 0; - u16 data; - - fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, - "%s(len=%d): ", __func__, len); - - while (len) { - len -= 2; - data = *(u16 *) buf; - buf += 2; - - /* Start writing by pulling down /WR */ - gpio_set_value(par->gpio.wr, 0); - - /* Set data */ - GPIOSET(par->gpio.db[0], (data&0x0001)); - GPIOSET(par->gpio.db[1], (data&0x0002)); - GPIOSET(par->gpio.db[2], (data&0x0004)); - GPIOSET(par->gpio.db[3], (data&0x0008)); - GPIOSET(par->gpio.db[4], (data&0x0010)); - GPIOSET(par->gpio.db[5], (data&0x0020)); - GPIOSET(par->gpio.db[6], (data&0x0040)); - GPIOSET(par->gpio.db[7], (data&0x0080)); - - GPIOSET(par->gpio.db[8], (data&0x0100)); - GPIOSET(par->gpio.db[9], (data&0x0200)); - GPIOSET(par->gpio.db[10], (data&0x0400)); - GPIOSET(par->gpio.db[11], (data&0x0800)); - GPIOSET(par->gpio.db[12], (data&0x1000)); - GPIOSET(par->gpio.db[13], (data&0x2000)); - GPIOSET(par->gpio.db[14], (data&0x4000)); - GPIOSET(par->gpio.db[15], (data&0x8000)); - - writel(set, __io_address(GPIO_BASE+0x1C)); - writel(reset, __io_address(GPIO_BASE+0x28)); - - /* Pullup /WR */ - gpio_set_value(par->gpio.wr, 1); - - set = 0; - reset = 0; - } - - return 0; -} -EXPORT_SYMBOL(fbtft_write_gpio16_wr); - -int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, void *buf, size_t len) -{ - unsigned int set = 0; - unsigned int reset = 0; - u16 data; - - fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, - "%s(len=%d): ", __func__, len); - - while (len) { - len -= 2; - data = *(u16 *) buf; - buf += 2; - - /* Start writing by pulling down /WR */ - gpio_set_value(par->gpio.wr, 0); - - /* Low byte */ - GPIOSET(par->gpio.db[0], (data&0x0001)); - GPIOSET(par->gpio.db[1], (data&0x0002)); - GPIOSET(par->gpio.db[2], (data&0x0004)); - GPIOSET(par->gpio.db[3], (data&0x0008)); - GPIOSET(par->gpio.db[4], (data&0x0010)); - GPIOSET(par->gpio.db[5], (data&0x0020)); - GPIOSET(par->gpio.db[6], (data&0x0040)); - GPIOSET(par->gpio.db[7], (data&0x0080)); - writel(set, __io_address(GPIO_BASE+0x1C)); - writel(reset, __io_address(GPIO_BASE+0x28)); - - /* Pulse 'latch' high */ - gpio_set_value(par->gpio.latch, 1); - gpio_set_value(par->gpio.latch, 0); - - /* High byte */ - GPIOSET(par->gpio.db[0], (data&0x0100)); - GPIOSET(par->gpio.db[1], (data&0x0200)); - GPIOSET(par->gpio.db[2], (data&0x0400)); - GPIOSET(par->gpio.db[3], (data&0x0800)); - GPIOSET(par->gpio.db[4], (data&0x1000)); - GPIOSET(par->gpio.db[5], (data&0x2000)); - GPIOSET(par->gpio.db[6], (data&0x4000)); - GPIOSET(par->gpio.db[7], (data&0x8000)); - writel(set, __io_address(GPIO_BASE+0x1C)); - writel(reset, __io_address(GPIO_BASE+0x28)); - - /* Pullup /WR */ - gpio_set_value(par->gpio.wr, 1); - - set = 0; - reset = 0; - } - - return 0; -} -EXPORT_SYMBOL(fbtft_write_gpio16_wr_latched); - -#undef GPIOSET - -#else - /* * Optimized use of gpiolib is twice as fast as no optimization * only one driver can use the optimized version at a time @@ -405,5 +237,3 @@ int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, void *buf, size_t len) return -1; } EXPORT_SYMBOL(fbtft_write_gpio16_wr_latched); - -#endif /* CONFIG_ARCH_BCM2708 */ -- cgit v0.10.2 From 3ec698816ab3a7aca39dd3389115840a48d5266d Mon Sep 17 00:00:00 2001 From: Marc Dietrich Date: Tue, 20 Jan 2015 23:01:28 +0100 Subject: staging: nvec: specify a platform-device base id commit 6e3f62f079 (mfd: core: Fix platform-device id generation) modified the computation of the mfd cell id. Negative numbers forbit the specification of cell ids as we do. Fix this for now by specifying a base of 0 instead. In the long run, this may be changed to automatic cell ids (base -2). Reported-by: Misha Komarovskiy Signed-off-by: Marc Dietrich Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 2637059..5868ebb 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -85,23 +85,20 @@ static struct nvec_chip *nvec_power_handle; static const struct mfd_cell nvec_devices[] = { { .name = "nvec-kbd", - .id = 1, }, { .name = "nvec-mouse", - .id = 1, }, { .name = "nvec-power", - .id = 1, + .id = 0, }, { .name = "nvec-power", - .id = 2, + .id = 1, }, { .name = "nvec-paz00", - .id = 1, }, }; @@ -891,7 +888,7 @@ static int tegra_nvec_probe(struct platform_device *pdev) nvec_msg_free(nvec, msg); } - ret = mfd_add_devices(nvec->dev, -1, nvec_devices, + ret = mfd_add_devices(nvec->dev, 0, nvec_devices, ARRAY_SIZE(nvec_devices), NULL, 0, NULL); if (ret) dev_err(nvec->dev, "error adding subdevices\n"); -- cgit v0.10.2 From 053e514f9172c10b55b1ef0706da57cecb6c85e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 23 Jan 2015 19:29:07 +0100 Subject: MAINTAINERS: add entry for staging/fbtft/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add MAINTAINERS entry for staging/fbtft/ FBTFT is a framework for writing framebuffer drivers for displays with LCD controllers having onchip RAM. Signed-off-by: Noralf Trønnes Signed-off-by: Greg Kroah-Hartman diff --git a/MAINTAINERS b/MAINTAINERS index 2fa3853..0dbe230 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3872,6 +3872,12 @@ S: Supported F: Documentation/fault-injection/ F: lib/fault-inject.c +FBTFT Framebuffer drivers +M: Thomas Petazzoni +M: Noralf Trønnes +S: Maintained +F: drivers/staging/fbtft/ + FCOE SUBSYSTEM (libfc, libfcoe, fcoe) M: Robert Love L: fcoe-devel@open-fcoe.org -- cgit v0.10.2 From b15f0277d75530d0c2e77c9dc7bc22dca137cf18 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sun, 18 Jan 2015 12:53:24 +0100 Subject: comedi: rtd520: if condition with no effect - if identical to else The if and the else branch code are identical - so the condition has no effect on the effective code - this patch removes the condition and the duplicated code. Signed-off-by: Nicholas Mc Guire Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 06ae436..3ccdade 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1012,10 +1012,8 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) readw(dev->mmio + LAS0_CLEAR); /* TODO: allow multiple interrupt sources */ - if (devpriv->xfer_count > 0) /* transfer every N samples */ - writew(IRQM_ADC_ABOUT_CNT, dev->mmio + LAS0_IT); - else /* 1/2 FIFO transfers */ - writew(IRQM_ADC_ABOUT_CNT, dev->mmio + LAS0_IT); + /* transfer every N samples */ + writew(IRQM_ADC_ABOUT_CNT, dev->mmio + LAS0_IT); /* BUG: start_src is ASSUMED to be TRIG_NOW */ /* BUG? it seems like things are running before the "start" */ -- cgit v0.10.2 From bff776931e6589192f07f22e1ec17b8eb878bd1a Mon Sep 17 00:00:00 2001 From: Chase Southwood Date: Mon, 19 Jan 2015 20:42:49 -0600 Subject: staging: comedi: das1800: prefer kmalloc_array over kmalloc with multiply Checkpatch doesn't like kmalloc with multiply very much: drivers/staging/comedi/drivers/das1800.c:1377: WARNING: Prefer kmalloc_array over kmalloc with multiply So this patch swaps that use out for kmalloc_array instead. Signed-off-by: Chase Southwood Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 381ae94..13ed31c 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1374,7 +1374,7 @@ static int das1800_attach(struct comedi_device *dev, if (dev->irq & it->options[2]) das1800_init_dma(dev, it); - devpriv->fifo_buf = kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL); + devpriv->fifo_buf = kmalloc_array(FIFO_SIZE, sizeof(uint16_t), GFP_KERNEL); if (!devpriv->fifo_buf) return -ENOMEM; -- cgit v0.10.2 From be8e89087ec2d2c8a1ad1e3db64bf4efdfc3c298 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 19 Jan 2015 14:47:27 +0000 Subject: staging: comedi: cb_pcidas64: fix incorrect AI range code handling The hardware range code values and list of valid ranges for the AI subdevice is incorrect for several supported boards. The hardware range code values for all boards except PCI-DAS4020/12 is determined by calling `ai_range_bits_6xxx()` based on the maximum voltage of the range and whether it is bipolar or unipolar, however it only returns the correct hardware range code for the PCI-DAS60xx boards. For PCI-DAS6402/16 (and /12) it returns the wrong code for the unipolar ranges. For PCI-DAS64/Mx/16 it returns the wrong code for all the ranges and the comedi range table is incorrect. Change `ai_range_bits_6xxx()` to use a look-up table pointed to by new member `ai_range_codes` of `struct pcidas64_board` to map the comedi range table indices to the hardware range codes. Use a new comedi range table for the PCI-DAS64/Mx/16 boards (and the commented out variants). Signed-off-by: Ian Abbott Cc: # 3.18.x Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index eddb7ac..569310a 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -439,6 +439,29 @@ static const struct comedi_lrange ai_ranges_64xx = { } }; +static const uint8_t ai_range_code_64xx[8] = { + 0x0, 0x1, 0x2, 0x3, /* bipolar 10, 5, 2,5, 1.25 */ + 0x8, 0x9, 0xa, 0xb /* unipolar 10, 5, 2.5, 1.25 */ +}; + +/* analog input ranges for 64-Mx boards */ +static const struct comedi_lrange ai_ranges_64_mx = { + 7, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } +}; + +static const uint8_t ai_range_code_64_mx[7] = { + 0x0, 0x1, 0x2, 0x3, /* bipolar 5, 2.5, 1.25, 0.625 */ + 0x9, 0xa, 0xb /* unipolar 5, 2.5, 1.25 */ +}; + /* analog input ranges for 60xx boards */ static const struct comedi_lrange ai_ranges_60xx = { 4, { @@ -449,6 +472,10 @@ static const struct comedi_lrange ai_ranges_60xx = { } }; +static const uint8_t ai_range_code_60xx[4] = { + 0x0, 0x1, 0x4, 0x7 /* bipolar 10, 5, 0.5, 0.05 */ +}; + /* analog input ranges for 6030, etc boards */ static const struct comedi_lrange ai_ranges_6030 = { 14, { @@ -469,6 +496,11 @@ static const struct comedi_lrange ai_ranges_6030 = { } }; +static const uint8_t ai_range_code_6030[14] = { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, /* bip 10, 5, 2, 1, 0.5, 0.2, 0.1 */ + 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* uni 10, 5, 2, 1, 0.5, 0.2, 0.1 */ +}; + /* analog input ranges for 6052, etc boards */ static const struct comedi_lrange ai_ranges_6052 = { 15, { @@ -490,6 +522,11 @@ static const struct comedi_lrange ai_ranges_6052 = { } }; +static const uint8_t ai_range_code_6052[15] = { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, /* bipolar 10 ... 0.05 */ + 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* unipolar 10 ... 0.1 */ +}; + /* analog input ranges for 4020 board */ static const struct comedi_lrange ai_ranges_4020 = { 2, { @@ -593,6 +630,7 @@ struct pcidas64_board { int ai_bits; /* analog input resolution */ int ai_speed; /* fastest conversion period in ns */ const struct comedi_lrange *ai_range_table; + const uint8_t *ai_range_code; int ao_nchan; /* number of analog out channels */ int ao_bits; /* analog output resolution */ int ao_scan_speed; /* analog output scan speed */ @@ -651,6 +689,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_64XX, .ai_range_table = &ai_ranges_64xx, + .ai_range_code = ai_range_code_64xx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -666,6 +705,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_64XX, .ai_range_table = &ai_ranges_64xx, + .ai_range_code = ai_range_code_64xx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -680,7 +720,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -695,7 +736,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -710,7 +752,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -725,6 +768,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -740,6 +784,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -754,6 +799,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -769,6 +815,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -784,6 +831,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -799,6 +847,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -812,6 +861,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ai_fifo = &ai_fifo_60xx, .has_8255 = 0, }, @@ -823,6 +873,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ai_fifo = &ai_fifo_60xx, .has_8255 = 0, }, @@ -835,6 +886,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 0, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ai_fifo = &ai_fifo_60xx, .has_8255 = 0, }, @@ -848,6 +900,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -863,6 +916,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -878,6 +932,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 1000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -893,6 +948,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 3333, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -908,6 +964,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 1000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -923,6 +980,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 1000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -957,6 +1015,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_64XX, .ai_range_table = &ai_ranges_64xx, + .ai_range_code = ai_range_code_64xx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -968,7 +1027,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -980,7 +1040,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -992,7 +1053,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1004,7 +1066,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 2, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1016,7 +1079,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 2, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1028,7 +1092,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 2, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1115,45 +1180,8 @@ static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, unsigned int range_index) { const struct pcidas64_board *thisboard = dev->board_ptr; - const struct comedi_krange *range = - &thisboard->ai_range_table->range[range_index]; - unsigned int bits = 0; - switch (range->max) { - case 10000000: - bits = 0x000; - break; - case 5000000: - bits = 0x100; - break; - case 2000000: - case 2500000: - bits = 0x200; - break; - case 1000000: - case 1250000: - bits = 0x300; - break; - case 500000: - bits = 0x400; - break; - case 200000: - case 250000: - bits = 0x500; - break; - case 100000: - bits = 0x600; - break; - case 50000: - bits = 0x700; - break; - default: - dev_err(dev->class_dev, "bug! in %s\n", __func__); - break; - } - if (range->min == 0) - bits += 0x900; - return bits; + return thisboard->ai_range_code[range_index] << 8; } static unsigned int hw_revision(const struct comedi_device *dev, -- cgit v0.10.2 From 53c0bee80f975cb095796e3676fd6a98e32f1beb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 12:00:22 -0700 Subject: staging: comedi: aio_iiro_16: return input state in async command sample Modify the sample data returned by the async command to include the current state of the digital inputs. Otherwise the command needs to be canceled in order for the user to do an (*insn_bits) operation to check the digital inputs. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index d8884a3..1c7b325 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -27,11 +27,14 @@ * * The board supports interrupts on change of state of the digital inputs. * The sample data returned by the async command indicates which inputs - * changed state: + * changed state and the current state of the inputs: * - * Bit 7 - IRQ Enable (1) / Disable (0) - * Bit 1 - Input 8-15 Changed State (1 = Changed, 0 = No Change) - * Bit 0 - Input 0-7 Changed State (1 = Changed, 0 = No Change) + * Bit 23 - IRQ Enable (1) / Disable (0) + * Bit 17 - Input 8-15 Changed State (1 = Changed, 0 = No Change) + * Bit 16 - Input 0-7 Changed State (1 = Changed, 0 = No Change) + * Bit 15 - Digital input 15 + * ... + * Bit 0 - Digital input 0 */ #include @@ -51,17 +54,31 @@ #define AIO_IIRO_16_STATUS_INPUT_8_15 BIT(1) #define AIO_IIRO_16_STATUS_INPUT_0_7 BIT(0) +static unsigned int aio_iiro_16_read_inputs(struct comedi_device *dev) +{ + unsigned int val; + + val = inb(dev->iobase + AIO_IIRO_16_INPUT_0_7); + val |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8; + + return val; +} + static irqreturn_t aio_iiro_16_cos(int irq, void *d) { struct comedi_device *dev = d; struct comedi_subdevice *s = dev->read_subdev; unsigned int status; + unsigned int val; status = inb(dev->iobase + AIO_IIRO_16_STATUS); if (!(status & AIO_IIRO_16_STATUS_IRQE)) return IRQ_NONE; - comedi_buf_write_samples(s, &status, 1); + val = aio_iiro_16_read_inputs(dev); + val |= (status << 16); + + comedi_buf_write_samples(s, &val, 1); comedi_handle_events(dev, s); return IRQ_HANDLED; @@ -150,9 +167,7 @@ static int aio_iiro_16_di_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - data[1] = 0; - data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_0_7); - data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8; + data[1] = aio_iiro_16_read_inputs(dev); return insn->n; } @@ -207,7 +222,7 @@ static int aio_iiro_16_attach(struct comedi_device *dev, s->insn_bits = aio_iiro_16_di_insn_bits; if (dev->irq) { dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; + s->subdev_flags |= SDF_CMD_READ | SDF_LSAMPL; s->len_chanlist = 1; s->do_cmdtest = aio_iiro_16_cos_cmdtest; s->do_cmd = aio_iiro_16_cos_cmd; -- cgit v0.10.2 From a8c66b684efaf628752262ed2c48cb096f1cf26d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 12:01:54 -0700 Subject: staging: comedi: addi_apci_1500: rewrite the subdevice support functions This driver is a mess. It violates the comedi API so much that I doubt anything actually works. Drop the addi-data/hwdrv_apci1500.c file and rewrite the subdevice support functions. This board has 16 digital inputs (subdevice 0) and 16 digital outputs (subdevice 1). It also has three 16-bit timer/counters provided by a Z8536 CIO chip (subdevice 2). The Z8536 chip is also used to support pattern match interrupt detection of the first 14 digital input channels. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c deleted file mode 100644 index 5bf943d..0000000 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c +++ /dev/null @@ -1,1620 +0,0 @@ -/* - * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - * - * ADDI-DATA GmbH - * Dieselstrasse 3 - * D-77833 Ottersweier - * Tel: +19(0)7223/9493-0 - * Fax: +49(0)7223/9493-92 - * http://www.addi-data.com - * info@addi-data.com - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - */ - -/* DIGITAL INPUT-OUTPUT DEFINE */ - -#define APCI1500_AND 2 -#define APCI1500_OR 4 -#define APCI1500_OR_PRIORITY 6 -#define COUNTER1 0 -#define COUNTER2 1 -#define COUNTER3 2 -#define APCI1500_COUNTER 0x20 -#define APCI1500_TIMER 0 -#define APCI1500_WATCHDOG 0 -#define APCI1500_SINGLE 0 -#define APCI1500_CONTINUOUS 0x80 -#define APCI1500_DISABLE 0 -#define APCI1500_ENABLE 1 -#define APCI1500_SOFTWARE_TRIGGER 0x4 -#define APCI1500_HARDWARE_TRIGGER 0x10 -#define APCI1500_SOFTWARE_GATE 0 -#define APCI1500_HARDWARE_GATE 0x8 -#define START 0 -#define STOP 1 -#define TRIGGER 2 - -/* - * Z8536 CIO Internal Address - */ -enum { - APCI1500_RW_MASTER_INTERRUPT_CONTROL, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL, - APCI1500_RW_PORT_A_INTERRUPT_CONTROL, - APCI1500_RW_PORT_B_INTERRUPT_CONTROL, - APCI1500_RW_TIMER_COUNTER_INTERRUPT_VECTOR, - APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY, - APCI1500_RW_PORT_C_DATA_DIRECTION, - APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL, - - APCI1500_RW_PORT_A_COMMAND_AND_STATUS, - APCI1500_RW_PORT_B_COMMAND_AND_STATUS, - APCI1500_RW_CPT_TMR1_CMD_STATUS, - APCI1500_RW_CPT_TMR2_CMD_STATUS, - APCI1500_RW_CPT_TMR3_CMD_STATUS, - APCI1500_RW_PORT_A_DATA, - APCI1500_RW_PORT_B_DATA, - APCI1500_RW_PORT_C_DATA, - - APCI1500_R_CPT_TMR1_VALUE_HIGH, - APCI1500_R_CPT_TMR1_VALUE_LOW, - APCI1500_R_CPT_TMR2_VALUE_HIGH, - APCI1500_R_CPT_TMR2_VALUE_LOW, - APCI1500_R_CPT_TMR3_VALUE_HIGH, - APCI1500_R_CPT_TMR3_VALUE_LOW, - APCI1500_RW_CPT_TMR1_TIME_CST_HIGH, - APCI1500_RW_CPT_TMR1_TIME_CST_LOW, - APCI1500_RW_CPT_TMR2_TIME_CST_HIGH, - APCI1500_RW_CPT_TMR2_TIME_CST_LOW, - APCI1500_RW_CPT_TMR3_TIME_CST_HIGH, - APCI1500_RW_CPT_TMR3_TIME_CST_LOW, - APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION, - APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION, - APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION, - APCI1500_R_CURRENT_VECTOR, - - APCI1500_RW_PORT_A_SPECIFICATION, - APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION, - APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY, - APCI1500_RW_PORT_A_DATA_DIRECTION, - APCI1500_RW_PORT_A_SPECIAL_IO_CONTROL, - APCI1500_RW_PORT_A_PATTERN_POLARITY, - APCI1500_RW_PORT_A_PATTERN_TRANSITION, - APCI1500_RW_PORT_A_PATTERN_MASK, - - APCI1500_RW_PORT_B_SPECIFICATION, - APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION, - APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY, - APCI1500_RW_PORT_B_DATA_DIRECTION, - APCI1500_RW_PORT_B_SPECIAL_IO_CONTROL, - APCI1500_RW_PORT_B_PATTERN_POLARITY, - APCI1500_RW_PORT_B_PATTERN_TRANSITION, - APCI1500_RW_PORT_B_PATTERN_MASK -}; - -static int i_TimerCounter1Init; -static int i_TimerCounter2Init; -static int i_WatchdogCounter3Init; -static int i_Event1Status, i_Event2Status; -static int i_TimerCounterWatchdogInterrupt; -static int i_Logic, i_CounterLogic; -static int i_InterruptMask; -static int i_InputChannel; -static int i_TimerCounter1Enabled, i_TimerCounter2Enabled, - i_WatchdogCounter3Enabled; - -static unsigned int z8536_read(struct comedi_device *dev, unsigned int reg) -{ - unsigned long flags; - unsigned int val; - - spin_lock_irqsave(&dev->spinlock, flags); - outb(reg, dev->iobase + APCI1500_Z8536_CTRL_REG); - val = inb(dev->iobase + APCI1500_Z8536_CTRL_REG); - spin_unlock_irqrestore(&dev->spinlock, flags); - - return val; -} - -static void z8536_write(struct comedi_device *dev, - unsigned int val, unsigned int reg) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->spinlock, flags); - outb(reg, dev->iobase + APCI1500_Z8536_CTRL_REG); - outb(val, dev->iobase + APCI1500_Z8536_CTRL_REG); - spin_unlock_irqrestore(&dev->spinlock, flags); -} - -static void z8536_reset(struct comedi_device *dev) -{ - unsigned long flags; - - /* - * Even if the state of the Z8536 is not known, the following - * sequence will reset it and put it in State 0. - */ - spin_lock_irqsave(&dev->spinlock, flags); - inb(dev->iobase + APCI1500_Z8536_CTRL_REG); - outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); - inb(dev->iobase + APCI1500_Z8536_CTRL_REG); - outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); - outb(1, dev->iobase + APCI1500_Z8536_CTRL_REG); - outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); - spin_unlock_irqrestore(&dev->spinlock, flags); - - z8536_write(dev, 0xf4, APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - z8536_write(dev, 0x10, APCI1500_RW_PORT_A_SPECIFICATION); - /* High level of port A means 1 */ - z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_PCITCH_POLARITY); - /* All bits used as inputs */ - z8536_write(dev, 0xff, APCI1500_RW_PORT_A_DATA_DIRECTION); - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - /* Deactivates the interrupt management of port A */ - z8536_write(dev, 0xe0, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - /* Deletes the register */ - z8536_write(dev, 0x00, APCI1500_RW_PORT_A_HANDSHAKE_SPECIFICATION); - - z8536_write(dev, 0x10, APCI1500_RW_PORT_B_SPECIFICATION); - /* A high level of port B means 1 */ - z8536_write(dev, 0x7f, APCI1500_RW_PORT_B_DATA_PCITCH_POLARITY); - /* All bits used as inputs */ - z8536_write(dev, 0xff, APCI1500_RW_PORT_B_DATA_DIRECTION); - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - /* Deactivates the interrupt management of port B */ - z8536_write(dev, 0xe0, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - /* Deletes the register */ - z8536_write(dev, 0x00, APCI1500_RW_PORT_B_HANDSHAKE_SPECIFICATION); - - /* High level of port C means 1 */ - z8536_write(dev, 0x09, APCI1500_RW_PORT_C_DATA_PCITCH_POLARITY); - /* All bits used as inputs except channel 1 */ - z8536_write(dev, 0x0e, APCI1500_RW_PORT_C_DATA_DIRECTION); - /* Deletes it */ - z8536_write(dev, 0x00, APCI1500_RW_PORT_C_SPECIAL_IO_CONTROL); - - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR1_CMD_STATUS); - /* Deactivates the interrupt management of timer 1 */ - z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR1_CMD_STATUS); - - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR2_CMD_STATUS); - /* Deactivates Timer 2 interrupt management */ - z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR2_CMD_STATUS); - - /* Deletes IP and IUS */ - z8536_write(dev, 0x20, APCI1500_RW_CPT_TMR3_CMD_STATUS); - /* Deactivates interrupt management of timer 3 */ - z8536_write(dev, 0xe0, APCI1500_RW_CPT_TMR3_CMD_STATUS); - - /* Deletes all interrupts */ - z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); -} - -/* - * An event can be generated for each port. The first event is related to the - * first 8 channels (port 1) and the second to the following 6 channels (port 2) - * An interrupt is generated when one or both events have occurred. - * - * data[0] Number of the input port on which the event will take place (1 or 2) - * data[1] The event logic for port 1 has three possibilities: - * APCI1500_AND This logic links the inputs with an AND logic. - * APCI1500_OR This logic links the inputs with a OR logic. - * APCI1500_OR_PRIORITY This logic links the inputs with a priority OR - * logic. Input 1 has the highest priority level - * and input 8 the smallest. - * For the second port the user has 1 possibility: - * APCI1500_OR This logic links the inputs with a polarity OR logic - * data[2] These 8-character word for port1 and 6-character word for port 2 - * give the mask of the event. Each place gives the state of the input - * channels and can have one of these six characters - * 0 This input must be on 0 - * 1 This input must be on 1 - * 2 This input reacts to a falling edge - * 3 This input reacts to a rising edge - * 4 This input reacts to both edges - * 5 This input is not used for event - */ -static int apci1500_di_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0; - int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0; - int i_PatternTransitionCount = 0, i_RegValue; - int i; - - /* Disables the main interrupt on the board */ - z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); - - if (data[0] == 1) { - i_MaxChannel = 8; - } else { - if (data[0] == 2) { - i_MaxChannel = 6; - } else { - dev_warn(dev->class_dev, - "The specified port event does not exist\n"); - return -EINVAL; - } - } - switch (data[1]) { - case 0: - data[1] = APCI1500_AND; - break; - case 1: - data[1] = APCI1500_OR; - break; - case 2: - data[1] = APCI1500_OR_PRIORITY; - break; - default: - dev_warn(dev->class_dev, - "The specified interrupt logic does not exist\n"); - return -EINVAL; - } - - i_Logic = data[1]; - for (i_Count = i_MaxChannel, i = 0; i_Count > 0; i_Count--, i++) { - i_EventMask = data[2 + i]; - switch (i_EventMask) { - case 0: - i_PatternMask = - i_PatternMask | (1 << (i_MaxChannel - i_Count)); - break; - case 1: - i_PatternMask = - i_PatternMask | (1 << (i_MaxChannel - i_Count)); - i_PatternPolarity = - i_PatternPolarity | (1 << (i_MaxChannel - - i_Count)); - break; - case 2: - i_PatternMask = - i_PatternMask | (1 << (i_MaxChannel - i_Count)); - i_PatternTransition = - i_PatternTransition | (1 << (i_MaxChannel - - i_Count)); - break; - case 3: - i_PatternMask = - i_PatternMask | (1 << (i_MaxChannel - i_Count)); - i_PatternPolarity = - i_PatternPolarity | (1 << (i_MaxChannel - - i_Count)); - i_PatternTransition = - i_PatternTransition | (1 << (i_MaxChannel - - i_Count)); - break; - case 4: - i_PatternTransition = - i_PatternTransition | (1 << (i_MaxChannel - - i_Count)); - break; - case 5: - break; - default: - dev_warn(dev->class_dev, - "The option indicated in the event mask does not exist\n"); - return -EINVAL; - } - } - - if (data[0] == 1) { - /* Test the interrupt logic */ - - if (data[1] == APCI1500_AND || - data[1] == APCI1500_OR || - data[1] == APCI1500_OR_PRIORITY) { - /* Tests if a transition was declared */ - /* for a OR PRIORITY logic */ - - if (data[1] == APCI1500_OR_PRIORITY - && i_PatternTransition != 0) { - dev_warn(dev->class_dev, - "Transition error on an OR PRIORITY logic\n"); - return -EINVAL; - } - - /* Tests if more than one transition */ - /* was declared for an AND logic */ - - if (data[1] == APCI1500_AND) { - for (i_Count = 0; i_Count < 8; i_Count++) { - i_PatternTransitionCount = - i_PatternTransitionCount + - ((i_PatternTransition >> - i_Count) & 0x1); - - } - - if (i_PatternTransitionCount > 1) { - dev_warn(dev->class_dev, - "Transition error on an AND logic\n"); - return -EINVAL; - } - } - - /* Disable Port A */ - z8536_write(dev, 0xf0, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - z8536_write(dev, i_PatternPolarity, - APCI1500_RW_PORT_A_PATTERN_POLARITY); - z8536_write(dev, i_PatternMask, - APCI1500_RW_PORT_A_PATTERN_MASK); - z8536_write(dev, i_PatternTransition, - APCI1500_RW_PORT_A_PATTERN_TRANSITION); - - /* Port A new mode */ - i_RegValue = z8536_read(dev, - APCI1500_RW_PORT_A_SPECIFICATION); - i_RegValue = (i_RegValue & 0xF9) | data[1] | 0x9; - z8536_write(dev, i_RegValue, - APCI1500_RW_PORT_A_SPECIFICATION); - - i_Event1Status = 1; - - /* Enable Port A */ - z8536_write(dev, 0xf4, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - } else { - dev_warn(dev->class_dev, - "The choice for interrupt logic does not exist\n"); - return -EINVAL; - } - } - - /* Test if event setting for port 2 */ - - if (data[0] == 2) { - /* Test the event logic */ - - if (data[1] == APCI1500_OR) { - /* Disable Port B */ - z8536_write(dev, 0x74, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - i_RegValue = z8536_read(dev, - APCI1500_RW_PORT_B_SPECIFICATION); - i_RegValue = i_RegValue & 0xF9; - z8536_write(dev, i_RegValue, - APCI1500_RW_PORT_B_SPECIFICATION); - - /* Selects error channels 1 and 2 */ - i_PatternMask = (i_PatternMask | 0xC0); - i_PatternPolarity = (i_PatternPolarity | 0xC0); - i_PatternTransition = (i_PatternTransition | 0xC0); - - z8536_write(dev, i_PatternPolarity, - APCI1500_RW_PORT_B_PATTERN_POLARITY); - z8536_write(dev, i_PatternTransition, - APCI1500_RW_PORT_B_PATTERN_TRANSITION); - z8536_write(dev, i_PatternMask, - APCI1500_RW_PORT_B_PATTERN_MASK); - - i_RegValue = z8536_read(dev, - APCI1500_RW_PORT_B_SPECIFICATION); - i_RegValue = (i_RegValue & 0xF9) | 4; - z8536_write(dev, i_RegValue, - APCI1500_RW_PORT_B_SPECIFICATION); - - i_Event2Status = 1; - - /* Enable Port B */ - z8536_write(dev, 0xf4, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - } else { - dev_warn(dev->class_dev, - "The choice for interrupt logic does not exist\n"); - return -EINVAL; - } - } - - return insn->n; -} - -/* - * Allows or disallows a port event - * - * data[0] 0 = Start input event, 1 = Stop input event - * data[1] Number of port (1 or 2) - */ -static int apci1500_di_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - int i_Event1InterruptStatus = 0, i_Event2InterruptStatus = - 0, i_RegValue; - - switch (data[0]) { - case START: - /* Tests the port number */ - - if (data[1] == 1 || data[1] == 2) { - /* Test if port 1 selected */ - - if (data[1] == 1) { - /* Test if event initialised */ - if (i_Event1Status == 1) { - /* Disable Port A */ - z8536_write(dev, 0xf0, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - /* Allows the pattern interrupt */ - z8536_write(dev, 0xc0, - APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - /* Enable Port A */ - z8536_write(dev, 0xf4, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - i_Event1InterruptStatus = 1; - - i_RegValue = z8536_read(dev, - APCI1500_RW_PORT_A_SPECIFICATION); - - /* Authorizes the main interrupt on the board */ - z8536_write(dev, 0xd0, - APCI1500_RW_MASTER_INTERRUPT_CONTROL); - } else { - dev_warn(dev->class_dev, - "Event 1 not initialised\n"); - return -EINVAL; - } - } - if (data[1] == 2) { - - if (i_Event2Status == 1) { - /* Disable Port B */ - z8536_write(dev, 0x74, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - /* Allows the pattern interrupt */ - z8536_write(dev, 0xc0, - APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - /* Enable Port B */ - z8536_write(dev, 0xf4, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - /* Authorizes the main interrupt on the board */ - z8536_write(dev, 0xd0, - APCI1500_RW_MASTER_INTERRUPT_CONTROL); - - i_Event2InterruptStatus = 1; - } else { - dev_warn(dev->class_dev, - "Event 2 not initialised\n"); - return -EINVAL; - } - } - } else { - dev_warn(dev->class_dev, - "The port parameter is in error\n"); - return -EINVAL; - } - - break; - - case STOP: - /* Tests the port number */ - - if (data[1] == 1 || data[1] == 2) { - /* Test if port 1 selected */ - - if (data[1] == 1) { - /* Test if event initialised */ - if (i_Event1Status == 1) { - /* Disable Port A */ - z8536_write(dev, 0xf0, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - /* Inhibits the pattern interrupt */ - z8536_write(dev, 0xe0, - APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - /* Enable Port A */ - z8536_write(dev, 0xf4, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - i_Event1InterruptStatus = 0; - } else { - dev_warn(dev->class_dev, - "Event 1 not initialised\n"); - return -EINVAL; - } - } - if (data[1] == 2) { - /* Test if event initialised */ - if (i_Event2Status == 1) { - /* Disable Port B */ - z8536_write(dev, 0x74, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - /* Inhibits the pattern interrupt */ - z8536_write(dev, 0xe0, - APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - /* Enable Port B */ - z8536_write(dev, 0xf4, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - i_Event2InterruptStatus = 0; - } else { - - dev_warn(dev->class_dev, - "Event 2 not initialised\n"); - return -EINVAL; - } - } - - } else { - dev_warn(dev->class_dev, - "The port parameter is in error\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "The option of START/STOP logic does not exist\n"); - return -EINVAL; - } - - return insn->n; -} - -/* - * Return the status of the digital input - */ -static int apci1500_di_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - /* Software reset */ - z8536_reset(dev); - - return insn->n; -} - -static int apci1500_di_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - - data[1] = inw(devpriv->addon + APCI1500_DI_REG); - - return insn->n; -} - -/* - * Configures the digital output memory and the digital output error interrupt - * - * data[1] 1 = Enable the voltage error interrupt - * 2 = Disable the voltage error interrupt - */ -static int apci1500_do_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - - devpriv->b_OutputMemoryStatus = data[0]; - return insn->n; -} - -/* - * Writes port value to the selected port - */ -static int apci1500_do_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - static unsigned int ui_Temp; - unsigned int ui_Temp1; - unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec); /* get the channel */ - - if (!devpriv->b_OutputMemoryStatus) - ui_Temp = 0; - - if (data[3] == 0) { - if (data[1] == 0) { - data[0] = (data[0] << ui_NoOfChannel) | ui_Temp; - outw(data[0], devpriv->addon + APCI1500_DO_REG); - } else { - if (data[1] == 1) { - switch (ui_NoOfChannel) { - - case 2: - data[0] = - (data[0] << (2 * - data[2])) | ui_Temp; - break; - - case 4: - data[0] = - (data[0] << (4 * - data[2])) | ui_Temp; - break; - - case 8: - data[0] = - (data[0] << (8 * - data[2])) | ui_Temp; - break; - - case 15: - data[0] = data[0] | ui_Temp; - break; - - default: - dev_err(dev->class_dev, - "chan spec wrong\n"); - return -EINVAL; /* "sorry channel spec wrong " */ - - } - - outw(data[0], devpriv->addon + APCI1500_DO_REG); - } else { - dev_warn(dev->class_dev, - "Specified channel not supported\n"); - return -EINVAL; - } - } - } else { - if (data[3] == 1) { - if (data[1] == 0) { - data[0] = ~data[0] & 0x1; - ui_Temp1 = 1; - ui_Temp1 = ui_Temp1 << ui_NoOfChannel; - ui_Temp = ui_Temp | ui_Temp1; - data[0] = - (data[0] << ui_NoOfChannel) ^ - 0xffffffff; - data[0] = data[0] & ui_Temp; - outw(data[0], devpriv->addon + APCI1500_DO_REG); - } else { - if (data[1] == 1) { - switch (ui_NoOfChannel) { - - case 2: - data[0] = ~data[0] & 0x3; - ui_Temp1 = 3; - ui_Temp1 = - ui_Temp1 << 2 * data[2]; - ui_Temp = ui_Temp | ui_Temp1; - data[0] = - ((data[0] << (2 * - data - [2])) ^ - 0xffffffff) & ui_Temp; - break; - - case 4: - data[0] = ~data[0] & 0xf; - ui_Temp1 = 15; - ui_Temp1 = - ui_Temp1 << 4 * data[2]; - ui_Temp = ui_Temp | ui_Temp1; - data[0] = - ((data[0] << (4 * - data - [2])) ^ - 0xffffffff) & ui_Temp; - break; - - case 8: - data[0] = ~data[0] & 0xff; - ui_Temp1 = 255; - ui_Temp1 = - ui_Temp1 << 8 * data[2]; - ui_Temp = ui_Temp | ui_Temp1; - data[0] = - ((data[0] << (8 * - data - [2])) ^ - 0xffffffff) & ui_Temp; - break; - - case 15: - break; - - default: - dev_err(dev->class_dev, - "chan spec wrong\n"); - return -EINVAL; /* "sorry channel spec wrong " */ - - } - - outw(data[0], - devpriv->addon + APCI1500_DO_REG); - } else { - dev_warn(dev->class_dev, - "Specified channel not supported\n"); - return -EINVAL; - } - } - } else { - dev_warn(dev->class_dev, - "Specified functionality does not exist\n"); - return -EINVAL; - } - } - ui_Temp = data[0]; - return insn->n; -} - -/* - * Configures The Watchdog - * - * data[0] 0 = APCI1500_115_KHZ, 1 = APCI1500_3_6_KHZ, 2 = APCI1500_1_8_KHZ - * data[1] 0 = Counter1/Timer1, 1 = Counter2/Timer2, 2 = Counter3/Watchdog - * data[2] 0 = Counter, 1 = Timer/Watchdog - * data[3] This parameter has two meanings. If the counter/timer is used as - * a counter the limit value of the counter is given. If the counter/timer - * is used as a timer, the divider factor for the output is given. - * data[4] 0 = APCI1500_CONTINUOUS, 1 = APCI1500_SINGLE - * data[5] 0 = Software Trigger, 1 = Hardware Trigger - * data[6] 0 = Software gate, 1 = Hardware gate - * data[7] 0 = Interrupt Disable, 1 = Interrupt Enable - */ -static int apci1500_timer_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - int i_TimerCounterMode, i_MasterConfiguration; - - devpriv->tsk_Current = current; - - /* Selection of the input clock */ - if (data[0] == 0 || data[0] == 1 || data[0] == 2) { - outw(data[0], devpriv->addon + APCI1500_CLK_SEL_REG); - } else { - if (data[0] != 3) { - dev_warn(dev->class_dev, - "The option for input clock selection does not exist\n"); - return -EINVAL; - } - } - /* Select the counter/timer */ - switch (data[1]) { - case COUNTER1: - /* selecting counter or timer */ - switch (data[2]) { - case 0: - data[2] = APCI1500_COUNTER; - break; - case 1: - data[2] = APCI1500_TIMER; - break; - default: - dev_warn(dev->class_dev, - "This choice is not a timer nor a counter\n"); - return -EINVAL; - } - - /* Selecting single or continuous mode */ - switch (data[4]) { - case 0: - data[4] = APCI1500_CONTINUOUS; - break; - case 1: - data[4] = APCI1500_SINGLE; - break; - default: - dev_warn(dev->class_dev, - "This option for single/continuous mode does not exist\n"); - return -EINVAL; - } - - i_TimerCounterMode = data[2] | data[4] | 7; - /* Test the reload value */ - - if ((data[3] >= 0) && (data[3] <= 65535)) { - if (data[7] == APCI1500_ENABLE || - data[7] == APCI1500_DISABLE) { - /* Writes the new mode */ - z8536_write(dev, i_TimerCounterMode, - APCI1500_RW_CPT_TMR1_MODE_SPECIFICATION); - - /* Writes the low value */ - z8536_write(dev, data[3], - APCI1500_RW_CPT_TMR1_TIME_CST_LOW); - /* Writes the high value */ - data[3] = data[3] >> 8; - z8536_write(dev, data[3], - APCI1500_RW_CPT_TMR1_TIME_CST_HIGH); - - /* Enables timer/counter 1 and triggers timer/counter 1 */ - i_MasterConfiguration = z8536_read(dev, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - i_MasterConfiguration = - i_MasterConfiguration | 0x40; - z8536_write(dev, i_MasterConfiguration, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - /* Disable timer/counter 1 */ - z8536_write(dev, 0x00, - APCI1500_RW_CPT_TMR1_CMD_STATUS); - /* Trigger timer/counter 1 */ - z8536_write(dev, 0x02, - APCI1500_RW_CPT_TMR1_CMD_STATUS); - } else { - dev_warn(dev->class_dev, - "Error in selection of interrupt enable or disable\n"); - return -EINVAL; - } - } else { - dev_warn(dev->class_dev, - "Error in selection of reload value\n"); - return -EINVAL; - } - i_TimerCounterWatchdogInterrupt = data[7]; - i_TimerCounter1Init = 1; - break; - - case COUNTER2: /* selecting counter or timer */ - switch (data[2]) { - case 0: - data[2] = APCI1500_COUNTER; - break; - case 1: - data[2] = APCI1500_TIMER; - break; - default: - dev_warn(dev->class_dev, - "This choice is not a timer nor a counter\n"); - return -EINVAL; - } - - /* Selecting single or continuous mode */ - switch (data[4]) { - case 0: - data[4] = APCI1500_CONTINUOUS; - break; - case 1: - data[4] = APCI1500_SINGLE; - break; - default: - dev_warn(dev->class_dev, - "This option for single/continuous mode does not exist\n"); - return -EINVAL; - } - - /* Selecting software or hardware trigger */ - switch (data[5]) { - case 0: - data[5] = APCI1500_SOFTWARE_TRIGGER; - break; - case 1: - data[5] = APCI1500_HARDWARE_TRIGGER; - break; - default: - dev_warn(dev->class_dev, - "This choice for software or hardware trigger does not exist\n"); - return -EINVAL; - } - - /* Selecting software or hardware gate */ - switch (data[6]) { - case 0: - data[6] = APCI1500_SOFTWARE_GATE; - break; - case 1: - data[6] = APCI1500_HARDWARE_GATE; - break; - default: - dev_warn(dev->class_dev, - "This choice for software or hardware gate does not exist\n"); - return -EINVAL; - } - - i_TimerCounterMode = data[2] | data[4] | data[5] | data[6] | 7; - - /* Test the reload value */ - - if ((data[3] >= 0) && (data[3] <= 65535)) { - if (data[7] == APCI1500_ENABLE || - data[7] == APCI1500_DISABLE) { - /* Writes the new mode */ - z8536_write(dev, i_TimerCounterMode, - APCI1500_RW_CPT_TMR2_MODE_SPECIFICATION); - - /* Writes the low value */ - z8536_write(dev, data[3], - APCI1500_RW_CPT_TMR2_TIME_CST_LOW); - /* Writes the high value */ - data[3] = data[3] >> 8; - z8536_write(dev, data[3], - APCI1500_RW_CPT_TMR2_TIME_CST_HIGH); - - /* Enables timer/counter 2 and triggers timer/counter 2 */ - i_MasterConfiguration = z8536_read(dev, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - i_MasterConfiguration = - i_MasterConfiguration | 0x20; - z8536_write(dev, i_MasterConfiguration, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - /* Disable timer/counter 2 */ - z8536_write(dev, 0x00, - APCI1500_RW_CPT_TMR2_CMD_STATUS); - /* Trigger timer/counter 1 */ - z8536_write(dev, 0x02, - APCI1500_RW_CPT_TMR2_CMD_STATUS); - } else { - dev_warn(dev->class_dev, - "Error in selection of interrupt enable or disable\n"); - return -EINVAL; - } - } else { - dev_warn(dev->class_dev, - "Error in selection of reload value\n"); - return -EINVAL; - } - i_TimerCounterWatchdogInterrupt = data[7]; - i_TimerCounter2Init = 1; - break; - - case COUNTER3: /* selecting counter or watchdog */ - switch (data[2]) { - case 0: - data[2] = APCI1500_COUNTER; - break; - case 1: - data[2] = APCI1500_WATCHDOG; - break; - default: - dev_warn(dev->class_dev, - "This choice is not a watchdog nor a counter\n"); - return -EINVAL; - } - - /* Selecting single or continuous mode */ - switch (data[4]) { - case 0: - data[4] = APCI1500_CONTINUOUS; - break; - case 1: - data[4] = APCI1500_SINGLE; - break; - default: - dev_warn(dev->class_dev, - "This option for single/continuous mode does not exist\n"); - return -EINVAL; - } - - /* Selecting software or hardware gate */ - switch (data[6]) { - case 0: - data[6] = APCI1500_SOFTWARE_GATE; - break; - case 1: - data[6] = APCI1500_HARDWARE_GATE; - break; - default: - dev_warn(dev->class_dev, - "This choice for software or hardware gate does not exist\n"); - return -EINVAL; - } - - /* Test if used for watchdog */ - - if (data[2] == APCI1500_WATCHDOG) { - /* - Enables the output line */ - /* - Enables retrigger */ - /* - Pulses output */ - i_TimerCounterMode = data[2] | data[4] | 0x54; - } else { - i_TimerCounterMode = data[2] | data[4] | data[6] | 7; - } - /* Test the reload value */ - - if ((data[3] >= 0) && (data[3] <= 65535)) { - if (data[7] == APCI1500_ENABLE || - data[7] == APCI1500_DISABLE) { - /* Writes the new mode */ - z8536_write(dev, i_TimerCounterMode, - APCI1500_RW_CPT_TMR3_MODE_SPECIFICATION); - - /* Writes the low value */ - z8536_write(dev, data[3], - APCI1500_RW_CPT_TMR3_TIME_CST_LOW); - /* Writes the high value */ - data[3] = data[3] >> 8; - z8536_write(dev, data[3], - APCI1500_RW_CPT_TMR3_TIME_CST_HIGH); - - /* Enables watchdog/counter 3 and triggers watchdog/counter 3 */ - i_MasterConfiguration = z8536_read(dev, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - i_MasterConfiguration = - i_MasterConfiguration | 0x10; - z8536_write(dev, i_MasterConfiguration, - APCI1500_RW_MASTER_CONFIGURATION_CONTROL); - - /* Test if COUNTER */ - if (data[2] == APCI1500_COUNTER) { - /* Disable the watchdog/counter 3 and starts it */ - z8536_write(dev, 0x00, - APCI1500_RW_CPT_TMR3_CMD_STATUS); - /* Trigger the watchdog/counter 3 and starts it */ - z8536_write(dev, 0x02, - APCI1500_RW_CPT_TMR3_CMD_STATUS); - } - - } else { - - dev_warn(dev->class_dev, - "Error in selection of interrupt enable or disable\n"); - return -EINVAL; - } - } else { - dev_warn(dev->class_dev, - "Error in selection of reload value\n"); - return -EINVAL; - } - i_TimerCounterWatchdogInterrupt = data[7]; - i_WatchdogCounter3Init = 1; - break; - - default: - dev_warn(dev->class_dev, - "The specified counter/timer option does not exist\n"); - return -EINVAL; - } - i_CounterLogic = data[2]; - return insn->n; -} - -/* - * Start / Stop or trigger the timer counter or Watchdog - * - * data[0] 0 = Counter1/Timer1, 1 = Counter2/Timer2, 2 = Counter3/Watchdog - * data[1] 0 = Start, 1 = Stop, 2 = Trigger - * data[2] 0 = Counter, 1 = Timer/Watchdog - */ -static int apci1500_timer_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - int i_CommandAndStatusValue; - - switch (data[0]) { - case COUNTER1: - switch (data[1]) { - case START: - if (i_TimerCounter1Init == 1) { - if (i_TimerCounterWatchdogInterrupt == 1) - i_CommandAndStatusValue = 0xC4; /* Enable the interrupt */ - else - i_CommandAndStatusValue = 0xE4; /* disable the interrupt */ - - /* Starts timer/counter 1 */ - i_TimerCounter1Enabled = 1; - z8536_write(dev, i_CommandAndStatusValue, - APCI1500_RW_CPT_TMR1_CMD_STATUS); - } else { - dev_warn(dev->class_dev, - "Counter/Timer1 not configured\n"); - return -EINVAL; - } - break; - - case STOP: - /* Stop timer/counter 1 */ - z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR1_CMD_STATUS); - i_TimerCounter1Enabled = 0; - break; - - case TRIGGER: - if (i_TimerCounter1Init == 1) { - if (i_TimerCounter1Enabled == 1) { - /* Set Trigger and gate */ - - i_CommandAndStatusValue = 0x6; - } else { - /* Set Trigger */ - - i_CommandAndStatusValue = 0x2; - } - z8536_write(dev, i_CommandAndStatusValue, - APCI1500_RW_CPT_TMR1_CMD_STATUS); - } else { - dev_warn(dev->class_dev, - "Counter/Timer1 not configured\n"); - return -EINVAL; - } - break; - - default: - dev_warn(dev->class_dev, - "The specified option for start/stop/trigger does not exist\n"); - return -EINVAL; - } - break; - - case COUNTER2: - switch (data[1]) { - case START: - if (i_TimerCounter2Init == 1) { - if (i_TimerCounterWatchdogInterrupt == 1) - i_CommandAndStatusValue = 0xC4; /* Enable the interrupt */ - else - i_CommandAndStatusValue = 0xE4; /* disable the interrupt */ - - /* Starts timer/counter 2 */ - i_TimerCounter2Enabled = 1; - z8536_write(dev, i_CommandAndStatusValue, - APCI1500_RW_CPT_TMR2_CMD_STATUS); - } else { - dev_warn(dev->class_dev, - "Counter/Timer2 not configured\n"); - return -EINVAL; - } - break; - - case STOP: - /* Stop timer/counter 2 */ - z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR2_CMD_STATUS); - i_TimerCounter2Enabled = 0; - break; - case TRIGGER: - if (i_TimerCounter2Init == 1) { - if (i_TimerCounter2Enabled == 1) { - /* Set Trigger and gate */ - - i_CommandAndStatusValue = 0x6; - } else { - /* Set Trigger */ - - i_CommandAndStatusValue = 0x2; - } - z8536_write(dev, i_CommandAndStatusValue, - APCI1500_RW_CPT_TMR2_CMD_STATUS); - } else { - dev_warn(dev->class_dev, - "Counter/Timer2 not configured\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "The specified option for start/stop/trigger does not exist\n"); - return -EINVAL; - } - break; - case COUNTER3: - switch (data[1]) { - case START: - if (i_WatchdogCounter3Init == 1) { - - if (i_TimerCounterWatchdogInterrupt == 1) - i_CommandAndStatusValue = 0xC4; /* Enable the interrupt */ - else - i_CommandAndStatusValue = 0xE4; /* disable the interrupt */ - - /* Starts Watchdog/counter 3 */ - i_WatchdogCounter3Enabled = 1; - z8536_write(dev, i_CommandAndStatusValue, - APCI1500_RW_CPT_TMR3_CMD_STATUS); - } else { - dev_warn(dev->class_dev, - "Watchdog/Counter3 not configured\n"); - return -EINVAL; - } - break; - - case STOP: - /* Stop Watchdog/counter 3 */ - z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR3_CMD_STATUS); - i_WatchdogCounter3Enabled = 0; - break; - - case TRIGGER: - switch (data[2]) { - case 0: /* triggering counter 3 */ - if (i_WatchdogCounter3Init == 1) { - if (i_WatchdogCounter3Enabled == 1) { - /* Set Trigger and gate */ - - i_CommandAndStatusValue = 0x6; - } else { - /* Set Trigger */ - - i_CommandAndStatusValue = 0x2; - } - z8536_write(dev, i_CommandAndStatusValue, - APCI1500_RW_CPT_TMR3_CMD_STATUS); - } else { - dev_warn(dev->class_dev, - "Counter3 not configured\n"); - return -EINVAL; - } - break; - case 1: - /* triggering Watchdog 3 */ - if (i_WatchdogCounter3Init == 1) { - z8536_write(dev, 0x06, - APCI1500_RW_CPT_TMR3_CMD_STATUS); - } else { - dev_warn(dev->class_dev, - "Watchdog 3 not configured\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "Wrong choice of watchdog/counter3\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "The specified option for start/stop/trigger does not exist\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "The specified choice for counter/watchdog/timer does not exist\n"); - return -EINVAL; - } - return insn->n; -} - -/* - * Read The Watchdog - * - * data[0] 0 = Counter1/Timer1, 1 = Counter2/Timer2, 2 = Counter3/Watchdog - */ -static int apci1500_timer_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - int i_CommandAndStatusValue; - - switch (data[0]) { - case COUNTER1: - /* Read counter/timer1 */ - if (i_TimerCounter1Init == 1) { - if (i_TimerCounter1Enabled == 1) { - /* Set RCC and gate */ - - i_CommandAndStatusValue = 0xC; - } else { - /* Set RCC */ - - i_CommandAndStatusValue = 0x8; - } - z8536_write(dev, i_CommandAndStatusValue, - APCI1500_RW_CPT_TMR1_CMD_STATUS); - - data[0] = z8536_read(dev, - APCI1500_R_CPT_TMR1_VALUE_HIGH); - data[0] = data[0] << 8; - data[0] = data[0] & 0xff00; - data[0] |= z8536_read(dev, - APCI1500_R_CPT_TMR1_VALUE_LOW); - } else { - dev_warn(dev->class_dev, - "Timer/Counter1 not configured\n"); - return -EINVAL; - } - break; - case COUNTER2: - /* Read counter/timer2 */ - if (i_TimerCounter2Init == 1) { - if (i_TimerCounter2Enabled == 1) { - /* Set RCC and gate */ - - i_CommandAndStatusValue = 0xC; - } else { - /* Set RCC */ - - i_CommandAndStatusValue = 0x8; - } - z8536_write(dev, i_CommandAndStatusValue, - APCI1500_RW_CPT_TMR2_CMD_STATUS); - - data[0] = z8536_read(dev, - APCI1500_R_CPT_TMR2_VALUE_HIGH); - data[0] = data[0] << 8; - data[0] = data[0] & 0xff00; - data[0] |= z8536_read(dev, - APCI1500_R_CPT_TMR2_VALUE_LOW); - } else { - dev_warn(dev->class_dev, - "Timer/Counter2 not configured\n"); - return -EINVAL; - } - break; - case COUNTER3: - /* Read counter/watchdog2 */ - if (i_WatchdogCounter3Init == 1) { - if (i_WatchdogCounter3Enabled == 1) { - /* Set RCC and gate */ - - i_CommandAndStatusValue = 0xC; - } else { - /* Set RCC */ - - i_CommandAndStatusValue = 0x8; - } - z8536_write(dev, i_CommandAndStatusValue, - APCI1500_RW_CPT_TMR3_CMD_STATUS); - - data[0] = z8536_read(dev, - APCI1500_R_CPT_TMR3_VALUE_HIGH); - data[0] = data[0] << 8; - data[0] = data[0] & 0xff00; - data[0] |= z8536_read(dev, - APCI1500_R_CPT_TMR3_VALUE_LOW); - } else { - dev_warn(dev->class_dev, - "WatchdogCounter3 not configured\n"); - return -EINVAL; - } - break; - default: - dev_warn(dev->class_dev, - "The choice of timer/counter/watchdog does not exist\n"); - return -EINVAL; - } - - return insn->n; -} - -/* - * Read the interrupt mask - * - * data[0] The interrupt mask value - * data[1] Channel Number - */ -static int apci1500_timer_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - data[0] = i_InterruptMask; - data[1] = i_InputChannel; - i_InterruptMask = 0; - return insn->n; -} - -/* - * Configures the interrupt registers - */ -static int apci1500_do_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct apci1500_private *devpriv = dev->private; - int i_RegValue; - int i_Constant; - - devpriv->tsk_Current = current; - outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR); - if (data[0] == 1) { - i_Constant = 0xC0; - } else { - if (data[0] == 0) { - i_Constant = 0x00; - } else { - dev_warn(dev->class_dev, - "The parameter passed to driver is in error for enabling the voltage interrupt\n"); - return -EINVAL; - } - } - - /* Writes the new configuration (APCI1500_OR) */ - i_RegValue = z8536_read(dev, APCI1500_RW_PORT_B_SPECIFICATION); - i_RegValue = (i_RegValue & 0xF9) | APCI1500_OR; - z8536_write(dev, i_RegValue, APCI1500_RW_PORT_B_SPECIFICATION); - - /* Authorises the interrupt on the board */ - z8536_write(dev, 0xc0, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - - z8536_write(dev, i_Constant, APCI1500_RW_PORT_B_PATTERN_POLARITY); - z8536_write(dev, i_Constant, APCI1500_RW_PORT_B_PATTERN_TRANSITION); - z8536_write(dev, i_Constant, APCI1500_RW_PORT_B_PATTERN_MASK); - - /* Deletes the interrupt of port A */ - i_RegValue = z8536_read(dev, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - i_RegValue = (i_RegValue & 0x0F) | 0x20; - z8536_write(dev, i_RegValue, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - - /* Deletes the interrupt of port B */ - i_RegValue = z8536_read(dev, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - i_RegValue = (i_RegValue & 0x0F) | 0x20; - z8536_write(dev, i_RegValue, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - - /* Deletes the interrupt of timer 1 */ - i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS); - i_RegValue = (i_RegValue & 0x0F) | 0x20; - z8536_write(dev, i_RegValue, APCI1500_RW_CPT_TMR1_CMD_STATUS); - - /* Deletes the interrupt of timer 2 */ - i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS); - i_RegValue = (i_RegValue & 0x0F) | 0x20; - z8536_write(dev, i_RegValue, APCI1500_RW_CPT_TMR2_CMD_STATUS); - - /* Deletes the interrupt of timer 3 */ - i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS); - i_RegValue = (i_RegValue & 0x0F) | 0x20; - z8536_write(dev, i_RegValue, APCI1500_RW_CPT_TMR3_CMD_STATUS); - - /* Authorizes the main interrupt on the board */ - z8536_write(dev, 0xd0, APCI1500_RW_MASTER_INTERRUPT_CONTROL); - - /* Enables the PCI interrupt */ - outl(0x2000 | INTCSR_INBOX_FULL_INT, - devpriv->amcc + AMCC_OP_REG_INTCSR); - inl(devpriv->amcc + AMCC_OP_REG_IMB1); - inl(devpriv->amcc + AMCC_OP_REG_INTCSR); - outl(INTCSR_INBOX_INTR_STATUS | 0x2000 | INTCSR_INBOX_FULL_INT, - devpriv->amcc + AMCC_OP_REG_INTCSR); - - return insn->n; -} - -static irqreturn_t apci1500_interrupt(int irq, void *d) -{ - - struct comedi_device *dev = d; - struct apci1500_private *devpriv = dev->private; - unsigned int val; - - /* Clear the interrupt mask */ - i_InterruptMask = 0; - - val = inl(devpriv->amcc + AMCC_OP_REG_INTCSR); - if (!(val & INTCSR_INTR_ASSERTED)) - return IRQ_NONE; - - /* Disable all Interrupt */ - /* Selects the master interrupt control register */ - /* Disables the main interrupt on the board */ - val = z8536_read(dev, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - if ((val & 0x60) == 0x60) { - /* Deletes the interrupt of port A */ - val &= 0x0f; - val |= 0x20; - z8536_write(dev, val, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - i_InterruptMask = i_InterruptMask | 1; - if (i_Logic == APCI1500_OR_PRIORITY) { - val = z8536_read(dev, APCI1500_RW_PORT_A_SPECIFICATION); - - val = z8536_read(dev, - APCI1500_RW_PORT_A_INTERRUPT_CONTROL); - - i_InputChannel = 1 + (val >> 1); - - } else { - i_InputChannel = 0; - } - } - - val = z8536_read(dev, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - if ((val & 0x60) == 0x60) { - /* Deletes the interrupt of port B */ - val &= 0x0f; - val |= 0x20; - z8536_write(dev, val, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - - /* Reads port B */ - val = inb(dev->iobase + APCI1500_Z8536_PORTB_REG); - val &= 0xc0; - /* Tests if this is an external error */ - if (val) { - /* Disable the interrupt */ - /* Selects the command and status register of port B */ - outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR); - - if (val & 0x80) - i_InterruptMask |= 0x40; - - if (val & 0x40) { - i_InterruptMask |= 0x80; - } - } else { - i_InterruptMask |= 0x02; - } - } - - val = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS); - if ((val & 0x60) == 0x60) { - /* Deletes the interrupt of timer 1 */ - val &= 0x0f; - val |= 0x20; - z8536_write(dev, val, APCI1500_RW_CPT_TMR1_CMD_STATUS); - - i_InterruptMask |= 0x04; - } - - val = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS); - if ((val & 0x60) == 0x60) { - /* Deletes the interrupt of timer 2 */ - val &= 0x0f; - val |= 0x20; - z8536_write(dev, val, APCI1500_RW_CPT_TMR2_CMD_STATUS); - - i_InterruptMask |= 0x08; - } - - val = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS); - if ((val & 0x60) == 0x60) { - /* Deletes the interrupt of timer 3 */ - val &= 0x0f; - val |= 0x20; - z8536_write(dev, val, APCI1500_RW_CPT_TMR3_CMD_STATUS); - - if (i_CounterLogic == APCI1500_COUNTER) - i_InterruptMask |= 0x10; - else - i_InterruptMask |= 0x20; - } - - /* send signal to the sample */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - - /* Authorizes the main interrupt on the board */ - z8536_write(dev, 0xd0, APCI1500_RW_MASTER_INTERRUPT_CONTROL); - - return IRQ_HANDLED; -} - -static int apci1500_reset(struct comedi_device *dev) -{ - struct apci1500_private *devpriv = dev->private; - - i_TimerCounter1Init = 0; - i_TimerCounter2Init = 0; - i_WatchdogCounter3Init = 0; - i_Event1Status = 0; - i_Event2Status = 0; - i_TimerCounterWatchdogInterrupt = 0; - i_Logic = 0; - i_CounterLogic = 0; - i_InterruptMask = 0; - i_InputChannel = 0; - i_TimerCounter1Enabled = 0; - i_TimerCounter2Enabled = 0; - i_WatchdogCounter3Enabled = 0; - - /* Software reset */ - z8536_reset(dev); - - /* reset all the digital outputs */ - outw(0x0, devpriv->addon + APCI1500_DO_REG); - - /* Deactivates all interrupts */ - z8536_write(dev, 0x00, APCI1500_RW_MASTER_INTERRUPT_CONTROL); - z8536_write(dev, 0x00, APCI1500_RW_PORT_A_COMMAND_AND_STATUS); - z8536_write(dev, 0x00, APCI1500_RW_PORT_B_COMMAND_AND_STATUS); - z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR1_CMD_STATUS); - z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR2_CMD_STATUS); - z8536_write(dev, 0x00, APCI1500_RW_CPT_TMR3_CMD_STATUS); - - return 0; -} diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 6892c0a..fc7db1d 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -1,11 +1,34 @@ +/* + * addi_apci_1500.c + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data.com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + #include #include -#include #include #include "../comedidev.h" #include "comedi_fc.h" #include "amcc_s5933.h" +#include "z8536.h" /* * PCI Bar 0 Register map (devpriv->amcc) @@ -14,6 +37,7 @@ /* * PCI Bar 1 Register map (dev->iobase) + * see z8536.h for Z8536 internal registers and bit defines */ #define APCI1500_Z8536_PORTC_REG 0x00 #define APCI1500_Z8536_PORTB_REG 0x01 @@ -30,11 +54,702 @@ struct apci1500_private { unsigned long amcc; unsigned long addon; - unsigned char b_OutputMemoryStatus; - struct task_struct *tsk_Current; + + unsigned int clk_src; + + /* Digital trigger configuration [0]=AND [1]=OR */ + unsigned int pm[2]; /* Pattern Mask */ + unsigned int pt[2]; /* Pattern Transition */ + unsigned int pp[2]; /* Pattern Polarity */ }; -#include "addi-data/hwdrv_apci1500.c" +static unsigned int z8536_read(struct comedi_device *dev, unsigned int reg) +{ + unsigned long flags; + unsigned int val; + + spin_lock_irqsave(&dev->spinlock, flags); + outb(reg, dev->iobase + APCI1500_Z8536_CTRL_REG); + val = inb(dev->iobase + APCI1500_Z8536_CTRL_REG); + spin_unlock_irqrestore(&dev->spinlock, flags); + + return val; +} + +static void z8536_write(struct comedi_device *dev, + unsigned int val, unsigned int reg) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->spinlock, flags); + outb(reg, dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(val, dev->iobase + APCI1500_Z8536_CTRL_REG); + spin_unlock_irqrestore(&dev->spinlock, flags); +} + +static void z8536_reset(struct comedi_device *dev) +{ + unsigned long flags; + + /* + * Even if the state of the Z8536 is not known, the following + * sequence will reset it and put it in State 0. + */ + spin_lock_irqsave(&dev->spinlock, flags); + inb(dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); + inb(dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(1, dev->iobase + APCI1500_Z8536_CTRL_REG); + outb(0, dev->iobase + APCI1500_Z8536_CTRL_REG); + spin_unlock_irqrestore(&dev->spinlock, flags); + + /* Disable all Ports and Counter/Timers */ + z8536_write(dev, 0x00, Z8536_CFG_CTRL_REG); + + /* + * Port A is connected to Ditial Input channels 0-7. + * Configure the port to allow interrupt detection. + */ + z8536_write(dev, Z8536_PAB_MODE_PTS_BIT | + Z8536_PAB_MODE_SB | + Z8536_PAB_MODE_PMS_DISABLE, + Z8536_PA_MODE_REG); + z8536_write(dev, 0xff, Z8536_PB_DPP_REG); + z8536_write(dev, 0xff, Z8536_PA_DD_REG); + + /* + * Port B is connected to Ditial Input channels 8-13. + * Configure the port to allow interrupt detection. + * + * NOTE: Bits 7 and 6 of Port B are connected to internal + * diagnostic signals and bit 7 is inverted. + */ + z8536_write(dev, Z8536_PAB_MODE_PTS_BIT | + Z8536_PAB_MODE_SB | + Z8536_PAB_MODE_PMS_DISABLE, + Z8536_PB_MODE_REG); + z8536_write(dev, 0x7f, Z8536_PB_DPP_REG); + z8536_write(dev, 0xff, Z8536_PB_DD_REG); + + /* + * Not sure what Port C is connected to... + */ + z8536_write(dev, 0x09, Z8536_PC_DPP_REG); + z8536_write(dev, 0x0e, Z8536_PC_DD_REG); + + /* + * Clear and disable all interrupt sources. + * + * Just in case, the reset of the Z8536 should have already + * done this. + */ + z8536_write(dev, Z8536_CMD_CLR_IP_IUS, Z8536_PA_CMDSTAT_REG); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_PA_CMDSTAT_REG); + + z8536_write(dev, Z8536_CMD_CLR_IP_IUS, Z8536_PB_CMDSTAT_REG); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_PB_CMDSTAT_REG); + + z8536_write(dev, Z8536_CMD_CLR_IP_IUS, Z8536_CT_CMDSTAT_REG(0)); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_CT_CMDSTAT_REG(0)); + + z8536_write(dev, Z8536_CMD_CLR_IP_IUS, Z8536_CT_CMDSTAT_REG(1)); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_CT_CMDSTAT_REG(1)); + + z8536_write(dev, Z8536_CMD_CLR_IP_IUS, Z8536_CT_CMDSTAT_REG(2)); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_CT_CMDSTAT_REG(2)); + + /* Disable all interrupts */ + z8536_write(dev, 0x00, Z8536_INT_CTRL_REG); +} + +static void apci1500_port_enable(struct comedi_device *dev, bool enable) +{ + unsigned int cfg; + + cfg = z8536_read(dev, Z8536_CFG_CTRL_REG); + if (enable) + cfg |= (Z8536_CFG_CTRL_PAE | Z8536_CFG_CTRL_PBE); + else + cfg &= ~(Z8536_CFG_CTRL_PAE | Z8536_CFG_CTRL_PBE); + z8536_write(dev, cfg, Z8536_CFG_CTRL_REG); +} + +static void apci1500_timer_enable(struct comedi_device *dev, + unsigned int chan, bool enable) +{ + unsigned int bit; + unsigned int cfg; + + if (chan == 0) + bit = Z8536_CFG_CTRL_CT1E; + else if (chan == 1) + bit = Z8536_CFG_CTRL_CT2E; + else + bit = Z8536_CFG_CTRL_PCE_CT3E; + + cfg = z8536_read(dev, Z8536_CFG_CTRL_REG); + if (enable) { + cfg |= bit; + } else { + cfg &= ~bit; + z8536_write(dev, 0x00, Z8536_CT_CMDSTAT_REG(chan)); + } + z8536_write(dev, cfg, Z8536_CFG_CTRL_REG); +} + +static bool apci1500_ack_irq(struct comedi_device *dev, + unsigned int reg) +{ + unsigned int val; + + val = z8536_read(dev, reg); + if ((val & Z8536_STAT_IE_IP) == Z8536_STAT_IE_IP) { + val &= 0x0f; /* preserve any write bits */ + val |= Z8536_CMD_CLR_IP_IUS; + z8536_write(dev, val, reg); + + return true; + } + return false; +} + +static irqreturn_t apci1500_interrupt(int irq, void *d) +{ + struct comedi_device *dev = d; + struct apci1500_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; + unsigned int status = 0; + unsigned int val; + + val = inl(devpriv->amcc + AMCC_OP_REG_INTCSR); + if (!(val & INTCSR_INTR_ASSERTED)) + return IRQ_NONE; + + if (apci1500_ack_irq(dev, Z8536_PA_CMDSTAT_REG)) + status |= 0x01; /* port a event (inputs 0-7) */ + + if (apci1500_ack_irq(dev, Z8536_PB_CMDSTAT_REG)) { + /* Tests if this is an external error */ + val = inb(dev->iobase + APCI1500_Z8536_PORTB_REG); + val &= 0xc0; + if (val) { + if (val & 0x80) /* voltage error */ + status |= 0x40; + if (val & 0x40) /* short circuit error */ + status |= 0x80; + } else { + status |= 0x02; /* port b event (inputs 8-13) */ + } + } + + /* + * NOTE: The 'status' returned by the sample matches the + * interrupt mask information from the APCI-1500 Users Manual. + * + * Mask Meaning + * ---------- ------------------------------------------ + * 0x00000001 Event 1 has occured + * 0x00000010 Event 2 has occured + * 0x00000100 Counter/timer 1 has run down (not implemented) + * 0x00001000 Counter/timer 2 has run down (not implemented) + * 0x00010000 Counter 3 has run down (not implemented) + * 0x00100000 Watchdog has run down (not implemented) + * 0x01000000 Voltage error + * 0x10000000 Short-circuit error + */ + comedi_buf_write_samples(s, &status, 1); + comedi_handle_events(dev, s); + + return IRQ_HANDLED; +} + +static int apci1500_di_cancel(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + /* Disables the main interrupt on the board */ + z8536_write(dev, 0x00, Z8536_INT_CTRL_REG); + + /* Disable Ports A & B */ + apci1500_port_enable(dev, false); + + /* Ack any pending interrupts */ + apci1500_ack_irq(dev, Z8536_PA_CMDSTAT_REG); + apci1500_ack_irq(dev, Z8536_PB_CMDSTAT_REG); + + /* Disable pattern interrupts */ + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_PA_CMDSTAT_REG); + z8536_write(dev, Z8536_CMD_CLR_IE, Z8536_PB_CMDSTAT_REG); + + /* Enable Ports A & B */ + apci1500_port_enable(dev, true); + + return 0; +} + +static int apci1500_di_inttrig_start(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int trig_num) +{ + struct apci1500_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; + unsigned int pa_mode = Z8536_PAB_MODE_PMS_DISABLE; + unsigned int pb_mode = Z8536_PAB_MODE_PMS_DISABLE; + unsigned int pa_trig = trig_num & 0x01; + unsigned int pb_trig = trig_num & 0x02; + bool valid_trig = false; + unsigned int val; + + if (trig_num != cmd->start_arg) + return -EINVAL; + + /* Disable Ports A & B */ + apci1500_port_enable(dev, false); + + /* Set Port A for selected trigger pattern */ + z8536_write(dev, devpriv->pm[pa_trig] & 0xff, Z8536_PA_PM_REG); + z8536_write(dev, devpriv->pt[pa_trig] & 0xff, Z8536_PA_PT_REG); + z8536_write(dev, devpriv->pp[pa_trig] & 0xff, Z8536_PA_PP_REG); + + /* Set Port B for selected trigger pattern */ + z8536_write(dev, (devpriv->pm[pb_trig] >> 8) & 0xff, Z8536_PB_PM_REG); + z8536_write(dev, (devpriv->pt[pb_trig] >> 8) & 0xff, Z8536_PB_PT_REG); + z8536_write(dev, (devpriv->pp[pb_trig] >> 8) & 0xff, Z8536_PB_PP_REG); + + /* Set Port A trigger mode (if enabled) and enable interrupt */ + if (devpriv->pm[pa_trig] & 0xff) { + pa_mode = pa_trig ? Z8536_PAB_MODE_PMS_AND + : Z8536_PAB_MODE_PMS_OR; + + val = z8536_read(dev, Z8536_PA_MODE_REG); + val &= ~Z8536_PAB_MODE_PMS_MASK; + val |= (pa_mode | Z8536_PAB_MODE_IMO); + z8536_write(dev, val, Z8536_PA_MODE_REG); + + z8536_write(dev, Z8536_CMD_SET_IE, Z8536_PA_CMDSTAT_REG); + + valid_trig = true; + + dev_dbg(dev->class_dev, + "Port A configured for %s mode pattern detection\n", + pa_trig ? "AND" : "OR"); + } + + /* Set Port B trigger mode (if enabled) and enable interrupt */ + if (devpriv->pm[pb_trig] & 0xff00) { + pb_mode = pb_trig ? Z8536_PAB_MODE_PMS_AND + : Z8536_PAB_MODE_PMS_OR; + + val = z8536_read(dev, Z8536_PB_MODE_REG); + val &= ~Z8536_PAB_MODE_PMS_MASK; + val |= (pb_mode | Z8536_PAB_MODE_IMO); + z8536_write(dev, val, Z8536_PB_MODE_REG); + + z8536_write(dev, Z8536_CMD_SET_IE, Z8536_PB_CMDSTAT_REG); + + valid_trig = true; + + dev_dbg(dev->class_dev, + "Port B configured for %s mode pattern detection\n", + pb_trig ? "AND" : "OR"); + } + + /* Enable Ports A & B */ + apci1500_port_enable(dev, true); + + if (!valid_trig) { + dev_dbg(dev->class_dev, + "digital trigger %d is not configured\n", trig_num); + return -EINVAL; + } + + /* Authorizes the main interrupt on the board */ + z8536_write(dev, Z8536_INT_CTRL_MIE | Z8536_INT_CTRL_DLC, + Z8536_INT_CTRL_REG); + + return 0; +} + +static int apci1500_di_cmd(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + s->async->inttrig = apci1500_di_inttrig_start; + + return 0; +} + +static int apci1500_di_cmdtest(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + int err = 0; + + /* Step 1 : check if triggers are trivially valid */ + + err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT); + err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); + err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW); + err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + + if (err) + return 1; + + /* Step 2a : make sure trigger sources are unique */ + /* Step 2b : and mutually compatible */ + + /* Step 3: check if arguments are trivially valid */ + + /* + * Internal start source triggers: + * + * 0 AND mode for Port A (digital inputs 0-7) + * AND mode for Port B (digital inputs 8-13 and internal signals) + * + * 1 OR mode for Port A (digital inputs 0-7) + * AND mode for Port B (digital inputs 8-13 and internal signals) + * + * 2 AND mode for Port A (digital inputs 0-7) + * OR mode for Port B (digital inputs 8-13 and internal signals) + * + * 3 OR mode for Port A (digital inputs 0-7) + * OR mode for Port B (digital inputs 8-13 and internal signals) + */ + err |= cfc_check_trigger_arg_max(&cmd->start_arg, 3); + + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); + err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); + err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); + + if (err) + return 3; + + /* Step 4: fix up any arguments */ + + /* Step 5: check channel list if it exists */ + + return 0; +} + +/* + * The pattern-recognition logic must be configured before the digital + * input async command is started. + * + * Digital input channels 0 to 13 can generate interrupts. Channels 14 + * and 15 are connected to internal board status/diagnostic signals. + * + * Channel 14 - Voltage error (the external supply is < 5V) + * Channel 15 - Short-circuit/overtemperature error + * + * data[0] : INSN_CONFIG_DIGITAL_TRIG + * data[1] : trigger number + * 0 = AND mode + * 1 = OR mode + * data[2] : configuration operation: + * COMEDI_DIGITAL_TRIG_DISABLE = no interrupts + * COMEDI_DIGITAL_TRIG_ENABLE_EDGES = edge interrupts + * COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = level interrupts + * data[3] : left-shift for data[4] and data[5] + * data[4] : rising-edge/high level channels + * data[5] : falling-edge/low level channels + */ +static int apci1500_di_cfg_trig(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct apci1500_private *devpriv = dev->private; + unsigned int trig = data[1]; + unsigned int shift = data[3]; + unsigned int hi_mask = data[4] << shift; + unsigned int lo_mask = data[5] << shift; + unsigned int chan_mask = hi_mask | lo_mask; + unsigned int old_mask = (1 << shift) - 1; + unsigned int pm = devpriv->pm[trig] & old_mask; + unsigned int pt = devpriv->pt[trig] & old_mask; + unsigned int pp = devpriv->pp[trig] & old_mask; + + if (trig > 1) { + dev_dbg(dev->class_dev, + "invalid digital trigger number (0=AND, 1=OR)\n"); + return -EINVAL; + } + + if (chan_mask > 0xffff) { + dev_dbg(dev->class_dev, "invalid digital trigger channel\n"); + return -EINVAL; + } + + switch (data[2]) { + case COMEDI_DIGITAL_TRIG_DISABLE: + /* clear trigger configuration */ + pm = 0; + pt = 0; + pp = 0; + break; + case COMEDI_DIGITAL_TRIG_ENABLE_EDGES: + pm |= chan_mask; /* enable channels */ + pt |= chan_mask; /* enable edge detection */ + pp |= hi_mask; /* rising-edge channels */ + pp &= ~lo_mask; /* falling-edge channels */ + break; + case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS: + pm |= chan_mask; /* enable channels */ + pt &= ~chan_mask; /* enable level detection */ + pp |= hi_mask; /* high level channels */ + pp &= ~lo_mask; /* low level channels */ + break; + default: + return -EINVAL; + } + + /* + * The AND mode trigger can only have one channel (max) enabled + * for edge detection. + */ + if (trig == 0) { + int ret = 0; + unsigned int src; + + src = pt & 0xff; + if (src) + ret |= cfc_check_trigger_is_unique(src); + + src = (pt >> 8) & 0xff; + if (src) + ret |= cfc_check_trigger_is_unique(src); + + if (ret) { + dev_dbg(dev->class_dev, + "invalid AND trigger configuration\n"); + return ret; + } + } + + /* save the trigger configuration */ + devpriv->pm[trig] = pm; + devpriv->pt[trig] = pt; + devpriv->pp[trig] = pp; + + return insn->n; +} + +static int apci1500_di_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + switch (data[0]) { + case INSN_CONFIG_DIGITAL_TRIG: + return apci1500_di_cfg_trig(dev, s, insn, data); + default: + return -EINVAL; + } +} + +static int apci1500_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct apci1500_private *devpriv = dev->private; + + data[1] = inw(devpriv->addon + APCI1500_DI_REG); + + return insn->n; +} + +static int apci1500_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct apci1500_private *devpriv = dev->private; + + if (comedi_dio_update_state(s, data)) + outw(s->state, devpriv->addon + APCI1500_DO_REG); + + data[1] = s->state; + + return insn->n; +} + +static int apci1500_timer_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct apci1500_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int val; + + switch (data[0]) { + case INSN_CONFIG_ARM: + val = data[1] & s->maxdata; + z8536_write(dev, val & 0xff, Z8536_CT_RELOAD_LSB_REG(chan)); + z8536_write(dev, (val >> 8) & 0xff, + Z8536_CT_RELOAD_MSB_REG(chan)); + + apci1500_timer_enable(dev, chan, true); + z8536_write(dev, Z8536_CT_CMDSTAT_GCB, + Z8536_CT_CMDSTAT_REG(chan)); + break; + case INSN_CONFIG_DISARM: + apci1500_timer_enable(dev, chan, false); + break; + + case INSN_CONFIG_GET_COUNTER_STATUS: + data[1] = 0; + val = z8536_read(dev, Z8536_CT_CMDSTAT_REG(chan)); + if (val & Z8536_CT_STAT_CIP) + data[1] |= COMEDI_COUNTER_COUNTING; + if (val & Z8536_CT_CMDSTAT_GCB) + data[1] |= COMEDI_COUNTER_ARMED; + if (val & Z8536_STAT_IP) { + data[1] |= COMEDI_COUNTER_TERMINAL_COUNT; + apci1500_ack_irq(dev, Z8536_CT_CMDSTAT_REG(chan)); + } + data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING | + COMEDI_COUNTER_TERMINAL_COUNT; + break; + + case INSN_CONFIG_SET_COUNTER_MODE: + /* Simulate the 8254 timer modes */ + switch (data[1]) { + case I8254_MODE0: + /* Interrupt on Terminal Count */ + val = Z8536_CT_MODE_ECE | + Z8536_CT_MODE_DCS_ONESHOT; + break; + case I8254_MODE1: + /* Hardware Retriggerable One-Shot */ + val = Z8536_CT_MODE_ETE | + Z8536_CT_MODE_DCS_ONESHOT; + break; + case I8254_MODE2: + /* Rate Generator */ + val = Z8536_CT_MODE_CSC | + Z8536_CT_MODE_DCS_PULSE; + break; + case I8254_MODE3: + /* Square Wave Mode */ + val = Z8536_CT_MODE_CSC | + Z8536_CT_MODE_DCS_SQRWAVE; + break; + case I8254_MODE4: + /* Software Triggered Strobe */ + val = Z8536_CT_MODE_REB | + Z8536_CT_MODE_DCS_PULSE; + break; + case I8254_MODE5: + /* Hardware Triggered Strobe (watchdog) */ + val = Z8536_CT_MODE_EOE | + Z8536_CT_MODE_ETE | + Z8536_CT_MODE_REB | + Z8536_CT_MODE_DCS_PULSE; + break; + default: + return -EINVAL; + } + apci1500_timer_enable(dev, chan, false); + z8536_write(dev, val, Z8536_CT_MODE_REG(chan)); + break; + + case INSN_CONFIG_SET_CLOCK_SRC: + if (data[1] > 2) + return -EINVAL; + devpriv->clk_src = data[1]; + if (devpriv->clk_src == 2) + devpriv->clk_src = 3; + outw(devpriv->clk_src, devpriv->addon + APCI1500_CLK_SEL_REG); + break; + case INSN_CONFIG_GET_CLOCK_SRC: + switch (devpriv->clk_src) { + case 0: + data[1] = 0; /* 111.86 kHz / 2 */ + data[2] = 17879; /* 17879 ns (approx) */ + break; + case 1: + data[1] = 1; /* 3.49 kHz / 2 */ + data[2] = 573066; /* 573066 ns (approx) */ + break; + case 3: + data[1] = 2; /* 1.747 kHz / 2 */ + data[2] = 1164822; /* 1164822 ns (approx) */ + break; + default: + return -EINVAL; + } + break; + + case INSN_CONFIG_SET_GATE_SRC: + if (chan == 0) + return -EINVAL; + + val = z8536_read(dev, Z8536_CT_MODE_REG(chan)); + val &= Z8536_CT_MODE_EGE; + if (data[1] == 1) + val |= Z8536_CT_MODE_EGE; + else if (data[1] > 1) + return -EINVAL; + z8536_write(dev, val, Z8536_CT_MODE_REG(chan)); + break; + case INSN_CONFIG_GET_GATE_SRC: + if (chan == 0) + return -EINVAL; + break; + + default: + return -EINVAL; + } + return insn->n; +} + +static int apci1500_timer_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int cmd; + + cmd = z8536_read(dev, Z8536_CT_CMDSTAT_REG(chan)); + cmd &= Z8536_CT_CMDSTAT_GCB; /* preserve gate */ + cmd |= Z8536_CT_CMD_TCB; /* set trigger */ + + /* software trigger a timer, it only makes sense to do one write */ + if (insn->n) + z8536_write(dev, cmd, Z8536_CT_CMDSTAT_REG(chan)); + + return insn->n; +} + +static int apci1500_timer_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int cmd; + unsigned int val; + int i; + + cmd = z8536_read(dev, Z8536_CT_CMDSTAT_REG(chan)); + cmd &= Z8536_CT_CMDSTAT_GCB; /* preserve gate */ + cmd |= Z8536_CT_CMD_RCC; /* set RCC */ + + for (i = 0; i < insn->n; i++) { + z8536_write(dev, cmd, Z8536_CT_CMDSTAT_REG(chan)); + + val = z8536_read(dev, Z8536_CT_VAL_MSB_REG(chan)) << 8; + val |= z8536_read(dev, Z8536_CT_VAL_LSB_REG(chan)); + + data[i] = val; + } + + return insn->n; +} static int apci1500_auto_attach(struct comedi_device *dev, unsigned long context) @@ -56,6 +771,8 @@ static int apci1500_auto_attach(struct comedi_device *dev, devpriv->amcc = pci_resource_start(pcidev, 0); devpriv->addon = pci_resource_start(pcidev, 2); + z8536_reset(dev); + if (pcidev->irq > 0) { ret = request_irq(pcidev->irq, apci1500_interrupt, IRQF_SHARED, dev->board_name, dev); @@ -67,51 +784,66 @@ static int apci1500_auto_attach(struct comedi_device *dev, if (ret) return ret; - /* Allocate and Initialise DI Subdevice Structures */ + /* Digital Input subdevice */ s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_config = apci1500_di_config; - s->insn_read = apci1500_di_read; - s->insn_write = apci1500_di_write; - s->insn_bits = apci1500_di_insn_bits; - - /* Allocate and Initialise DO Subdevice Structures */ + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = apci1500_di_insn_bits; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = 1; + s->insn_config = apci1500_di_insn_config; + s->do_cmdtest = apci1500_di_cmdtest; + s->do_cmd = apci1500_di_cmd; + s->cancel = apci1500_di_cancel; + } + + /* Digital Output subdevice */ s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_config = apci1500_do_config; - s->insn_write = apci1500_do_write; - s->insn_bits = apci1500_do_bits; - - /* Allocate and Initialise Timer Subdevice Structures */ + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = apci1500_do_insn_bits; + + /* reset all the digital outputs */ + outw(0x0, devpriv->addon + APCI1500_DO_REG); + + /* Counter/Timer(Watchdog) subdevice */ s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_TIMER; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 1; - s->maxdata = 0; - s->len_chanlist = 1; - s->range_table = &range_digital; - s->insn_write = apci1500_timer_write; - s->insn_read = apci1500_timer_read; - s->insn_config = apci1500_timer_config; - s->insn_bits = apci1500_timer_bits; - - apci1500_reset(dev); + s->type = COMEDI_SUBD_TIMER; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 3; + s->maxdata = 0xffff; + s->range_table = &range_unknown; + s->insn_config = apci1500_timer_insn_config; + s->insn_write = apci1500_timer_insn_write; + s->insn_read = apci1500_timer_insn_read; + + /* Enable the PCI interrupt */ + if (dev->irq) { + outl(0x2000 | INTCSR_INBOX_FULL_INT, + devpriv->amcc + AMCC_OP_REG_INTCSR); + inl(devpriv->amcc + AMCC_OP_REG_IMB1); + inl(devpriv->amcc + AMCC_OP_REG_INTCSR); + outl(INTCSR_INBOX_INTR_STATUS | 0x2000 | INTCSR_INBOX_FULL_INT, + devpriv->amcc + AMCC_OP_REG_INTCSR); + } return 0; } static void apci1500_detach(struct comedi_device *dev) { - if (dev->iobase) - apci1500_reset(dev); + struct apci1500_private *devpriv = dev->private; + + if (devpriv->amcc) + outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR); comedi_pci_detach(dev); } diff --git a/drivers/staging/comedi/drivers/z8536.h b/drivers/staging/comedi/drivers/z8536.h new file mode 100644 index 0000000..7be5310 --- /dev/null +++ b/drivers/staging/comedi/drivers/z8536.h @@ -0,0 +1,202 @@ +/* + * Z8536 CIO Internal registers + */ + +#ifndef _Z8536_H +#define _Z8536_H + +/* Master Interrupt Control register */ +#define Z8536_INT_CTRL_REG 0x00 +#define Z8536_INT_CTRL_MIE BIT(7) /* Master Interrupt Enable */ +#define Z8536_INT_CTRL_DLC BIT(6) /* Disable Lower Chain */ +#define Z8536_INT_CTRL_NV BIT(5) /* No Vector */ +#define Z8536_INT_CTRL_PA_VIS BIT(4) /* Port A Vect Inc Status */ +#define Z8536_INT_CTRL_PB_VIS BIT(3) /* Port B Vect Inc Status */ +#define Z8536_INT_CTRL_VT_VIS BIT(2) /* C/T Vect Inc Status */ +#define Z8536_INT_CTRL_RJA BIT(1) /* Right Justified Addresses */ +#define Z8536_INT_CTRL_RESET BIT(0) /* Reset */ + +/* Master Configuration Control register */ +#define Z8536_CFG_CTRL_REG 0x01 +#define Z8536_CFG_CTRL_PBE BIT(7) /* Port B Enable */ +#define Z8536_CFG_CTRL_CT1E BIT(6) /* C/T 1 Enable */ +#define Z8536_CFG_CTRL_CT2E BIT(5) /* C/T 2 Enable */ +#define Z8536_CFG_CTRL_PCE_CT3E BIT(4) /* Port C & C/T 3 Enable */ +#define Z8536_CFG_CTRL_PLC BIT(3) /* Port A/B Link Control */ +#define Z8536_CFG_CTRL_PAE BIT(2) /* Port A Enable */ +#define Z8536_CFG_CTRL_LC_INDEP (0 << 0)/* C/Ts Independent */ +#define Z8536_CFG_CTRL_LC_GATE (1 << 0)/* C/T 1 Out Gates C/T 2 */ +#define Z8536_CFG_CTRL_LC_TRIG (2 << 0)/* C/T 1 Out Triggers C/T 2 */ +#define Z8536_CFG_CTRL_LC_CLK (3 << 0)/* C/T 1 Out Clocks C/T 2 */ +#define Z8536_CFG_CTRL_LC_MASK (3 << 0)/* C/T Link Control mask */ + +/* Interrupt Vector registers */ +#define Z8536_PA_INT_VECT_REG 0x02 +#define Z8536_PB_INT_VECT_REG 0x03 +#define Z8536_CT_INT_VECT_REG 0x04 +#define Z8536_CURR_INT_VECT_REG 0x1f + +/* Port A/B & Counter/Timer 1/2/3 Command and Status registers */ +#define Z8536_PA_CMDSTAT_REG 0x08 +#define Z8536_PB_CMDSTAT_REG 0x09 +#define Z8536_CT1_CMDSTAT_REG 0x0a +#define Z8536_CT2_CMDSTAT_REG 0x0b +#define Z8536_CT3_CMDSTAT_REG 0x0c +#define Z8536_CT_CMDSTAT_REG(x) (0x0a + (x)) +#define Z8536_CMD_NULL (0 << 5)/* Null Code */ +#define Z8536_CMD_CLR_IP_IUS (1 << 5)/* Clear IP & IUS */ +#define Z8536_CMD_SET_IUS (2 << 5)/* Set IUS */ +#define Z8536_CMD_CLR_IUS (3 << 5)/* Clear IUS */ +#define Z8536_CMD_SET_IP (4 << 5)/* Set IP */ +#define Z8536_CMD_CLR_IP (5 << 5)/* Clear IP */ +#define Z8536_CMD_SET_IE (6 << 5)/* Set IE */ +#define Z8536_CMD_CLR_IE (7 << 5)/* Clear IE */ +#define Z8536_CMD_MASK (7 << 5) + +#define Z8536_STAT_IUS BIT(7) /* Interrupt Under Service */ +#define Z8536_STAT_IE BIT(6) /* Interrupt Enable */ +#define Z8536_STAT_IP BIT(5) /* Interrupt Pending */ +#define Z8536_STAT_ERR BIT(4) /* Interrupt Error */ +#define Z8536_STAT_IE_IP (Z8536_STAT_IE | Z8536_STAT_IP) + +#define Z8536_PAB_STAT_ORE BIT(3) /* Output Register Empty */ +#define Z8536_PAB_STAT_IRF BIT(2) /* Input Register Full */ +#define Z8536_PAB_STAT_PMF BIT(1) /* Pattern Match Flag */ +#define Z8536_PAB_CMDSTAT_IOE BIT(0) /* Interrupt On Error */ + +#define Z8536_CT_CMD_RCC BIT(3) /* Read Counter Control */ +#define Z8536_CT_CMDSTAT_GCB BIT(2) /* Gate Command Bit */ +#define Z8536_CT_CMD_TCB BIT(1) /* Trigger Command Bit */ +#define Z8536_CT_STAT_CIP BIT(0) /* Count In Progress */ + +/* Port Data registers */ +#define Z8536_PA_DATA_REG 0x0d +#define Z8536_PB_DATA_REG 0x0e +#define Z8536_PC_DATA_REG 0x0f + +/* Counter/Timer 1/2/3 Current Count registers */ +#define Z8536_CT1_VAL_MSB_REG 0x10 +#define Z8536_CT1_VAL_LSB_REG 0x11 +#define Z8536_CT2_VAL_MSB_REG 0x12 +#define Z8536_CT2_VAL_LSB_REG 0x13 +#define Z8536_CT3_VAL_MSB_REG 0x14 +#define Z8536_CT3_VAL_LSB_REG 0x15 +#define Z8536_CT_VAL_MSB_REG(x) (0x10 + ((x) * 2)) +#define Z8536_CT_VAL_LSB_REG(x) (0x11 + ((x) * 2)) + +/* Counter/Timer 1/2/3 Time Constant registers */ +#define Z8536_CT1_RELOAD_MSB_REG 0x16 +#define Z8536_CT1_RELOAD_LSB_REG 0x17 +#define Z8536_CT2_RELOAD_MSB_REG 0x18 +#define Z8536_CT2_RELOAD_LSB_REG 0x19 +#define Z8536_CT3_RELOAD_MSB_REG 0x1a +#define Z8536_CT3_RELOAD_LSB_REG 0x1b +#define Z8536_CT_RELOAD_MSB_REG(x) (0x16 + ((x) * 2)) +#define Z8536_CT_RELOAD_LSB_REG(x) (0x17 + ((x) * 2)) + +/* Counter/Timer 1/2/3 Mode Specification registers */ +#define Z8536_CT1_MODE_REG 0x1c +#define Z8536_CT2_MODE_REG 0x1d +#define Z8536_CT3_MODE_REG 0x1e +#define Z8536_CT_MODE_REG(x) (0x1c + (x)) +#define Z8536_CT_MODE_CSC BIT(7) /* Continuous/Single Cycle */ +#define Z8536_CT_MODE_EOE BIT(6) /* External Output Enable */ +#define Z8536_CT_MODE_ECE BIT(5) /* External Count Enable */ +#define Z8536_CT_MODE_ETE BIT(4) /* External Trigger Enable */ +#define Z8536_CT_MODE_EGE BIT(3) /* External Gate Enable */ +#define Z8536_CT_MODE_REB BIT(2) /* Retrigger Enable Bit */ +#define Z8536_CT_MODE_DCS_PULSE (0 << 0)/* Duty Cycle - Pulse */ +#define Z8536_CT_MODE_DCS_ONESHOT (1 << 0)/* Duty Cycle - One-Shot */ +#define Z8536_CT_MODE_DCS_SQRWAVE (2 << 0)/* Duty Cycle - Square Wave */ +#define Z8536_CT_MODE_DCS_DO_NOT_USE (3 << 0)/* Duty Cycle - Do Not Use */ +#define Z8536_CT_MODE_DCS_MASK (3 << 0)/* Duty Cycle mask */ + +/* Port A/B Mode Specification registers */ +#define Z8536_PA_MODE_REG 0x20 +#define Z8536_PB_MODE_REG 0x28 +#define Z8536_PAB_MODE_PTS_BIT (0 << 6)/* Bit Port */ +#define Z8536_PAB_MODE_PTS_INPUT (1 << 6)/* Input Port */ +#define Z8536_PAB_MODE_PTS_OUTPUT (2 << 6)/* Output Port */ +#define Z8536_PAB_MODE_PTS_BIDIR (3 << 6)/* Bidirectional Port */ +#define Z8536_PAB_MODE_PTS_MASK (3 << 6)/* Port Type Select mask */ +#define Z8536_PAB_MODE_ITB BIT(5) /* Interrupt on Two Bytes */ +#define Z8536_PAB_MODE_SB BIT(4) /* Single Buffered mode */ +#define Z8536_PAB_MODE_IMO BIT(3) /* Interrupt on Match Only */ +#define Z8536_PAB_MODE_PMS_DISABLE (0 << 1)/* Disable Pattern Match */ +#define Z8536_PAB_MODE_PMS_AND (1 << 1)/* "AND" mode */ +#define Z8536_PAB_MODE_PMS_OR (2 << 1)/* "OR" mode */ +#define Z8536_PAB_MODE_PMS_OR_PEV (3 << 1)/* "OR-Priority" mode */ +#define Z8536_PAB_MODE_PMS_MASK (3 << 1)/* Pattern Mode mask */ +#define Z8536_PAB_MODE_LPM BIT(0) /* Latch on Pattern Match */ +#define Z8536_PAB_MODE_DTE BIT(0) /* Deskew Timer Enabled */ + +/* Port A/B Handshake Specification registers */ +#define Z8536_PA_HANDSHAKE_REG 0x21 +#define Z8536_PB_HANDSHAKE_REG 0x29 +#define Z8536_PAB_HANDSHAKE_HST_INTER (0 << 6)/* Interlocked Handshake */ +#define Z8536_PAB_HANDSHAKE_HST_STROBED (1 << 6)/* Strobed Handshake */ +#define Z8536_PAB_HANDSHAKE_HST_PULSED (2 << 6)/* Pulsed Handshake */ +#define Z8536_PAB_HANDSHAKE_HST_3WIRE (3 << 6)/* Three-Wire Handshake */ +#define Z8536_PAB_HANDSHAKE_HST_MASK (3 << 6)/* Handshake Type mask */ +#define Z8536_PAB_HANDSHAKE_RWS_DISABLE (0 << 3)/* Req/Wait Disabled */ +#define Z8536_PAB_HANDSHAKE_RWS_OUTWAIT (1 << 3)/* Output Wait */ +#define Z8536_PAB_HANDSHAKE_RWS_INWAIT (3 << 3)/* Input Wait */ +#define Z8536_PAB_HANDSHAKE_RWS_SPREQ (4 << 3)/* Special Request */ +#define Z8536_PAB_HANDSHAKE_RWS_OUTREQ (5 << 4)/* Output Request */ +#define Z8536_PAB_HANDSHAKE_RWS_INREQ (7 << 3)/* Input Request */ +#define Z8536_PAB_HANDSHAKE_RWS_MASK (7 << 3)/* Req/Wait mask */ +#define Z8536_PAB_HANDSHAKE_DESKEW(x) ((x) << 0)/* Deskew Time */ +#define Z8536_PAB_HANDSHAKE_DESKEW_MASK (3 << 0)/* Deskew Time mask */ + +/* + * Port A/B/C Data Path Polarity registers + * + * 0 = Non-Inverting + * 1 = Inverting + */ +#define Z8536_PA_DPP_REG 0x22 +#define Z8536_PB_DPP_REG 0x2a +#define Z8536_PC_DPP_REG 0x05 + +/* + * Port A/B/C Data Direction registers + * + * 0 = Output bit + * 1 = Input bit + */ +#define Z8536_PA_DD_REG 0x23 +#define Z8536_PB_DD_REG 0x2b +#define Z8536_PC_DD_REG 0x06 + +/* + * Port A/B/C Special I/O Control registers + * + * 0 = Normal Input or Output + * 1 = Output with open drain or Input with 1's catcher + */ +#define Z8536_PA_SIO_REG 0x24 +#define Z8536_PB_SIO_REG 0x2c +#define Z8536_PC_SIO_REG 0x07 + +/* + * Port A/B Pattern Polarity/Transition/Mask registers + * + * PM PT PP Pattern Specification + * -- -- -- ------------------------------------- + * 0 0 x Bit masked off + * 0 1 x Any transition + * 1 0 0 Zero (low-level) + * 1 0 1 One (high-level) + * 1 1 0 One-to-zero transition (falling-edge) + * 1 1 1 Zero-to-one transition (rising-edge) + */ +#define Z8536_PA_PP_REG 0x25 +#define Z8536_PB_PP_REG 0x2d + +#define Z8536_PA_PT_REG 0x26 +#define Z8536_PB_PT_REG 0x2e + +#define Z8536_PA_PM_REG 0x27 +#define Z8536_PB_PM_REG 0x2f + +#endif /* _Z8536_H */ -- cgit v0.10.2 From a35ccfe093199671358735ac4c928fc257629d9d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 12:05:58 -0700 Subject: staging: comedi: comedidev.h: remove unused "minor bits" information The enum comedi_minor_bits and the COMEDI_SUBDEVICE_MINOR_{SHIFT,OFFSET} defines are not used. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 77be191..84245fb 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -299,17 +299,6 @@ struct comedi_device { void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); -/* we can expand the number of bits used to encode devices/subdevices into - the minor number soon, after more distros support > 8 bit minor numbers - (like after Debian Etch gets released) */ -enum comedi_minor_bits { - COMEDI_DEVICE_MINOR_MASK = 0xf, - COMEDI_SUBDEVICE_MINOR_MASK = 0xf0 -}; - -static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4; -static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1; - struct comedi_device *comedi_dev_get_from_minor(unsigned minor); int comedi_dev_put(struct comedi_device *dev); -- cgit v0.10.2 From 738e1e1bd7995208e968fe9ad5424856f7f44b65 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 12:05:59 -0700 Subject: staging: comedi: comedidev.h: remove unused "polling" function prototypes These "polling" functions are not implemented in the comedi core. Remove the unnecessary prototypes. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 84245fb..928572f 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -302,11 +302,6 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); struct comedi_device *comedi_dev_get_from_minor(unsigned minor); int comedi_dev_put(struct comedi_device *dev); -void init_polling(void); -void cleanup_polling(void); -void start_polling(struct comedi_device *); -void stop_polling(struct comedi_device *); - /* subdevice runflags */ enum subdevice_runflags { SRF_RT = 0x00000002, -- cgit v0.10.2 From 84bb0bccd26ec3029124a9dd200b985c1cde77bd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 12:06:00 -0700 Subject: staging: comedi: comedidev.h: add namespace to the subdevice "runflags" Tidy up and document the subdevice "runflags". Rename them so they have comedi namespace. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index f143cb6..68bfe92 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -604,7 +604,7 @@ bool comedi_is_subdevice_running(struct comedi_subdevice *s) { unsigned runflags = comedi_get_subdevice_runflags(s); - return (runflags & SRF_RUNNING) ? true : false; + return (runflags & COMEDI_SRF_RUNNING) ? true : false; } EXPORT_SYMBOL_GPL(comedi_is_subdevice_running); @@ -612,14 +612,14 @@ static bool comedi_is_subdevice_in_error(struct comedi_subdevice *s) { unsigned runflags = comedi_get_subdevice_runflags(s); - return (runflags & SRF_ERROR) ? true : false; + return (runflags & COMEDI_SRF_ERROR) ? true : false; } static bool comedi_is_subdevice_idle(struct comedi_subdevice *s) { unsigned runflags = comedi_get_subdevice_runflags(s); - return (runflags & (SRF_ERROR | SRF_RUNNING)) ? false : true; + return (runflags & COMEDI_SRF_BUSY_MASK) ? false : true; } /** @@ -634,7 +634,7 @@ void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size) { s->private = kzalloc(size, GFP_KERNEL); if (s->private) - s->runflags |= SRF_FREE_SPRIV; + s->runflags |= COMEDI_SRF_FREE_SPRIV; return s->private; } EXPORT_SYMBOL_GPL(comedi_alloc_spriv); @@ -647,7 +647,7 @@ static void do_become_nonbusy(struct comedi_device *dev, { struct comedi_async *async = s->async; - comedi_set_subdevice_runflags(s, SRF_RUNNING, 0); + comedi_set_subdevice_runflags(s, COMEDI_SRF_RUNNING, 0); if (async) { comedi_buf_reset(s); async->inttrig = NULL; @@ -1634,10 +1634,13 @@ static int do_cmd_ioctl(struct comedi_device *dev, if (async->cmd.flags & CMDF_WAKE_EOS) async->cb_mask |= COMEDI_CB_EOS; - comedi_set_subdevice_runflags(s, SRF_ERROR | SRF_RUNNING, SRF_RUNNING); + comedi_set_subdevice_runflags(s, COMEDI_SRF_BUSY_MASK, + COMEDI_SRF_RUNNING); - /* set s->busy _after_ setting SRF_RUNNING flag to avoid race with - * comedi_read() or comedi_write() */ + /* + * Set s->busy _after_ setting COMEDI_SRF_RUNNING flag to avoid + * race with comedi_read() or comedi_write(). + */ s->busy = file; ret = s->do_cmd(dev, s); if (ret == 0) @@ -2591,18 +2594,21 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) return; if (s->async->events & COMEDI_CB_CANCEL_MASK) - runflags_mask |= SRF_RUNNING; + runflags_mask |= COMEDI_SRF_RUNNING; /* * Remember if an error event has occurred, so an error * can be returned the next time the user does a read(). */ if (s->async->events & COMEDI_CB_ERROR_MASK) { - runflags_mask |= SRF_ERROR; - runflags |= SRF_ERROR; + runflags_mask |= COMEDI_SRF_ERROR; + runflags |= COMEDI_SRF_ERROR; } if (runflags_mask) { - /*sets SRF_ERROR and SRF_RUNNING together atomically */ + /* + * Sets COMEDI_SRF_ERROR and COMEDI_SRF_RUNNING together + * atomically. + */ comedi_set_subdevice_runflags(s, runflags_mask, runflags); } diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 928572f..e5daaeb 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -302,15 +302,22 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); struct comedi_device *comedi_dev_get_from_minor(unsigned minor); int comedi_dev_put(struct comedi_device *dev); -/* subdevice runflags */ -enum subdevice_runflags { - SRF_RT = 0x00000002, - /* indicates an COMEDI_CB_ERROR event has occurred since the last - * command was started */ - SRF_ERROR = 0x00000004, - SRF_RUNNING = 0x08000000, - SRF_FREE_SPRIV = 0x80000000, /* free s->private on detach */ -}; +/** + * comedi_subdevice "runflags" + * @COMEDI_SRF_RT: DEPRECATED: command is running real-time + * @COMEDI_SRF_ERROR: indicates an COMEDI_CB_ERROR event has occurred + * since the last command was started + * @COMEDI_SRF_RUNNING: command is running + * @COMEDI_SRF_FREE_SPRIV: free s->private on detach + * + * @COMEDI_SRF_BUSY_MASK: runflags that indicate the subdevice is "busy" + */ +#define COMEDI_SRF_RT BIT(1) +#define COMEDI_SRF_ERROR BIT(2) +#define COMEDI_SRF_RUNNING BIT(27) +#define COMEDI_SRF_FREE_SPRIV BIT(31) + +#define COMEDI_SRF_BUSY_MASK (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING) bool comedi_is_subdevice_running(struct comedi_subdevice *s); diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 61802d7..f32e714 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -125,7 +125,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev) if (dev->subdevices) { for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; - if (s->runflags & SRF_FREE_SPRIV) + if (s->runflags & COMEDI_SRF_FREE_SPRIV) kfree(s->private); comedi_free_subdevice_minor(s); if (s->async) { -- cgit v0.10.2 From a3b2ee1d3ef56d0221fc5b246368dc13cf6b8ba4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 12:06:01 -0700 Subject: staging: comedi: das16: use COMEDI_CB_CANCEL_MASK to see if command is running In das16_interrupt(), use COMEDI_CB_CANCEL_MASK to determine if the async command is still running and the dma needs to be re-enabled. This will cause the driver not re-enable the dma if the async buffer overflows (COMEDI_CB_OVERFLOW), a hardware error occurs (COMEDI_CB_ERROR), or the command completes (COMEDI_CB_EOA). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 466d4ef..4608b01 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -523,7 +523,7 @@ static void das16_interrupt(struct comedi_device *dev) devpriv->adc_byte_count -= num_bytes; /* re-enable dma */ - if ((async->events & COMEDI_CB_EOA) == 0) { + if (!(async->events & COMEDI_CB_CANCEL_MASK)) { struct comedi_isadma_desc *nxt_desc = &dma->desc[dma->cur_dma]; nxt_desc->size = nxt_desc->maxsize; -- cgit v0.10.2 From 3e6cb74f5632e1ac2b4209b4d2c64fca43e2838b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 12:06:02 -0700 Subject: staging: comedi: drivers: remove inappropriate COMEDI_CB_EOA events Hardware errors should be reported with the COMEDI_CB_ERROR event. This event will cause the async command to cancel. It's not necessary to also set the COMEDI_CB_EOA event. Remove these events. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 47f6c0e..f68dc99 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -539,7 +539,7 @@ static irqreturn_t pci9111_interrupt(int irq, void *p_device) spin_unlock_irqrestore(&dev->spinlock, irq_flags); dev_dbg(dev->class_dev, "fifo overflow\n"); outb(0, dev->iobase + PCI9111_INT_CLR_REG); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return IRQ_HANDLED; diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 2660358..f61e392 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -749,13 +749,13 @@ static irqreturn_t pci9118_interrupt(int irq, void *d) if (intcsr & MASTER_ABORT_INT) { dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n"); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; goto interrupt_exit; } if (intcsr & TARGET_ABORT_INT) { dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n"); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; goto interrupt_exit; } diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index d02df7d..1b8715b 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -743,14 +743,14 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, status = inw(dev->iobase + PCI171x_STATUS); if (status & Status_FE) { dev_dbg(dev->class_dev, "A/D FIFO empty (%4x)\n", status); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return; } if (status & Status_FF) { dev_dbg(dev->class_dev, "A/D FIFO Full status (Fatal Error!) (%4x)\n", status); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return; } @@ -761,7 +761,7 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, val = inw(dev->iobase + PCI171x_AD_DATA); ret = pci171x_ai_dropout(dev, s, s->async->cur_chan, val); if (ret) { - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; break; } @@ -795,7 +795,7 @@ static int move_block_from_fifo(struct comedi_device *dev, ret = pci171x_ai_dropout(dev, s, s->async->cur_chan, val); if (ret) { - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; return ret; } @@ -816,14 +816,14 @@ static void pci1710_handle_fifo(struct comedi_device *dev, m = inw(dev->iobase + PCI171x_STATUS); if (!(m & Status_FH)) { dev_dbg(dev->class_dev, "A/D FIFO not half full! (%4x)\n", m); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return; } if (m & Status_FF) { dev_dbg(dev->class_dev, "A/D FIFO Full status (Fatal Error!) (%4x)\n", m); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return; } diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 669b170..dd0c65a 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1355,7 +1355,7 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) outw(devpriv->adc_fifo_bits | LADFUL, devpriv->control_status + INT_ADCFIFO); spin_unlock_irqrestore(&dev->spinlock, flags); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; } comedi_handle_events(dev, s); diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 569310a..5b43e4e 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -2804,7 +2804,7 @@ static void handle_ai_interrupt(struct comedi_device *dev, /* check for fifo overrun */ if (status & ADC_OVERRUN_BIT) { dev_err(dev->class_dev, "fifo overrun\n"); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; } /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index 80f41b7..3666a68 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -455,7 +455,7 @@ static void das16m1_handler(struct comedi_device *dev, unsigned int status) /* this probably won't catch overruns since the card doesn't generate * overrun interrupts, but we might as well try */ if (status & OVRUN) { - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; dev_err(dev->class_dev, "fifo overflow\n"); } diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 13ed31c..0790a28 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -611,7 +611,7 @@ static void das1800_ai_handler(struct comedi_device *dev) /* clear OVF interrupt bit */ outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS); dev_err(dev->class_dev, "FIFO overflow\n"); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return; } diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index e5bdc24..ff7f4be 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -511,7 +511,7 @@ static irqreturn_t das800_interrupt(int irq, void *d) if (fifo_overflow) { spin_unlock_irqrestore(&dev->spinlock, irq_flags); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return IRQ_HANDLED; } diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 1d9a7a6..0aa5198 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -355,7 +355,7 @@ static irqreturn_t dt3k_interrupt(int irq, void *d) dt3k_ai_empty_fifo(dev, s); if (status & (DT3000_ADSWERR | DT3000_ADHWERR)) - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; debug_n_ints++; if (debug_n_ints >= 10) diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 0979f53..deada97 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -261,12 +261,12 @@ static irqreturn_t gsc_hpdi_interrupt(int irq, void *d) if (hpdi_board_status & RX_OVERRUN_BIT) { dev_err(dev->class_dev, "rx fifo overrun\n"); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; } if (hpdi_board_status & RX_UNDERRUN_BIT) { dev_err(dev->class_dev, "rx fifo underrun\n"); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; } if (devpriv->dio_count == 0) diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index 915685c..d120aa2 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1068,7 +1068,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) ME4000_AI_CTRL_BIT_SC_IRQ); outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; dev_err(dev->class_dev, "FIFO overflow\n"); } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) @@ -1089,7 +1089,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) ME4000_AI_CTRL_BIT_SC_IRQ); outl(tmp, dev->iobase + ME4000_AI_CTRL_REG); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; dev_err(dev->class_dev, "Undefined FIFO state\n"); } diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 2500148..a1ce0b0 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -175,12 +175,12 @@ static irqreturn_t a2150_interrupt(int irq, void *d) return IRQ_NONE; if (status & OVFL_BIT) { - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); } if ((status & DMA_TC_BIT) == 0) { - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); return IRQ_HANDLED; } diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index eea7f94..8fb5c1f 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -823,7 +823,7 @@ static int labpc_drain_fifo(struct comedi_device *dev) } if (i == timeout) { dev_err(dev->class_dev, "ai timeout, fifo never empties\n"); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; return -1; } @@ -875,7 +875,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d) if (devpriv->stat1 & STAT1_OVERRUN) { /* clear error interrupt */ devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); dev_err(dev->class_dev, "overrun\n"); return IRQ_HANDLED; @@ -895,7 +895,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d) if (devpriv->stat1 & STAT1_OVERFLOW) { /* clear error interrupt */ devpriv->write_byte(dev, 0x1, ADC_FIFO_CLEAR_REG); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); dev_err(dev->class_dev, "overflow\n"); return IRQ_HANDLED; diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 11e7017..b6ddc01 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -1478,7 +1478,7 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, dev_err(dev->class_dev, "unknown mite interrupt (ai_mite_status=%08x)\n", ai_mite_status); - s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; /* disable_irq(dev->irq); */ } #endif @@ -1491,8 +1491,7 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, /* we probably aren't even running a command now, * so it's a good idea to be careful. */ if (comedi_is_subdevice_running(s)) { - s->async->events |= - COMEDI_CB_ERROR | COMEDI_CB_EOA; + s->async->events |= COMEDI_CB_ERROR; comedi_handle_events(dev, s); } return; @@ -1579,7 +1578,7 @@ static void handle_b_interrupt(struct comedi_device *dev, dev_err(dev->class_dev, "unknown mite interrupt (ao_mite_status=%08x)\n", ao_mite_status); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; } #endif diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index db7e8aa..db399fe 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -418,7 +418,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) CHSR_DRQ1 | CHSR_MRDY)) { dev_dbg(dev->class_dev, "unknown mite interrupt, disabling IRQ\n"); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; disable_irq(dev->irq); } } @@ -460,7 +460,7 @@ static irqreturn_t nidio_interrupt(int irq, void *d) break; } else if (flags & Waited) { writeb(ClearWaited, dev->mmio + Group_1_First_Clear); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + async->events |= COMEDI_CB_ERROR; break; } else if (flags & PrimaryTC) { writeb(ClearPrimaryTC, diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index f76601a..37cc5e4 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -797,7 +797,7 @@ static void pcl812_handle_eoc(struct comedi_device *dev, if (pcl812_ai_eoc(dev, s, NULL, 0)) { dev_dbg(dev->class_dev, "A/D cmd IRQ without DRDY!\n"); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; return; } diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index ba2e137..6e5d8bf 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -468,7 +468,7 @@ static bool pcl818_ai_dropout(struct comedi_device *dev, (devpriv->dma) ? "DMA" : (devpriv->usefifo) ? "FIFO" : "IRQ", chan, expected_chan); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; return true; } return false; @@ -501,7 +501,7 @@ static void pcl818_handle_eoc(struct comedi_device *dev, if (pcl818_ai_eoc(dev, s, NULL, 0)) { dev_err(dev->class_dev, "A/D mode1/3 IRQ without DRDY!\n"); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; return; } @@ -558,14 +558,14 @@ static void pcl818_handle_fifo(struct comedi_device *dev, if (status & 4) { dev_err(dev->class_dev, "A/D mode1/3 FIFO overflow!\n"); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; return; } if (status & 1) { dev_err(dev->class_dev, "A/D mode1/3 FIFO interrupt without data!\n"); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; return; } diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 9609811..dd06734 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -210,8 +210,7 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id) unsigned short data; if (status & DAQP_STATUS_DATA_LOST) { - s->async->events |= - COMEDI_CB_EOA | COMEDI_CB_OVERFLOW; + s->async->events |= COMEDI_CB_OVERFLOW; dev_warn(dev->class_dev, "data lost\n"); break; } @@ -239,7 +238,7 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id) if (loop_limit <= 0) { dev_warn(dev->class_dev, "loop_limit reached in daqp_interrupt()\n"); - s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + s->async->events |= COMEDI_CB_ERROR; } comedi_handle_events(dev, s); -- cgit v0.10.2 From d615416de6157812e6d7b732991ece884fc6c59e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 12:06:03 -0700 Subject: staging: comedi: pcl818: introduce pcl818_ai_write_sample() This driver can acquire analog input samples during the async command with DMA, by using the FIFO, or sample-by-sample using the End-Of-Conversion interrupt. All three methods do the following sequence: 1) check for channel dropout 2) add the sample to the async buffer 3) advance the channel dropout detection and detect the end of the command Merge this sequence into a new helper function. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 6e5d8bf..a10ce41 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -454,11 +454,12 @@ static int pcl818_ai_eoc(struct comedi_device *dev, return -EBUSY; } -static bool pcl818_ai_dropout(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int chan) +static bool pcl818_ai_write_sample(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int chan, unsigned int val) { struct pcl818_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; unsigned int expected_chan; expected_chan = devpriv->act_chanlist[devpriv->act_chanlist_pos]; @@ -469,16 +470,10 @@ static bool pcl818_ai_dropout(struct comedi_device *dev, (devpriv->usefifo) ? "FIFO" : "IRQ", chan, expected_chan); s->async->events |= COMEDI_CB_ERROR; - return true; + return false; } - return false; -} -static bool pcl818_ai_next_chan(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pcl818_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; + comedi_buf_write_samples(s, &val, 1); devpriv->act_chanlist_pos++; if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) @@ -506,13 +501,7 @@ static void pcl818_handle_eoc(struct comedi_device *dev, } val = pcl818_ai_get_sample(dev, s, &chan); - - if (pcl818_ai_dropout(dev, s, chan)) - return; - - comedi_buf_write_samples(s, &val, 1); - - pcl818_ai_next_chan(dev, s); + pcl818_ai_write_sample(dev, s, chan, val); } static void pcl818_handle_dma(struct comedi_device *dev, @@ -535,13 +524,7 @@ static void pcl818_handle_dma(struct comedi_device *dev, val = ptr[i]; chan = val & 0xf; val = (val >> 4) & s->maxdata; - - if (pcl818_ai_dropout(dev, s, chan)) - break; - - comedi_buf_write_samples(s, &val, 1); - - if (!pcl818_ai_next_chan(dev, s)) + if (!pcl818_ai_write_sample(dev, s, chan, val)) break; } } @@ -576,13 +559,7 @@ static void pcl818_handle_fifo(struct comedi_device *dev, for (i = 0; i < len; i++) { val = pcl818_ai_get_fifo_sample(dev, s, &chan); - - if (pcl818_ai_dropout(dev, s, chan)) - break; - - comedi_buf_write_samples(s, &val, 1); - - if (!pcl818_ai_next_chan(dev, s)) + if (!pcl818_ai_write_sample(dev, s, chan, val)) break; } } -- cgit v0.10.2 From c5b6b54488d0cd054ab28f86565aeef537d7ee65 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:52:59 -0700 Subject: staging: comedi: adv_pci1710: change boardinfo 'n_counter' to 'has_counter' The 'n_counter' member of the boardinfo is actually a flag indicating that the board exposes a single channel counter subdevice. For aesthetics, change the 'n_counter' member to a bit-field flag 'has_counter' and refactor the board attach accordingly. Remove the unnecessary initialization of the subdevice 'len_chanlist'. That member is only used by subdevices that support async commands. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 1b8715b..9f88cfb 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -198,7 +198,6 @@ struct boardtype { int n_aochan; /* num of D/A chans */ int n_dichan; /* num of DI chans */ int n_dochan; /* num of DO chans */ - int n_counter; /* num of counters */ int ai_maxdata; /* resolution of A/D */ int ao_maxdata; /* resolution of D/A */ const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ @@ -206,6 +205,7 @@ struct boardtype { const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ unsigned int ai_ns_min; /* max sample speed of card v ns */ unsigned int fifo_half_size; /* size of FIFO/2 */ + unsigned int has_counter:1; }; static const struct boardtype boardtypes[] = { @@ -218,7 +218,6 @@ static const struct boardtype boardtypes[] = { .n_aochan = 2, .n_dichan = 16, .n_dochan = 16, - .n_counter = 1, .ai_maxdata = 0x0fff, .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci1710_3, @@ -226,6 +225,7 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 2048, + .has_counter = 1, }, [BOARD_PCI1710HG] = { .name = "pci1710hg", @@ -236,7 +236,6 @@ static const struct boardtype boardtypes[] = { .n_aochan = 2, .n_dichan = 16, .n_dochan = 16, - .n_counter = 1, .ai_maxdata = 0x0fff, .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci1710hg, @@ -244,6 +243,7 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 2048, + .has_counter = 1, }, [BOARD_PCI1711] = { .name = "pci1711", @@ -253,7 +253,6 @@ static const struct boardtype boardtypes[] = { .n_aochan = 2, .n_dichan = 16, .n_dochan = 16, - .n_counter = 1, .ai_maxdata = 0x0fff, .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci17x1, @@ -261,6 +260,7 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 512, + .has_counter = 1, }, [BOARD_PCI1713] = { .name = "pci1713", @@ -1122,7 +1122,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, n_subdevices++; if (this_board->n_dochan) n_subdevices++; - if (this_board->n_counter) + if (this_board->has_counter) n_subdevices++; ret = comedi_alloc_subdevices(dev, n_subdevices); @@ -1205,12 +1205,11 @@ static int pci1710_auto_attach(struct comedi_device *dev, subdev++; } - if (this_board->n_counter) { + if (this_board->has_counter) { s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = this_board->n_counter; - s->len_chanlist = this_board->n_counter; + s->n_chan = 1; s->maxdata = 0xffff; s->range_table = &range_unknown; s->insn_read = pci171x_insn_counter_read; -- cgit v0.10.2 From 068de2b65b9d14777c7d30853a332ccead664b94 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:00 -0700 Subject: staging: comedi: adv_pci1710: simplify digital input and output boardinfo The boards that have digital inputs and outputs always have 16 input channels and 16 output channels. Replace the 'n_dichan' and 'n_dochan' members of the boardinfo with the fit-field flag 'has_di_do' and refactor the board attach accordingly. Remove the unnecessary initialization of the subdevice 'len_chanlist'. That member is only used by subdevices that support async commands. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 9f88cfb..667900f 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -196,8 +196,6 @@ struct boardtype { int n_aichan; /* num of A/D chans */ int n_aichand; /* num of A/D chans in diff mode */ int n_aochan; /* num of D/A chans */ - int n_dichan; /* num of DI chans */ - int n_dochan; /* num of DO chans */ int ai_maxdata; /* resolution of A/D */ int ao_maxdata; /* resolution of D/A */ const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ @@ -205,6 +203,7 @@ struct boardtype { const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ unsigned int ai_ns_min; /* max sample speed of card v ns */ unsigned int fifo_half_size; /* size of FIFO/2 */ + unsigned int has_di_do:1; unsigned int has_counter:1; }; @@ -216,8 +215,6 @@ static const struct boardtype boardtypes[] = { .n_aichan = 16, .n_aichand = 8, .n_aochan = 2, - .n_dichan = 16, - .n_dochan = 16, .ai_maxdata = 0x0fff, .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci1710_3, @@ -225,6 +222,7 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 2048, + .has_di_do = 1, .has_counter = 1, }, [BOARD_PCI1710HG] = { @@ -234,8 +232,6 @@ static const struct boardtype boardtypes[] = { .n_aichan = 16, .n_aichand = 8, .n_aochan = 2, - .n_dichan = 16, - .n_dochan = 16, .ai_maxdata = 0x0fff, .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci1710hg, @@ -243,6 +239,7 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 2048, + .has_di_do = 1, .has_counter = 1, }, [BOARD_PCI1711] = { @@ -251,8 +248,6 @@ static const struct boardtype boardtypes[] = { .cardtype = TYPE_PCI171X, .n_aichan = 16, .n_aochan = 2, - .n_dichan = 16, - .n_dochan = 16, .ai_maxdata = 0x0fff, .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci17x1, @@ -260,6 +255,7 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 512, + .has_di_do = 1, .has_counter = 1, }, [BOARD_PCI1713] = { @@ -286,13 +282,12 @@ static const struct boardtype boardtypes[] = { .have_irq = 1, .cardtype = TYPE_PCI171X, .n_aichan = 16, - .n_dichan = 16, - .n_dochan = 16, .ai_maxdata = 0x0fff, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, .ai_ns_min = 10000, .fifo_half_size = 512, + .has_di_do = 1, }, }; @@ -1118,10 +1113,8 @@ static int pci1710_auto_attach(struct comedi_device *dev, n_subdevices++; if (this_board->n_aochan) n_subdevices++; - if (this_board->n_dichan) - n_subdevices++; - if (this_board->n_dochan) - n_subdevices++; + if (this_board->has_di_do) + n_subdevices += 2; if (this_board->has_counter) n_subdevices++; @@ -1181,25 +1174,21 @@ static int pci1710_auto_attach(struct comedi_device *dev, subdev++; } - if (this_board->n_dichan) { + if (this_board->has_di_do) { s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; - s->n_chan = this_board->n_dichan; + s->n_chan = 16; s->maxdata = 1; - s->len_chanlist = this_board->n_dichan; s->range_table = &range_digital; s->insn_bits = pci171x_insn_bits_di; subdev++; - } - if (this_board->n_dochan) { s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = this_board->n_dochan; + s->n_chan = 16; s->maxdata = 1; - s->len_chanlist = this_board->n_dochan; s->range_table = &range_digital; s->insn_bits = pci171x_insn_bits_do; subdev++; -- cgit v0.10.2 From 0b25aa79ccb6bf46143410483b58f8ebab7ffa55 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:01 -0700 Subject: staging: comedi: adv_pci1710: rename boardinfo 'have_irq' For aesthetics, rename this member of the boardinfo to 'has_irq' and change it to a bit-field flag. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 667900f..9f415fe 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -191,7 +191,6 @@ enum pci1710_boardid { struct boardtype { const char *name; /* board name */ - char have_irq; /* 1=card support IRQ */ char cardtype; /* 0=1710& co. 2=1713, ... */ int n_aichan; /* num of A/D chans */ int n_aichand; /* num of A/D chans in diff mode */ @@ -203,6 +202,7 @@ struct boardtype { const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ unsigned int ai_ns_min; /* max sample speed of card v ns */ unsigned int fifo_half_size; /* size of FIFO/2 */ + unsigned int has_irq:1; unsigned int has_di_do:1; unsigned int has_counter:1; }; @@ -210,7 +210,6 @@ struct boardtype { static const struct boardtype boardtypes[] = { [BOARD_PCI1710] = { .name = "pci1710", - .have_irq = 1, .cardtype = TYPE_PCI171X, .n_aichan = 16, .n_aichand = 8, @@ -222,12 +221,12 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 2048, + .has_irq = 1, .has_di_do = 1, .has_counter = 1, }, [BOARD_PCI1710HG] = { .name = "pci1710hg", - .have_irq = 1, .cardtype = TYPE_PCI171X, .n_aichan = 16, .n_aichand = 8, @@ -239,12 +238,12 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 2048, + .has_irq = 1, .has_di_do = 1, .has_counter = 1, }, [BOARD_PCI1711] = { .name = "pci1711", - .have_irq = 1, .cardtype = TYPE_PCI171X, .n_aichan = 16, .n_aochan = 2, @@ -255,12 +254,12 @@ static const struct boardtype boardtypes[] = { .rangelist_ao = &range_pci171x_da, .ai_ns_min = 10000, .fifo_half_size = 512, + .has_irq = 1, .has_di_do = 1, .has_counter = 1, }, [BOARD_PCI1713] = { .name = "pci1713", - .have_irq = 1, .cardtype = TYPE_PCI1713, .n_aichan = 32, .n_aichand = 16, @@ -269,6 +268,7 @@ static const struct boardtype boardtypes[] = { .rangecode_ai = range_codes_pci1710_3, .ai_ns_min = 10000, .fifo_half_size = 2048, + .has_irq = 1, }, [BOARD_PCI1720] = { .name = "pci1720", @@ -279,7 +279,6 @@ static const struct boardtype boardtypes[] = { }, [BOARD_PCI1731] = { .name = "pci1731", - .have_irq = 1, .cardtype = TYPE_PCI171X, .n_aichan = 16, .ai_maxdata = 0x0fff, @@ -287,6 +286,7 @@ static const struct boardtype boardtypes[] = { .rangecode_ai = range_codes_pci17x1, .ai_ns_min = 10000, .fifo_half_size = 512, + .has_irq = 1, .has_di_do = 1, }, }; @@ -1124,7 +1124,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, pci1710_reset(dev); - if (this_board->have_irq && pcidev->irq) { + if (this_board->has_irq && pcidev->irq) { ret = request_irq(pcidev->irq, interrupt_service_pci1710, IRQF_SHARED, dev->board_name, dev); if (ret == 0) -- cgit v0.10.2 From 853bbcc26368319cf0abafca88342a17b237c41c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:02 -0700 Subject: staging: comedi: adv_pci1710: remove boardinfo 'ai_maxdata' The analog input resolution is always 12-bits in this driver. Remove the unnecessary boardinfo. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 9f415fe..fb5ad60 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -195,7 +195,6 @@ struct boardtype { int n_aichan; /* num of A/D chans */ int n_aichand; /* num of A/D chans in diff mode */ int n_aochan; /* num of D/A chans */ - int ai_maxdata; /* resolution of A/D */ int ao_maxdata; /* resolution of D/A */ const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ const char *rangecode_ai; /* range codes for programming */ @@ -214,7 +213,6 @@ static const struct boardtype boardtypes[] = { .n_aichan = 16, .n_aichand = 8, .n_aochan = 2, - .ai_maxdata = 0x0fff, .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, @@ -231,7 +229,6 @@ static const struct boardtype boardtypes[] = { .n_aichan = 16, .n_aichand = 8, .n_aochan = 2, - .ai_maxdata = 0x0fff, .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci1710hg, .rangecode_ai = range_codes_pci1710hg, @@ -247,7 +244,6 @@ static const struct boardtype boardtypes[] = { .cardtype = TYPE_PCI171X, .n_aichan = 16, .n_aochan = 2, - .ai_maxdata = 0x0fff, .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, @@ -263,7 +259,6 @@ static const struct boardtype boardtypes[] = { .cardtype = TYPE_PCI1713, .n_aichan = 32, .n_aichand = 16, - .ai_maxdata = 0x0fff, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, .ai_ns_min = 10000, @@ -281,7 +276,6 @@ static const struct boardtype boardtypes[] = { .name = "pci1731", .cardtype = TYPE_PCI171X, .n_aichan = 16, - .ai_maxdata = 0x0fff, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, .ai_ns_min = 10000, @@ -1140,7 +1134,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, if (this_board->n_aichand) s->subdev_flags |= SDF_DIFF; s->n_chan = this_board->n_aichan; - s->maxdata = this_board->ai_maxdata; + s->maxdata = 0x0fff; s->range_table = this_board->rangelist_ai; s->insn_read = pci171x_insn_read_ai; if (dev->irq) { -- cgit v0.10.2 From af9408e5dfbe8014bef343e745551c17e3a7daa9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:03 -0700 Subject: staging: comedi: adv_pci1710: remove boardinfo 'ao_maxdata' The analog output resolution is always 12-bits in this driver. Remove the unnecessary boardinfo. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index fb5ad60..395a2dd 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -195,7 +195,6 @@ struct boardtype { int n_aichan; /* num of A/D chans */ int n_aichand; /* num of A/D chans in diff mode */ int n_aochan; /* num of D/A chans */ - int ao_maxdata; /* resolution of D/A */ const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ const char *rangecode_ai; /* range codes for programming */ const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ @@ -213,7 +212,6 @@ static const struct boardtype boardtypes[] = { .n_aichan = 16, .n_aichand = 8, .n_aochan = 2, - .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, .rangelist_ao = &range_pci171x_da, @@ -229,7 +227,6 @@ static const struct boardtype boardtypes[] = { .n_aichan = 16, .n_aichand = 8, .n_aochan = 2, - .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci1710hg, .rangecode_ai = range_codes_pci1710hg, .rangelist_ao = &range_pci171x_da, @@ -244,7 +241,6 @@ static const struct boardtype boardtypes[] = { .cardtype = TYPE_PCI171X, .n_aichan = 16, .n_aochan = 2, - .ao_maxdata = 0x0fff, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, .rangelist_ao = &range_pci171x_da, @@ -269,7 +265,6 @@ static const struct boardtype boardtypes[] = { .name = "pci1720", .cardtype = TYPE_PCI1720, .n_aochan = 4, - .ao_maxdata = 0x0fff, .rangelist_ao = &range_pci1720, }, [BOARD_PCI1731] = { @@ -1153,7 +1148,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->n_chan = this_board->n_aochan; - s->maxdata = this_board->ao_maxdata; + s->maxdata = 0x0fff; s->len_chanlist = this_board->n_aochan; s->range_table = this_board->rangelist_ao; switch (this_board->cardtype) { -- cgit v0.10.2 From 177a07296478c025259b97afd28b3ffe56268aea Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:04 -0700 Subject: staging: comedi: adv_pci1710: change boardinfo 'n_aichand' to 'has_diff_ai' The 'n_aichand' member of the boardinfo is actually a flag indicating that the board supports differential analog inputs. The number of channels is always half the single-ended number of channels. For aesthetics, change the 'n_aichand' member to a bit-field flag 'has_diff_ai'. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 395a2dd..0664359 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -193,7 +193,6 @@ struct boardtype { const char *name; /* board name */ char cardtype; /* 0=1710& co. 2=1713, ... */ int n_aichan; /* num of A/D chans */ - int n_aichand; /* num of A/D chans in diff mode */ int n_aochan; /* num of D/A chans */ const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ const char *rangecode_ai; /* range codes for programming */ @@ -201,6 +200,7 @@ struct boardtype { unsigned int ai_ns_min; /* max sample speed of card v ns */ unsigned int fifo_half_size; /* size of FIFO/2 */ unsigned int has_irq:1; + unsigned int has_diff_ai:1; unsigned int has_di_do:1; unsigned int has_counter:1; }; @@ -210,7 +210,6 @@ static const struct boardtype boardtypes[] = { .name = "pci1710", .cardtype = TYPE_PCI171X, .n_aichan = 16, - .n_aichand = 8, .n_aochan = 2, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, @@ -218,6 +217,7 @@ static const struct boardtype boardtypes[] = { .ai_ns_min = 10000, .fifo_half_size = 2048, .has_irq = 1, + .has_diff_ai = 1, .has_di_do = 1, .has_counter = 1, }, @@ -225,7 +225,6 @@ static const struct boardtype boardtypes[] = { .name = "pci1710hg", .cardtype = TYPE_PCI171X, .n_aichan = 16, - .n_aichand = 8, .n_aochan = 2, .rangelist_ai = &range_pci1710hg, .rangecode_ai = range_codes_pci1710hg, @@ -233,6 +232,7 @@ static const struct boardtype boardtypes[] = { .ai_ns_min = 10000, .fifo_half_size = 2048, .has_irq = 1, + .has_diff_ai = 1, .has_di_do = 1, .has_counter = 1, }, @@ -254,12 +254,12 @@ static const struct boardtype boardtypes[] = { .name = "pci1713", .cardtype = TYPE_PCI1713, .n_aichan = 32, - .n_aichand = 16, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, .ai_ns_min = 10000, .fifo_half_size = 2048, .has_irq = 1, + .has_diff_ai = 1, }, [BOARD_PCI1720] = { .name = "pci1720", @@ -1126,7 +1126,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; - if (this_board->n_aichand) + if (this_board->has_diff_ai) s->subdev_flags |= SDF_DIFF; s->n_chan = this_board->n_aichan; s->maxdata = 0x0fff; -- cgit v0.10.2 From abd2839c596cd598a52f716a9e409d000a40235b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:05 -0700 Subject: staging: comedi: adv_pci1710: remove boardinfo 'ai_ns_min' The minimum analog input conversion time is 10000 ns for all board types. Remove this unnecessary boardinfo. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 0664359..634b2a0 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -197,7 +197,6 @@ struct boardtype { const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ const char *rangecode_ai; /* range codes for programming */ const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ - unsigned int ai_ns_min; /* max sample speed of card v ns */ unsigned int fifo_half_size; /* size of FIFO/2 */ unsigned int has_irq:1; unsigned int has_diff_ai:1; @@ -214,7 +213,6 @@ static const struct boardtype boardtypes[] = { .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, .rangelist_ao = &range_pci171x_da, - .ai_ns_min = 10000, .fifo_half_size = 2048, .has_irq = 1, .has_diff_ai = 1, @@ -229,7 +227,6 @@ static const struct boardtype boardtypes[] = { .rangelist_ai = &range_pci1710hg, .rangecode_ai = range_codes_pci1710hg, .rangelist_ao = &range_pci171x_da, - .ai_ns_min = 10000, .fifo_half_size = 2048, .has_irq = 1, .has_diff_ai = 1, @@ -244,7 +241,6 @@ static const struct boardtype boardtypes[] = { .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, .rangelist_ao = &range_pci171x_da, - .ai_ns_min = 10000, .fifo_half_size = 512, .has_irq = 1, .has_di_do = 1, @@ -256,7 +252,6 @@ static const struct boardtype boardtypes[] = { .n_aichan = 32, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, - .ai_ns_min = 10000, .fifo_half_size = 2048, .has_irq = 1, .has_diff_ai = 1, @@ -273,7 +268,6 @@ static const struct boardtype boardtypes[] = { .n_aichan = 16, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, - .ai_ns_min = 10000, .fifo_half_size = 512, .has_irq = 1, .has_di_do = 1, @@ -928,7 +922,6 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct boardtype *this_board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; int err = 0; unsigned int arg; @@ -961,8 +954,7 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); if (cmd->convert_src == TRIG_TIMER) - err |= cfc_check_trigger_arg_min(&cmd->convert_arg, - this_board->ai_ns_min); + err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 10000); else /* TRIG_FOLLOW */ err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); -- cgit v0.10.2 From 7bd428c43437ddd401af6b3214051f89628ac12f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:06 -0700 Subject: staging: comedi: adv_pci1710: change boardinfo 'fifo_half_size' to 'has_large_fifo' The boards supported by this driver have a 4K or 1K FIFO that is used when reading analog input samples when running an async command. The maximum number of samples in the FIFO is half the FIFO size due to the 2 bytes/sample (12-bit resolution). For aesthetics, change the 'fifo_half_size' member to a bit-field flag 'has_large_fifo' and add a new member to the private data to hold the 'max_samples' available in the FIFO. Refactor the board attach and pci1710_handle_fifo() accordingly. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 634b2a0..14aaa1e 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -197,8 +197,8 @@ struct boardtype { const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ const char *rangecode_ai; /* range codes for programming */ const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ - unsigned int fifo_half_size; /* size of FIFO/2 */ unsigned int has_irq:1; + unsigned int has_large_fifo:1; /* 4K or 1K FIFO */ unsigned int has_diff_ai:1; unsigned int has_di_do:1; unsigned int has_counter:1; @@ -213,8 +213,8 @@ static const struct boardtype boardtypes[] = { .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, .rangelist_ao = &range_pci171x_da, - .fifo_half_size = 2048, .has_irq = 1, + .has_large_fifo = 1, .has_diff_ai = 1, .has_di_do = 1, .has_counter = 1, @@ -227,8 +227,8 @@ static const struct boardtype boardtypes[] = { .rangelist_ai = &range_pci1710hg, .rangecode_ai = range_codes_pci1710hg, .rangelist_ao = &range_pci171x_da, - .fifo_half_size = 2048, .has_irq = 1, + .has_large_fifo = 1, .has_diff_ai = 1, .has_di_do = 1, .has_counter = 1, @@ -241,7 +241,6 @@ static const struct boardtype boardtypes[] = { .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, .rangelist_ao = &range_pci171x_da, - .fifo_half_size = 512, .has_irq = 1, .has_di_do = 1, .has_counter = 1, @@ -252,8 +251,8 @@ static const struct boardtype boardtypes[] = { .n_aichan = 32, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, - .fifo_half_size = 2048, .has_irq = 1, + .has_large_fifo = 1, .has_diff_ai = 1, }, [BOARD_PCI1720] = { @@ -268,13 +267,13 @@ static const struct boardtype boardtypes[] = { .n_aichan = 16, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, - .fifo_half_size = 512, .has_irq = 1, .has_di_do = 1, }, }; struct pci1710_private { + unsigned int max_samples; unsigned int CntrlReg; /* Control register */ unsigned char ai_et; unsigned int ai_et_CntrlReg; @@ -786,7 +785,7 @@ static int move_block_from_fifo(struct comedi_device *dev, static void pci1710_handle_fifo(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct boardtype *this_board = dev->board_ptr; + struct pci1710_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned int nsamples; unsigned int m; @@ -806,7 +805,7 @@ static void pci1710_handle_fifo(struct comedi_device *dev, return; } - nsamples = this_board->fifo_half_size; + nsamples = devpriv->max_samples; if (comedi_samples_to_bytes(s, nsamples) >= s->async->prealloc_bufsz) { m = comedi_bytes_to_samples(s, s->async->prealloc_bufsz); if (move_block_from_fifo(dev, s, m, 0)) @@ -1188,6 +1187,9 @@ static int pci1710_auto_attach(struct comedi_device *dev, subdev++; } + /* max_samples is half the FIFO size (2 bytes/sample) */ + devpriv->max_samples = (this_board->has_large_fifo) ? 2048 : 512; + return 0; } -- cgit v0.10.2 From 87abf660912c75c08a8eeb501a4770b9e9126750 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:07 -0700 Subject: staging: comedi: adv_pci1710: change boardinfo 'n_aochan' to 'has_ao' Some of the boards supported by this driver have analog outputs. The pci1720 board has 4 analog output channels and the others have 2. For aesthetics, change the 'n_aochan' member to a bit-field flag 'has_ao' and refactor the board attach accordingly. Remove the unnecessary initialization of the subdevice 'len_chanlist'. That member is only used by subdevices that support async commands. Also, remove the unnecessary 'number of channels' check in pci171x_reset(). The boards that used this function, and have analog outputs, always have 2 channels. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 14aaa1e..ced13e9 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -193,13 +193,13 @@ struct boardtype { const char *name; /* board name */ char cardtype; /* 0=1710& co. 2=1713, ... */ int n_aichan; /* num of A/D chans */ - int n_aochan; /* num of D/A chans */ const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ const char *rangecode_ai; /* range codes for programming */ const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ unsigned int has_irq:1; unsigned int has_large_fifo:1; /* 4K or 1K FIFO */ unsigned int has_diff_ai:1; + unsigned int has_ao:1; unsigned int has_di_do:1; unsigned int has_counter:1; }; @@ -209,13 +209,13 @@ static const struct boardtype boardtypes[] = { .name = "pci1710", .cardtype = TYPE_PCI171X, .n_aichan = 16, - .n_aochan = 2, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, .rangelist_ao = &range_pci171x_da, .has_irq = 1, .has_large_fifo = 1, .has_diff_ai = 1, + .has_ao = 1, .has_di_do = 1, .has_counter = 1, }, @@ -223,13 +223,13 @@ static const struct boardtype boardtypes[] = { .name = "pci1710hg", .cardtype = TYPE_PCI171X, .n_aichan = 16, - .n_aochan = 2, .rangelist_ai = &range_pci1710hg, .rangecode_ai = range_codes_pci1710hg, .rangelist_ao = &range_pci171x_da, .has_irq = 1, .has_large_fifo = 1, .has_diff_ai = 1, + .has_ao = 1, .has_di_do = 1, .has_counter = 1, }, @@ -237,11 +237,11 @@ static const struct boardtype boardtypes[] = { .name = "pci1711", .cardtype = TYPE_PCI171X, .n_aichan = 16, - .n_aochan = 2, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, .rangelist_ao = &range_pci171x_da, .has_irq = 1, + .has_ao = 1, .has_di_do = 1, .has_counter = 1, }, @@ -258,8 +258,8 @@ static const struct boardtype boardtypes[] = { [BOARD_PCI1720] = { .name = "pci1720", .cardtype = TYPE_PCI1720, - .n_aochan = 4, .rangelist_ao = &range_pci1720, + .has_ao = 1, }, [BOARD_PCI1731] = { .name = "pci1731", @@ -1008,15 +1008,13 @@ static int pci171x_reset(struct comedi_device *dev) outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */ pci171x_start_pacer(dev, false); devpriv->da_ranges = 0; - if (this_board->n_aochan) { + if (this_board->has_ao) { /* set DACs to 0..5V */ outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); outw(0, dev->iobase + PCI171x_DA1); /* set DA outputs to 0V */ devpriv->ao_data[0] = 0x0000; - if (this_board->n_aochan > 1) { - outw(0, dev->iobase + PCI171x_DA2); - devpriv->ao_data[1] = 0x0000; - } + outw(0, dev->iobase + PCI171x_DA2); + devpriv->ao_data[1] = 0x0000; } outw(0, dev->iobase + PCI171x_DO); /* digital outputs to 0 */ outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */ @@ -1091,7 +1089,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, n_subdevices = 0; if (this_board->n_aichan) n_subdevices++; - if (this_board->n_aochan) + if (this_board->has_ao) n_subdevices++; if (this_board->has_di_do) n_subdevices += 2; @@ -1134,19 +1132,19 @@ static int pci1710_auto_attach(struct comedi_device *dev, subdev++; } - if (this_board->n_aochan) { + if (this_board->has_ao) { s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = this_board->n_aochan; s->maxdata = 0x0fff; - s->len_chanlist = this_board->n_aochan; s->range_table = this_board->rangelist_ao; switch (this_board->cardtype) { case TYPE_PCI1720: + s->n_chan = 4; s->insn_write = pci1720_insn_write_ao; break; default: + s->n_chan = 2; s->insn_write = pci171x_insn_write_ao; break; } -- cgit v0.10.2 From e4623cee9ebaa114c367160728cd1d7f9d2c615d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:08 -0700 Subject: staging: comedi: adv_pci1710: use comedi_subdevice 'readback' Use the new comedi_subdevice 'readback' member and the core provided (*insn_read) for the readback of the analog output subdevice channels. The board is "reset" prior to the subdevice init. Part of this reset sets all the analog output channels to 0V. Move the initialization of the 'readback' values after the 'readback' member has been allocated. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index ced13e9..ab11819 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -285,7 +285,6 @@ struct pci1710_private { unsigned int act_chanlist[32]; /* list of scanned channel */ unsigned char saved_seglen; /* len of the non-repeating chanlist */ unsigned char da_ranges; /* copy of D/A outpit range register */ - unsigned short ao_data[4]; /* data output buffer */ unsigned int cnt0_write_wait; /* after a write, wait for update of the * internal state */ }; @@ -491,14 +490,14 @@ static int pci171x_insn_write_ao(struct comedi_device *dev, outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); ofs = PCI171x_DA1; } - val = devpriv->ao_data[chan]; + val = s->readback[chan]; for (n = 0; n < insn->n; n++) { val = data[n]; outw(val, dev->iobase + ofs); } - devpriv->ao_data[chan] = val; + s->readback[chan] = val; return n; @@ -507,23 +506,6 @@ static int pci171x_insn_write_ao(struct comedi_device *dev, /* ============================================================================== */ -static int pci171x_insn_read_ao(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct pci1710_private *devpriv = dev->private; - int n, chan; - - chan = CR_CHAN(insn->chanspec); - for (n = 0; n < insn->n; n++) - data[n] = devpriv->ao_data[chan]; - - return n; -} - -/* -============================================================================== -*/ static int pci171x_insn_bits_di(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -672,7 +654,7 @@ static int pci1720_insn_write_ao(struct comedi_device *dev, outb(rangereg, dev->iobase + PCI1720_RANGE); devpriv->da_ranges = rangereg; } - val = devpriv->ao_data[chan]; + val = s->readback[chan]; for (n = 0; n < insn->n; n++) { val = data[n]; @@ -680,7 +662,7 @@ static int pci1720_insn_write_ao(struct comedi_device *dev, outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ } - devpriv->ao_data[chan] = val; + s->readback[chan] = val; return n; } @@ -1012,9 +994,7 @@ static int pci171x_reset(struct comedi_device *dev) /* set DACs to 0..5V */ outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); outw(0, dev->iobase + PCI171x_DA1); /* set DA outputs to 0V */ - devpriv->ao_data[0] = 0x0000; outw(0, dev->iobase + PCI171x_DA2); - devpriv->ao_data[1] = 0x0000; } outw(0, dev->iobase + PCI171x_DO); /* digital outputs to 0 */ outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */ @@ -1039,10 +1019,7 @@ static int pci1720_reset(struct comedi_device *dev) outw(0x0800, dev->iobase + PCI1720_DA2); outw(0x0800, dev->iobase + PCI1720_DA3); outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ - devpriv->ao_data[0] = 0x0800; - devpriv->ao_data[1] = 0x0800; - devpriv->ao_data[2] = 0x0800; - devpriv->ao_data[3] = 0x0800; + return 0; } @@ -1148,7 +1125,19 @@ static int pci1710_auto_attach(struct comedi_device *dev, s->insn_write = pci171x_insn_write_ao; break; } - s->insn_read = pci171x_insn_read_ao; + + ret = comedi_alloc_subdev_readback(s); + if (ret) + return ret; + + /* initialize the readback values to match the board reset */ + if (this_board->cardtype == TYPE_PCI1720) { + int i; + + for (i = 0; i < s->n_chan; i++) + s->readback[i] = 0x0800; + } + subdev++; } -- cgit v0.10.2 From 3e5cf6d4ed29dfcb2159620e55bade62b9f36230 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:09 -0700 Subject: staging: comedi: adv_pci1710: tidy up pci1720_insn_write_ao() For aesthetics, rename this function and tidy it up. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index ab11819..dca1bf2 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -636,35 +636,34 @@ static int pci171x_insn_counter_config(struct comedi_device *dev, return 1; } -/* -============================================================================== -*/ -static int pci1720_insn_write_ao(struct comedi_device *dev, +static int pci1720_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct pci1710_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); unsigned int val; - int n, rangereg, chan; + int i; - chan = CR_CHAN(insn->chanspec); - rangereg = devpriv->da_ranges & (~(0x03 << (chan << 1))); - rangereg |= (CR_RANGE(insn->chanspec) << (chan << 1)); - if (rangereg != devpriv->da_ranges) { - outb(rangereg, dev->iobase + PCI1720_RANGE); - devpriv->da_ranges = rangereg; + val = devpriv->da_ranges & (~(0x03 << (chan << 1))); + val |= (range << (chan << 1)); + if (val != devpriv->da_ranges) { + outb(val, dev->iobase + PCI1720_RANGE); + devpriv->da_ranges = val; } - val = s->readback[chan]; - for (n = 0; n < insn->n; n++) { - val = data[n]; + val = s->readback[chan]; + for (i = 0; i < insn->n; i++) { + val = data[i]; outw(val, dev->iobase + PCI1720_DA0 + (chan << 1)); - outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ + outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */ } s->readback[chan] = val; - return n; + return insn->n; } /* @@ -1118,7 +1117,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, switch (this_board->cardtype) { case TYPE_PCI1720: s->n_chan = 4; - s->insn_write = pci1720_insn_write_ao; + s->insn_write = pci1720_ao_insn_write; break; default: s->n_chan = 2; -- cgit v0.10.2 From 2d21fc2280e48b35dd467ab7801925d6f98b28af Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:10 -0700 Subject: staging: comedi: adv_pci1710: tidy up pci171x_insn_write_ao() For aesthetics, rename this function and tidy it up. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index dca1bf2..ce91cec 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -466,41 +466,30 @@ static int pci171x_insn_read_ai(struct comedi_device *dev, return ret ? ret : insn->n; } -/* -============================================================================== -*/ -static int pci171x_insn_write_ao(struct comedi_device *dev, +static int pci171x_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct pci1710_private *devpriv = dev->private; - unsigned int val; - int n, chan, range, ofs; - - chan = CR_CHAN(insn->chanspec); - range = CR_RANGE(insn->chanspec); - if (chan) { - devpriv->da_ranges &= 0xfb; - devpriv->da_ranges |= (range << 2); - outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); - ofs = PCI171x_DA2; - } else { - devpriv->da_ranges &= 0xfe; - devpriv->da_ranges |= range; - outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); - ofs = PCI171x_DA1; - } - val = s->readback[chan]; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int reg = chan ? PCI171x_DA2 : PCI171x_DA1; + unsigned int val = s->readback[chan]; + int i; + + devpriv->da_ranges &= ~(1 << (chan << 1)); + devpriv->da_ranges |= (range << (chan << 1)); + outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); - for (n = 0; n < insn->n; n++) { - val = data[n]; - outw(val, dev->iobase + ofs); + for (i = 0; i < insn->n; i++) { + val = data[i]; + outw(val, dev->iobase + reg); } s->readback[chan] = val; - return n; - + return insn->n; } /* @@ -1121,7 +1110,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, break; default: s->n_chan = 2; - s->insn_write = pci171x_insn_write_ao; + s->insn_write = pci171x_ao_insn_write; break; } -- cgit v0.10.2 From db2c4a053629d4ce7ef6b0c760ce4232758fbb1d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:11 -0700 Subject: staging: comedi: adv_pci1710: tidy up counter subdevice init For aesthetics, add some whitespace to the counter subdevice init and rename the support functions. Also remove the unnecessary comments. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index ce91cec..4b0735a 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -532,10 +532,7 @@ static void pci171x_start_pacer(struct comedi_device *dev, } } -/* -============================================================================== -*/ -static int pci171x_insn_counter_read(struct comedi_device *dev, +static int pci171x_counter_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -556,10 +553,7 @@ static int pci171x_insn_counter_read(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ -static int pci171x_insn_counter_write(struct comedi_device *dev, +static int pci171x_counter_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -586,10 +580,7 @@ static int pci171x_insn_counter_write(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ -static int pci171x_insn_counter_config(struct comedi_device *dev, +static int pci171x_counter_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -1151,14 +1142,14 @@ static int pci1710_auto_attach(struct comedi_device *dev, if (this_board->has_counter) { s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 1; - s->maxdata = 0xffff; - s->range_table = &range_unknown; - s->insn_read = pci171x_insn_counter_read; - s->insn_write = pci171x_insn_counter_write; - s->insn_config = pci171x_insn_counter_config; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 1; + s->maxdata = 0xffff; + s->range_table = &range_unknown; + s->insn_read = pci171x_counter_insn_read; + s->insn_write = pci171x_counter_insn_write; + s->insn_config = pci171x_counter_insn_config; subdev++; } -- cgit v0.10.2 From 1fbe6e91a004fe95ddb6b2d96c41f69f2a4f0320 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:12 -0700 Subject: staging: comedi: adv_pci1710: tidy up digital input and output subdevice init For aesthetics, add some whitespace to the digital input and output subdevice init and rename the support functions. Also remove the unnecessary comment. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 4b0735a..297a560 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -492,19 +492,17 @@ static int pci171x_ao_insn_write(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ -static int pci171x_insn_bits_di(struct comedi_device *dev, +static int pci171x_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { data[1] = inw(dev->iobase + PCI171x_DI); return insn->n; } -static int pci171x_insn_bits_do(struct comedi_device *dev, +static int pci171x_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -1122,21 +1120,21 @@ static int pci1710_auto_attach(struct comedi_device *dev, if (this_board->has_di_do) { s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = pci171x_insn_bits_di; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pci171x_di_insn_bits; subdev++; s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 16; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = pci171x_insn_bits_do; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 16; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pci171x_do_insn_bits; subdev++; } -- cgit v0.10.2 From b420eeaf10223b2f666ac0fff9d65f5b66ffed65 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:13 -0700 Subject: staging: comedi: adv_pci1710: tidy up analog output subdevice init For aesthetics, add some whitespace to the analog output subdevice init. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 297a560..ba34a26 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1088,18 +1088,18 @@ static int pci1710_auto_attach(struct comedi_device *dev, if (this_board->has_ao) { s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; - s->maxdata = 0x0fff; - s->range_table = this_board->rangelist_ao; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->maxdata = 0x0fff; + s->range_table = this_board->rangelist_ao; switch (this_board->cardtype) { case TYPE_PCI1720: - s->n_chan = 4; - s->insn_write = pci1720_ao_insn_write; + s->n_chan = 4; + s->insn_write = pci1720_ao_insn_write; break; default: - s->n_chan = 2; - s->insn_write = pci171x_ao_insn_write; + s->n_chan = 2; + s->insn_write = pci171x_ao_insn_write; break; } -- cgit v0.10.2 From fc8e86898fe5e5a32d64a02e297c1659213b2237 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:14 -0700 Subject: staging: comedi: adv_pci1710: tidy up analog input subdevice init For aesthetics, add some whitespace to the analog input subdevice init and rename the (*insn_read) support function. Also remove the unnecessary comments. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index ba34a26..4c638a0 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -426,9 +426,10 @@ static int pci171x_ai_eoc(struct comedi_device *dev, return -EBUSY; } -static int pci171x_insn_read_ai(struct comedi_device *dev, +static int pci171x_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct pci1710_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); @@ -644,9 +645,6 @@ static int pci1720_ao_insn_write(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ static int pci171x_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { @@ -873,9 +871,6 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -/* -============================================================================== -*/ static int pci171x_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) @@ -1067,21 +1062,21 @@ static int pci1710_auto_attach(struct comedi_device *dev, if (this_board->n_aichan) { s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; if (this_board->has_diff_ai) - s->subdev_flags |= SDF_DIFF; - s->n_chan = this_board->n_aichan; - s->maxdata = 0x0fff; - s->range_table = this_board->rangelist_ai; - s->insn_read = pci171x_insn_read_ai; + s->subdev_flags |= SDF_DIFF; + s->n_chan = this_board->n_aichan; + s->maxdata = 0x0fff; + s->range_table = this_board->rangelist_ai; + s->insn_read = pci171x_ai_insn_read; if (dev->irq) { dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; - s->len_chanlist = s->n_chan; - s->do_cmdtest = pci171x_ai_cmdtest; - s->do_cmd = pci171x_ai_cmd; - s->cancel = pci171x_ai_cancel; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = s->n_chan; + s->do_cmdtest = pci171x_ai_cmdtest; + s->do_cmd = pci171x_ai_cmd; + s->cancel = pci171x_ai_cancel; } subdev++; } -- cgit v0.10.2 From 383fab4074c4b7da17284e54c969c87d24f3167e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:15 -0700 Subject: staging: comedi: adv_pci1710: rename 'this_board' local variables For aesthetics, rename all the 'this_board' local variables to simply 'board'. That's more common in comed drivers. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 4c638a0..4fdf041 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -388,14 +388,14 @@ static void setup_channel_list(struct comedi_device *dev, unsigned int *chanlist, unsigned int n_chan, unsigned int seglen) { - const struct boardtype *this_board = dev->board_ptr; + const struct boardtype *board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; unsigned int i, range, chanprog; for (i = 0; i < seglen; i++) { /* store range list to card */ chanprog = muxonechan[CR_CHAN(chanlist[i])]; outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */ - range = this_board->rangecode_ai[CR_RANGE(chanlist[i])]; + range = board->rangecode_ai[CR_RANGE(chanlist[i])]; if (CR_AREF(chanlist[i]) == AREF_DIFF) range |= 0x0020; outw(range, dev->iobase + PCI171x_RANGE); /* select gain */ @@ -648,10 +648,10 @@ static int pci1720_ao_insn_write(struct comedi_device *dev, static int pci171x_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct boardtype *this_board = dev->board_ptr; + const struct boardtype *board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; - switch (this_board->cardtype) { + switch (board->cardtype) { default: devpriv->CntrlReg &= Control_CNT0; devpriv->CntrlReg |= Control_SW; @@ -950,7 +950,7 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, */ static int pci171x_reset(struct comedi_device *dev) { - const struct boardtype *this_board = dev->board_ptr; + const struct boardtype *board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; outw(0x30, dev->iobase + PCI171x_CNTCTRL); @@ -962,7 +962,7 @@ static int pci171x_reset(struct comedi_device *dev) outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */ pci171x_start_pacer(dev, false); devpriv->da_ranges = 0; - if (this_board->has_ao) { + if (board->has_ao) { /* set DACs to 0..5V */ outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); outw(0, dev->iobase + PCI171x_DA1); /* set DA outputs to 0V */ @@ -1000,9 +1000,9 @@ static int pci1720_reset(struct comedi_device *dev) */ static int pci1710_reset(struct comedi_device *dev) { - const struct boardtype *this_board = dev->board_ptr; + const struct boardtype *board = dev->board_ptr; - switch (this_board->cardtype) { + switch (board->cardtype) { case TYPE_PCI1720: return pci1720_reset(dev); default: @@ -1014,17 +1014,17 @@ static int pci1710_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct boardtype *this_board = NULL; + const struct boardtype *board = NULL; struct pci1710_private *devpriv; struct comedi_subdevice *s; int ret, subdev, n_subdevices; if (context < ARRAY_SIZE(boardtypes)) - this_board = &boardtypes[context]; - if (!this_board) + board = &boardtypes[context]; + if (!board) return -ENODEV; - dev->board_ptr = this_board; - dev->board_name = this_board->name; + dev->board_ptr = board; + dev->board_name = board->name; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -1036,13 +1036,13 @@ static int pci1710_auto_attach(struct comedi_device *dev, dev->iobase = pci_resource_start(pcidev, 2); n_subdevices = 0; - if (this_board->n_aichan) + if (board->n_aichan) n_subdevices++; - if (this_board->has_ao) + if (board->has_ao) n_subdevices++; - if (this_board->has_di_do) + if (board->has_di_do) n_subdevices += 2; - if (this_board->has_counter) + if (board->has_counter) n_subdevices++; ret = comedi_alloc_subdevices(dev, n_subdevices); @@ -1051,7 +1051,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, pci1710_reset(dev); - if (this_board->has_irq && pcidev->irq) { + if (board->has_irq && pcidev->irq) { ret = request_irq(pcidev->irq, interrupt_service_pci1710, IRQF_SHARED, dev->board_name, dev); if (ret == 0) @@ -1060,15 +1060,15 @@ static int pci1710_auto_attach(struct comedi_device *dev, subdev = 0; - if (this_board->n_aichan) { + if (board->n_aichan) { s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; - if (this_board->has_diff_ai) + if (board->has_diff_ai) s->subdev_flags |= SDF_DIFF; - s->n_chan = this_board->n_aichan; + s->n_chan = board->n_aichan; s->maxdata = 0x0fff; - s->range_table = this_board->rangelist_ai; + s->range_table = board->rangelist_ai; s->insn_read = pci171x_ai_insn_read; if (dev->irq) { dev->read_subdev = s; @@ -1081,13 +1081,13 @@ static int pci1710_auto_attach(struct comedi_device *dev, subdev++; } - if (this_board->has_ao) { + if (board->has_ao) { s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->maxdata = 0x0fff; - s->range_table = this_board->rangelist_ao; - switch (this_board->cardtype) { + s->range_table = board->rangelist_ao; + switch (board->cardtype) { case TYPE_PCI1720: s->n_chan = 4; s->insn_write = pci1720_ao_insn_write; @@ -1103,7 +1103,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, return ret; /* initialize the readback values to match the board reset */ - if (this_board->cardtype == TYPE_PCI1720) { + if (board->cardtype == TYPE_PCI1720) { int i; for (i = 0; i < s->n_chan; i++) @@ -1113,7 +1113,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, subdev++; } - if (this_board->has_di_do) { + if (board->has_di_do) { s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; @@ -1133,7 +1133,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, subdev++; } - if (this_board->has_counter) { + if (board->has_counter) { s = &dev->subdevices[subdev]; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; @@ -1147,7 +1147,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, } /* max_samples is half the FIFO size (2 bytes/sample) */ - devpriv->max_samples = (this_board->has_large_fifo) ? 2048 : 512; + devpriv->max_samples = (board->has_large_fifo) ? 2048 : 512; return 0; } -- cgit v0.10.2 From 6e7862fc10fc0e8159a18199509e3aa7c658375a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:16 -0700 Subject: staging: comedi: adv_pci1710: remove function separation comments Remove the remaining, unnecessary, function separation comments. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 4fdf041..200be09 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -714,9 +714,6 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, comedi_handle_events(dev, s); } -/* -============================================================================== -*/ static int move_block_from_fifo(struct comedi_device *dev, struct comedi_subdevice *s, int n, int turn) { @@ -786,9 +783,6 @@ static void pci1710_handle_fifo(struct comedi_device *dev, comedi_handle_events(dev, s); } -/* -============================================================================== -*/ static irqreturn_t interrupt_service_pci1710(int irq, void *d) { struct comedi_device *dev = d; @@ -945,9 +939,6 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, return 0; } -/* -============================================================================== -*/ static int pci171x_reset(struct comedi_device *dev) { const struct boardtype *board = dev->board_ptr; @@ -975,9 +966,6 @@ static int pci171x_reset(struct comedi_device *dev) return 0; } -/* -============================================================================== -*/ static int pci1720_reset(struct comedi_device *dev) { struct pci1710_private *devpriv = dev->private; @@ -995,9 +983,6 @@ static int pci1720_reset(struct comedi_device *dev) return 0; } -/* -============================================================================== -*/ static int pci1710_reset(struct comedi_device *dev) { const struct boardtype *board = dev->board_ptr; -- cgit v0.10.2 From 76201d05165679e1eb10c826f6516c6ba8ace733 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:17 -0700 Subject: staging: comedi: adv_pci1710: update the MODULE_DESCRIPTION Change the MODULE_DESCRIPTION to something more useful than the generic "Comedi low-level driver". Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 200be09..2017285 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1227,5 +1227,5 @@ static struct pci_driver adv_pci1710_pci_driver = { module_comedi_pci_driver(adv_pci1710_driver, adv_pci1710_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi: Advantech PCI-1710 Series Multifunction DAS Cards"); MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 7a772eea0ca15bafb76db218d4f5bd69d9bf9f77 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:18 -0700 Subject: staging: comedi: adv_pci1710: remove boardinfo 'rangelist_ao' This boardinfo is not necessary. All the boards with analog outputs have the same range options except for the pci1720 board. That board type is already handled specially during the driver attach. Remove the boardinfo and add the subdevice range_table initialization in the cardtype switch. Rename the range tables to clarify that they are "analog output" ranges. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 2017285..62c2a51 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -164,7 +164,7 @@ static const struct comedi_lrange range_pci17x1 = { static const char range_codes_pci17x1[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; -static const struct comedi_lrange range_pci1720 = { +static const struct comedi_lrange pci1720_ao_range = { 4, { UNI_RANGE(5), UNI_RANGE(10), @@ -173,7 +173,7 @@ static const struct comedi_lrange range_pci1720 = { } }; -static const struct comedi_lrange range_pci171x_da = { +static const struct comedi_lrange pci171x_ao_range = { 2, { UNI_RANGE(5), UNI_RANGE(10) @@ -195,7 +195,6 @@ struct boardtype { int n_aichan; /* num of A/D chans */ const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ const char *rangecode_ai; /* range codes for programming */ - const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ unsigned int has_irq:1; unsigned int has_large_fifo:1; /* 4K or 1K FIFO */ unsigned int has_diff_ai:1; @@ -211,7 +210,6 @@ static const struct boardtype boardtypes[] = { .n_aichan = 16, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, - .rangelist_ao = &range_pci171x_da, .has_irq = 1, .has_large_fifo = 1, .has_diff_ai = 1, @@ -225,7 +223,6 @@ static const struct boardtype boardtypes[] = { .n_aichan = 16, .rangelist_ai = &range_pci1710hg, .rangecode_ai = range_codes_pci1710hg, - .rangelist_ao = &range_pci171x_da, .has_irq = 1, .has_large_fifo = 1, .has_diff_ai = 1, @@ -239,7 +236,6 @@ static const struct boardtype boardtypes[] = { .n_aichan = 16, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, - .rangelist_ao = &range_pci171x_da, .has_irq = 1, .has_ao = 1, .has_di_do = 1, @@ -258,7 +254,6 @@ static const struct boardtype boardtypes[] = { [BOARD_PCI1720] = { .name = "pci1720", .cardtype = TYPE_PCI1720, - .rangelist_ao = &range_pci1720, .has_ao = 1, }, [BOARD_PCI1731] = { @@ -1071,14 +1066,15 @@ static int pci1710_auto_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->maxdata = 0x0fff; - s->range_table = board->rangelist_ao; switch (board->cardtype) { case TYPE_PCI1720: s->n_chan = 4; + s->range_table = &pci1720_ao_range; s->insn_write = pci1720_ao_insn_write; break; default: s->n_chan = 2; + s->range_table = &pci171x_ao_range; s->insn_write = pci171x_ao_insn_write; break; } -- cgit v0.10.2 From e4451eeb456550d1fa1641ce369c1b914b02d225 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:19 -0700 Subject: staging: comedi: adv_pci1710: refactor boardinfo 'cardtype' The 'cardtype' in the boardinfo is only used to: 1) determine if the board is a pci1720 during the attach of the driver and when reseting the board 2) determine is the board is not a pci1713 when checking for analog input data dropout There is also an unnecessary use of the 'cardtype' when canceling an analog input async command. Remove the 'cardtype' member and add two bit-field flags, 'is_pci1713' and 'is_pci1720'. Refactor the driver to use the new flags. Remove the unnecessary cardtype handling in pci171x_ai_cancel(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 62c2a51..9bbdef8 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -51,11 +51,6 @@ Configuration options: #include "8253.h" #include "amcc_s5933.h" -/* hardware types of the cards */ -#define TYPE_PCI171X 0 -#define TYPE_PCI1713 2 -#define TYPE_PCI1720 3 - #define PCI171x_AD_DATA 0 /* R: A/D data */ #define PCI171x_SOFTTRG 0 /* W: soft trigger for A/D */ #define PCI171x_RANGE 2 /* W: A/D gain/range register */ @@ -191,10 +186,11 @@ enum pci1710_boardid { struct boardtype { const char *name; /* board name */ - char cardtype; /* 0=1710& co. 2=1713, ... */ int n_aichan; /* num of A/D chans */ const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ const char *rangecode_ai; /* range codes for programming */ + unsigned int is_pci1713:1; + unsigned int is_pci1720:1; unsigned int has_irq:1; unsigned int has_large_fifo:1; /* 4K or 1K FIFO */ unsigned int has_diff_ai:1; @@ -206,7 +202,6 @@ struct boardtype { static const struct boardtype boardtypes[] = { [BOARD_PCI1710] = { .name = "pci1710", - .cardtype = TYPE_PCI171X, .n_aichan = 16, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, @@ -219,7 +214,6 @@ static const struct boardtype boardtypes[] = { }, [BOARD_PCI1710HG] = { .name = "pci1710hg", - .cardtype = TYPE_PCI171X, .n_aichan = 16, .rangelist_ai = &range_pci1710hg, .rangecode_ai = range_codes_pci1710hg, @@ -232,7 +226,6 @@ static const struct boardtype boardtypes[] = { }, [BOARD_PCI1711] = { .name = "pci1711", - .cardtype = TYPE_PCI171X, .n_aichan = 16, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, @@ -243,22 +236,21 @@ static const struct boardtype boardtypes[] = { }, [BOARD_PCI1713] = { .name = "pci1713", - .cardtype = TYPE_PCI1713, .n_aichan = 32, .rangelist_ai = &range_pci1710_3, .rangecode_ai = range_codes_pci1710_3, + .is_pci1713 = 1, .has_irq = 1, .has_large_fifo = 1, .has_diff_ai = 1, }, [BOARD_PCI1720] = { .name = "pci1720", - .cardtype = TYPE_PCI1720, + .is_pci1720 = 1, .has_ao = 1, }, [BOARD_PCI1731] = { .name = "pci1731", - .cardtype = TYPE_PCI171X, .n_aichan = 16, .rangelist_ai = &range_pci17x1, .rangecode_ai = range_codes_pci17x1, @@ -300,7 +292,7 @@ static int pci171x_ai_dropout(struct comedi_device *dev, const struct boardtype *board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; - if (board->cardtype != TYPE_PCI1713) { + if (!board->is_pci1713) { if ((val & 0xf000) != devpriv->act_chanlist[chan]) { dev_err(dev->class_dev, "A/D data droput: received from channel %d, expected %d\n", @@ -643,20 +635,15 @@ static int pci1720_ao_insn_write(struct comedi_device *dev, static int pci171x_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct boardtype *board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; - switch (board->cardtype) { - default: - devpriv->CntrlReg &= Control_CNT0; - devpriv->CntrlReg |= Control_SW; - /* reset any operations */ - outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); - pci171x_start_pacer(dev, false); - outb(0, dev->iobase + PCI171x_CLRFIFO); - outb(0, dev->iobase + PCI171x_CLRINT); - break; - } + devpriv->CntrlReg &= Control_CNT0; + devpriv->CntrlReg |= Control_SW; + /* reset any operations */ + outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); + pci171x_start_pacer(dev, false); + outb(0, dev->iobase + PCI171x_CLRFIFO); + outb(0, dev->iobase + PCI171x_CLRINT); return 0; } @@ -982,12 +969,10 @@ static int pci1710_reset(struct comedi_device *dev) { const struct boardtype *board = dev->board_ptr; - switch (board->cardtype) { - case TYPE_PCI1720: + if (board->is_pci1720) return pci1720_reset(dev); - default: - return pci171x_reset(dev); - } + + return pci171x_reset(dev); } static int pci1710_auto_attach(struct comedi_device *dev, @@ -1066,17 +1051,14 @@ static int pci1710_auto_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; s->maxdata = 0x0fff; - switch (board->cardtype) { - case TYPE_PCI1720: + if (board->is_pci1720) { s->n_chan = 4; s->range_table = &pci1720_ao_range; s->insn_write = pci1720_ao_insn_write; - break; - default: + } else { s->n_chan = 2; s->range_table = &pci171x_ao_range; s->insn_write = pci171x_ao_insn_write; - break; } ret = comedi_alloc_subdev_readback(s); @@ -1084,7 +1066,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, return ret; /* initialize the readback values to match the board reset */ - if (board->cardtype == TYPE_PCI1720) { + if (board->is_pci1720) { int i; for (i = 0; i < s->n_chan; i++) -- cgit v0.10.2 From 133dfbfb226db01d0548efcd712ba11c5f208922 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:20 -0700 Subject: staging: comedi: adv_pci1710: clarify the 'act_chanlist' This driver saves the channel list of a scan in the private data and uses that list to check analog input samples for data dropout. Currently the channel numbers are shifted 12 bits so that they match the channel number in the samples that are read from the board. All of the shifts make the driver a bit harder to follow. Store the channel numbers directly to the 'act_chanlist' and shift the sample value instead when checking for the dropout. Add a comment for clarity. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 9bbdef8..0927bbe 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -293,11 +293,16 @@ static int pci171x_ai_dropout(struct comedi_device *dev, struct pci1710_private *devpriv = dev->private; if (!board->is_pci1713) { - if ((val & 0xf000) != devpriv->act_chanlist[chan]) { + /* + * The upper 4 bits of the 16-bit sample are the channel number + * that the sample was acquired from. Verify that this channel + * number matches the expected channel number. + */ + val >>= 12; + if (val != devpriv->act_chanlist[chan]) { dev_err(dev->class_dev, "A/D data droput: received from channel %d, expected %d\n", - (val >> 12) & 0xf, - (devpriv->act_chanlist[chan] >> 12) & 0xf); + val, devpriv->act_chanlist[chan]); return -ENODATA; } } @@ -386,13 +391,10 @@ static void setup_channel_list(struct comedi_device *dev, if (CR_AREF(chanlist[i]) == AREF_DIFF) range |= 0x0020; outw(range, dev->iobase + PCI171x_RANGE); /* select gain */ - devpriv->act_chanlist[i] = - (CR_CHAN(chanlist[i]) << 12) & 0xf000; - } - for ( ; i < n_chan; i++) { /* store remainder of channel list */ - devpriv->act_chanlist[i] = - (CR_CHAN(chanlist[i]) << 12) & 0xf000; + devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); } + for ( ; i < n_chan; i++) /* store remainder of channel list */ + devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); devpriv->ai_et_MuxVal = CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8); -- cgit v0.10.2 From a65e1419e64c26c3c14ba93d65ea86a416f47569 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:21 -0700 Subject: staging: comedi: adv_pci1710: tidy up setup_channel_list() Rename this function so it has namespace associated with the driver. Tidy up the code to clarify the function. Remove the unnecessary static const array muxonechan[]. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 0927bbe..719497c 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -276,14 +276,6 @@ struct pci1710_private { * internal state */ }; -/* used for gain list programming */ -static const unsigned int muxonechan[] = { - 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, - 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, - 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717, - 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f -}; - static int pci171x_ai_dropout(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int chan, @@ -375,30 +367,39 @@ static int pci171x_ai_check_chanlist(struct comedi_device *dev, return 0; } -static void setup_channel_list(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int *chanlist, unsigned int n_chan, - unsigned int seglen) +static void pci171x_ai_setup_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int *chanlist, + unsigned int n_chan, + unsigned int seglen) { const struct boardtype *board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; - unsigned int i, range, chanprog; + unsigned int first_chan = CR_CHAN(chanlist[0]); + unsigned int last_chan = CR_CHAN(chanlist[seglen - 1]); + unsigned int i; for (i = 0; i < seglen; i++) { /* store range list to card */ - chanprog = muxonechan[CR_CHAN(chanlist[i])]; - outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */ - range = board->rangecode_ai[CR_RANGE(chanlist[i])]; - if (CR_AREF(chanlist[i]) == AREF_DIFF) - range |= 0x0020; - outw(range, dev->iobase + PCI171x_RANGE); /* select gain */ - devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); + unsigned int chan = CR_CHAN(chanlist[i]); + unsigned int range = CR_RANGE(chanlist[i]); + unsigned int aref = CR_AREF(chanlist[i]); + unsigned int rangeval; + + rangeval = board->rangecode_ai[range]; + if (aref == AREF_DIFF) + rangeval |= 0x0020; + + /* select channel and set range */ + outw(chan | (chan << 8), dev->iobase + PCI171x_MUX); + outw(rangeval, dev->iobase + PCI171x_RANGE); + + devpriv->act_chanlist[i] = chan; } for ( ; i < n_chan; i++) /* store remainder of channel list */ devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); - devpriv->ai_et_MuxVal = - CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8); /* select channel interval to scan */ + devpriv->ai_et_MuxVal = first_chan | (last_chan << 8); outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); } @@ -431,7 +432,7 @@ static int pci171x_ai_insn_read(struct comedi_device *dev, outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); - setup_channel_list(dev, s, &insn->chanspec, 1, 1); + pci171x_ai_setup_chanlist(dev, s, &insn->chanspec, 1, 1); for (i = 0; i < insn->n; i++) { unsigned int val; @@ -813,8 +814,8 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) pci171x_start_pacer(dev, false); - setup_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len, - devpriv->saved_seglen); + pci171x_ai_setup_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, + devpriv->saved_seglen); outb(0, dev->iobase + PCI171x_CLRFIFO); outb(0, dev->iobase + PCI171x_CLRINT); -- cgit v0.10.2 From 7fd2dae2500dee7da9a16557ace9506fb8aefd12 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:22 -0700 Subject: staging: comedi: adv_pci1710: introduce pci171x_ai_read_sample() Introduce a helper function to read an analog input sample, check for channel dropout, and mask the sample to the maxdata of the subdevice. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 719497c..6068f40 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -276,31 +276,6 @@ struct pci1710_private { * internal state */ }; -static int pci171x_ai_dropout(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int chan, - unsigned int val) -{ - const struct boardtype *board = dev->board_ptr; - struct pci1710_private *devpriv = dev->private; - - if (!board->is_pci1713) { - /* - * The upper 4 bits of the 16-bit sample are the channel number - * that the sample was acquired from. Verify that this channel - * number matches the expected channel number. - */ - val >>= 12; - if (val != devpriv->act_chanlist[chan]) { - dev_err(dev->class_dev, - "A/D data droput: received from channel %d, expected %d\n", - val, devpriv->act_chanlist[chan]); - return -ENODATA; - } - } - return 0; -} - static int pci171x_ai_check_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) @@ -416,6 +391,35 @@ static int pci171x_ai_eoc(struct comedi_device *dev, return -EBUSY; } +static int pci171x_ai_read_sample(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int cur_chan, + unsigned int *val) +{ + const struct boardtype *board = dev->board_ptr; + struct pci1710_private *devpriv = dev->private; + unsigned int sample; + unsigned int chan; + + sample = inw(dev->iobase + PCI171x_AD_DATA); + if (!board->is_pci1713) { + /* + * The upper 4 bits of the 16-bit sample are the channel number + * that the sample was acquired from. Verify that this channel + * number matches the expected channel number. + */ + chan = sample >> 12; + if (chan != devpriv->act_chanlist[cur_chan]) { + dev_err(dev->class_dev, + "A/D data droput: received from channel %d, expected %d\n", + chan, devpriv->act_chanlist[cur_chan]); + return -ENODATA; + } + } + *val = sample & s->maxdata; + return 0; +} + static int pci171x_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -443,12 +447,11 @@ static int pci171x_ai_insn_read(struct comedi_device *dev, if (ret) break; - val = inw(dev->iobase + PCI171x_AD_DATA); - ret = pci171x_ai_dropout(dev, s, chan, val); + ret = pci171x_ai_read_sample(dev, s, chan, &val); if (ret) break; - data[i] = val & s->maxdata; + data[i] = val; } outb(0, dev->iobase + PCI171x_CLRFIFO); @@ -677,14 +680,12 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) { - val = inw(dev->iobase + PCI171x_AD_DATA); - ret = pci171x_ai_dropout(dev, s, s->async->cur_chan, val); + ret = pci171x_ai_read_sample(dev, s, s->async->cur_chan, &val); if (ret) { s->async->events |= COMEDI_CB_ERROR; break; } - val &= s->maxdata; comedi_buf_write_samples(s, &val, 1); if (cmd->stop_src == TRIG_COUNT && @@ -707,15 +708,12 @@ static int move_block_from_fifo(struct comedi_device *dev, int i; for (i = 0; i < n; i++) { - val = inw(dev->iobase + PCI171x_AD_DATA); - - ret = pci171x_ai_dropout(dev, s, s->async->cur_chan, val); + ret = pci171x_ai_read_sample(dev, s, s->async->cur_chan, &val); if (ret) { s->async->events |= COMEDI_CB_ERROR; return ret; } - val &= s->maxdata; comedi_buf_write_samples(s, &val, 1); } return 0; -- cgit v0.10.2 From d61b786ab0950ccf451336bcbc5fb159025e77c8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:23 -0700 Subject: staging: comedi: adv_pci1710: do comedi_handle_events() in common code patch The pci1710_handle_every_sample() and pci1710_handle_fifo() helpers, called by the interrupt handler, both have multiple comedi_handle_events() calls. Remove these and just do a single comedi_handle_events() at the end of the interrupt handler. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 6068f40..7ad59ab 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -666,14 +666,12 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, if (status & Status_FE) { dev_dbg(dev->class_dev, "A/D FIFO empty (%4x)\n", status); s->async->events |= COMEDI_CB_ERROR; - comedi_handle_events(dev, s); return; } if (status & Status_FF) { dev_dbg(dev->class_dev, "A/D FIFO Full status (Fatal Error!) (%4x)\n", status); s->async->events |= COMEDI_CB_ERROR; - comedi_handle_events(dev, s); return; } @@ -696,8 +694,6 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, } outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ - - comedi_handle_events(dev, s); } static int move_block_from_fifo(struct comedi_device *dev, @@ -731,14 +727,12 @@ static void pci1710_handle_fifo(struct comedi_device *dev, if (!(m & Status_FH)) { dev_dbg(dev->class_dev, "A/D FIFO not half full! (%4x)\n", m); s->async->events |= COMEDI_CB_ERROR; - comedi_handle_events(dev, s); return; } if (m & Status_FF) { dev_dbg(dev->class_dev, "A/D FIFO Full status (Fatal Error!) (%4x)\n", m); s->async->events |= COMEDI_CB_ERROR; - comedi_handle_events(dev, s); return; } @@ -758,12 +752,10 @@ static void pci1710_handle_fifo(struct comedi_device *dev, if (cmd->stop_src == TRIG_COUNT && s->async->scans_done >= cmd->stop_arg) { s->async->events |= COMEDI_CB_EOA; - comedi_handle_events(dev, s); return; } outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ - comedi_handle_events(dev, s); } static irqreturn_t interrupt_service_pci1710(int irq, void *d) @@ -802,6 +794,8 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) else pci1710_handle_fifo(dev, s); + comedi_handle_events(dev, s); + return IRQ_HANDLED; } -- cgit v0.10.2 From f01663ec35eb37cd30bcdd0b97281bd147f29f45 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:24 -0700 Subject: staging: comedi: adv_pci1710: remove 'turn' param from move_block_from_fifo() This parameter is not used in the function. It was only used in some debug messages that were previously removed. Remove the parameter. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 7ad59ab..0a50053 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -697,7 +697,7 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, } static int move_block_from_fifo(struct comedi_device *dev, - struct comedi_subdevice *s, int n, int turn) + struct comedi_subdevice *s, int n) { unsigned int val; int ret; @@ -739,13 +739,13 @@ static void pci1710_handle_fifo(struct comedi_device *dev, nsamples = devpriv->max_samples; if (comedi_samples_to_bytes(s, nsamples) >= s->async->prealloc_bufsz) { m = comedi_bytes_to_samples(s, s->async->prealloc_bufsz); - if (move_block_from_fifo(dev, s, m, 0)) + if (move_block_from_fifo(dev, s, m)) return; nsamples -= m; } if (nsamples) { - if (move_block_from_fifo(dev, s, nsamples, 1)) + if (move_block_from_fifo(dev, s, nsamples)) return; } -- cgit v0.10.2 From d6c42d78c019ecef96ee09b20e55adf46fd430a2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:25 -0700 Subject: staging: comedi: adv_pci1710: transfer all ai samples in one step The two step process to transfer the ai samples in pci1710_handle_fifo() doesn't make any sense. If the async buffer does not have enough room for the samples the core will set the async event COMEDI_CB_OVERFLOW which will cause the async command to cancel. Splitting the transfer doesn't add any value. Transfer all the samples in one step to simplify the code. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 0a50053..76075db 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -720,7 +720,6 @@ static void pci1710_handle_fifo(struct comedi_device *dev, { struct pci1710_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - unsigned int nsamples; unsigned int m; m = inw(dev->iobase + PCI171x_STATUS); @@ -736,18 +735,8 @@ static void pci1710_handle_fifo(struct comedi_device *dev, return; } - nsamples = devpriv->max_samples; - if (comedi_samples_to_bytes(s, nsamples) >= s->async->prealloc_bufsz) { - m = comedi_bytes_to_samples(s, s->async->prealloc_bufsz); - if (move_block_from_fifo(dev, s, m)) - return; - nsamples -= m; - } - - if (nsamples) { - if (move_block_from_fifo(dev, s, nsamples)) - return; - } + if (move_block_from_fifo(dev, s, devpriv->max_samples)) + return; if (cmd->stop_src == TRIG_COUNT && s->async->scans_done >= cmd->stop_arg) { -- cgit v0.10.2 From c0e4a8decb2e519789537896d2f75ef979e8cf05 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 20 Jan 2015 14:53:26 -0700 Subject: staging: comedi: adv_pci1710: absorb move_block_from_fifo() This function is only called by pci1710_handle_fifo(). Absorb it and clean up pci1710_handle_fifo(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 76075db..9800c01 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -696,55 +696,49 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ } -static int move_block_from_fifo(struct comedi_device *dev, - struct comedi_subdevice *s, int n) -{ - unsigned int val; - int ret; - int i; - - for (i = 0; i < n; i++) { - ret = pci171x_ai_read_sample(dev, s, s->async->cur_chan, &val); - if (ret) { - s->async->events |= COMEDI_CB_ERROR; - return ret; - } - - comedi_buf_write_samples(s, &val, 1); - } - return 0; -} - static void pci1710_handle_fifo(struct comedi_device *dev, struct comedi_subdevice *s) { struct pci1710_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; - unsigned int m; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned int status; + int i; - m = inw(dev->iobase + PCI171x_STATUS); - if (!(m & Status_FH)) { - dev_dbg(dev->class_dev, "A/D FIFO not half full! (%4x)\n", m); - s->async->events |= COMEDI_CB_ERROR; + status = inw(dev->iobase + PCI171x_STATUS); + if (!(status & Status_FH)) { + dev_dbg(dev->class_dev, "A/D FIFO not half full!\n"); + async->events |= COMEDI_CB_ERROR; return; } - if (m & Status_FF) { + if (status & Status_FF) { dev_dbg(dev->class_dev, - "A/D FIFO Full status (Fatal Error!) (%4x)\n", m); - s->async->events |= COMEDI_CB_ERROR; + "A/D FIFO Full status (Fatal Error!)\n"); + async->events |= COMEDI_CB_ERROR; return; } - if (move_block_from_fifo(dev, s, devpriv->max_samples)) - return; + for (i = 0; i < devpriv->max_samples; i++) { + unsigned int val; + int ret; - if (cmd->stop_src == TRIG_COUNT && - s->async->scans_done >= cmd->stop_arg) { - s->async->events |= COMEDI_CB_EOA; - return; + ret = pci171x_ai_read_sample(dev, s, s->async->cur_chan, &val); + if (ret) { + s->async->events |= COMEDI_CB_ERROR; + break; + } + + if (!comedi_buf_write_samples(s, &val, 1)) + break; + + if (cmd->stop_src == TRIG_COUNT && + async->scans_done >= cmd->stop_arg) { + async->events |= COMEDI_CB_EOA; + break; + } } - outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ + outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */ } static irqreturn_t interrupt_service_pci1710(int irq, void *d) -- cgit v0.10.2 From 83d682bda16b515c61a99ff830964c1461b837a2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 21 Jan 2015 15:11:44 -0700 Subject: staging: comedi: ni_labpc_common: move comedi_alloc_devpriv() to common code The ni_labpc_common module is used by the ni_labpc, ni_labpc_pci, and ni_labpc_cs drivers to provide the common code support. Those drivers currently all call comedi_alloc_devpriv() to allocate the private data before calling the common attach function. For aesthetics, move the private data allocation into the common code. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 59da404..e7b25e8 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -84,15 +84,10 @@ static const struct labpc_boardinfo labpc_boards[] = { static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) { - struct labpc_private *devpriv; unsigned int irq = it->options[1]; unsigned int dma_chan = it->options[2]; int ret; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - ret = comedi_request_region(dev, it->options[0], 0x20); if (ret) return ret; diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index 8fb5c1f..3cd200a 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -1215,11 +1215,15 @@ int labpc_common_attach(struct comedi_device *dev, unsigned int irq, unsigned long isr_flags) { const struct labpc_boardinfo *board = dev->board_ptr; - struct labpc_private *devpriv = dev->private; + struct labpc_private *devpriv; struct comedi_subdevice *s; int ret; int i; + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) + return -ENOMEM; + if (dev->mmio) { devpriv->read_byte = labpc_readb; devpriv->write_byte = labpc_writeb; diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index 0a8b322..d58f1f9 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -80,7 +80,6 @@ static int labpc_auto_attach(struct comedi_device *dev, unsigned long context) { struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); - struct labpc_private *devpriv; int ret; /* The ni_labpc driver needs the board_ptr */ @@ -96,10 +95,6 @@ static int labpc_auto_attach(struct comedi_device *dev, if (!link->irq) return -EINVAL; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - return labpc_common_attach(dev, link->irq, IRQF_SHARED); } diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index a9f408a..0407ff6 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -79,7 +79,6 @@ static int labpc_pci_auto_attach(struct comedi_device *dev, { struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct labpc_boardinfo *board = NULL; - struct labpc_private *devpriv; int ret; if (context < ARRAY_SIZE(labpc_pci_boards)) @@ -101,10 +100,6 @@ static int labpc_pci_auto_attach(struct comedi_device *dev, if (!dev->mmio) return -ENOMEM; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - return labpc_common_attach(dev, pcidev->irq, IRQF_SHARED); } -- cgit v0.10.2 From 67a0149ee6b20e3e3da15be27acdbec319214280 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 21 Jan 2015 15:11:45 -0700 Subject: staging: comedi: ni_labpc_cs: remove unnecessary includes This driver includes a number of unnecessary headers. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index d58f1f9..ece0010 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -54,19 +54,15 @@ NI manuals: */ #include -#include "../comedidev.h" - -#include -#include "8253.h" -#include "8255.h" -#include "comedi_fc.h" -#include "ni_labpc.h" +#include "../comedidev.h" #include #include #include +#include "ni_labpc.h" + static const struct labpc_boardinfo labpc_cs_boards[] = { { .name = "daqcard-1200", -- cgit v0.10.2 From aae59483bce95c3fffd4fa66d5360712f372ba1a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 21 Jan 2015 15:11:46 -0700 Subject: staging: comedi: ni_labpc: remove unnecessary private data validation The labpc_free_dma_chan() function validates the private data. Remove the unnecessary validation in labpc_datach(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index e7b25e8..a916047 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -104,11 +104,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) static void labpc_detach(struct comedi_device *dev) { - struct labpc_private *devpriv = dev->private; - - if (devpriv) - labpc_free_dma_chan(dev); - + labpc_free_dma_chan(dev); comedi_legacy_detach(dev); } -- cgit v0.10.2 From bcdf8b5d01df2ac5aedf94e750a135c3798e3e93 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 21 Jan 2015 15:11:47 -0700 Subject: staging: comedi: ni_labpc_common: use DIV_ROUND_UP to round divisor values Use the DIV_ROUND_UP macro to clarify the (((n) + (d) - 1) / (d)) calculations. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index 3cd200a..c494c53 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -406,10 +406,10 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, (scan_period + (base_period / 2)) / base_period; break; case CMDF_ROUND_UP: - devpriv->divisor_a0 = - (convert_period + (base_period - 1)) / base_period; - devpriv->divisor_b1 = - (scan_period + (base_period - 1)) / base_period; + devpriv->divisor_a0 = DIV_ROUND_UP(convert_period, + base_period); + devpriv->divisor_b1 = DIV_ROUND_UP(scan_period, + base_period); break; case CMDF_ROUND_DOWN: devpriv->divisor_a0 = convert_period / base_period; -- cgit v0.10.2 From b35759de976320229ec708c7fa57a62249833ab9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 21 Jan 2015 15:11:48 -0700 Subject: staging: comedi: ni_labpc_common: use DIV_ROUND_CLOSEST to round divisor values Use the DIV_ROUND_CLOSEST macro to clarify the (((x) + ((divisor) / 2)) / (divisor)) calculations. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index c494c53..77a7856 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -400,10 +400,10 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, switch (cmd->flags & CMDF_ROUND_MASK) { default: case CMDF_ROUND_NEAREST: - devpriv->divisor_a0 = - (convert_period + (base_period / 2)) / base_period; - devpriv->divisor_b1 = - (scan_period + (base_period / 2)) / base_period; + devpriv->divisor_a0 = DIV_ROUND_CLOSEST(convert_period, + base_period); + devpriv->divisor_b1 = DIV_ROUND_CLOSEST(scan_period, + base_period); break; case CMDF_ROUND_UP: devpriv->divisor_a0 = DIV_ROUND_UP(convert_period, -- cgit v0.10.2 From c79089c8d625824863bd922c9cf4096b54a98709 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 21 Jan 2015 15:11:49 -0700 Subject: staging: comedi: ni_labpc_common: use the cfc_check_trigger_arg_*() helpers For aesthetics, use the helper functions to check the min/max divisor values. Remove the const int local variables and open code the values. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_common.c b/drivers/staging/comedi/drivers/ni_labpc_common.c index 77a7856..b88ee26 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_common.c +++ b/drivers/staging/comedi/drivers/ni_labpc_common.c @@ -368,10 +368,6 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, enum scan_mode mode) { struct labpc_private *devpriv = dev->private; - /* max value for 16 bit counter in mode 2 */ - const int max_counter_value = 0x10000; - /* min value for 16 bit counter in mode 2 */ - const int min_counter_value = 2; unsigned int base_period; unsigned int scan_period; unsigned int convert_period; @@ -388,11 +384,10 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, * clock speed on convert and scan counters) */ devpriv->divisor_b0 = (scan_period - 1) / - (I8254_OSC_BASE_2MHZ * max_counter_value) + 1; - if (devpriv->divisor_b0 < min_counter_value) - devpriv->divisor_b0 = min_counter_value; - if (devpriv->divisor_b0 > max_counter_value) - devpriv->divisor_b0 = max_counter_value; + (I8254_OSC_BASE_2MHZ * 0x10000) + 1; + + cfc_check_trigger_arg_min(&devpriv->divisor_b0, 2); + cfc_check_trigger_arg_max(&devpriv->divisor_b0, 0x10000); base_period = I8254_OSC_BASE_2MHZ * devpriv->divisor_b0; @@ -417,14 +412,10 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd, break; } /* make sure a0 and b1 values are acceptable */ - if (devpriv->divisor_a0 < min_counter_value) - devpriv->divisor_a0 = min_counter_value; - if (devpriv->divisor_a0 > max_counter_value) - devpriv->divisor_a0 = max_counter_value; - if (devpriv->divisor_b1 < min_counter_value) - devpriv->divisor_b1 = min_counter_value; - if (devpriv->divisor_b1 > max_counter_value) - devpriv->divisor_b1 = max_counter_value; + cfc_check_trigger_arg_min(&devpriv->divisor_a0, 2); + cfc_check_trigger_arg_max(&devpriv->divisor_a0, 0x10000); + cfc_check_trigger_arg_min(&devpriv->divisor_b1, 2); + cfc_check_trigger_arg_max(&devpriv->divisor_b1, 0x10000); /* write corrected timings to command */ labpc_set_ai_convert_period(cmd, mode, base_period * devpriv->divisor_a0); -- cgit v0.10.2 From 8518a52c4456c697033bf81f0df73c026200ad8e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 21 Jan 2015 17:22:13 -0700 Subject: staging: comedi: vmk80xx: GPCT_RESET is not an (*insn_config) instruction The data[0] parameter to (*insn_config) functions is the "configuration instruction" that should be handled. These are defined by the enum configuration_ids in comedi.h. This driver is currently checking the data[0] value to be INSN_CONFIG_RESET or GPCT_RESET in order to reset a counter channel. GPCT_RESET is defined as 0x0001 which would match the configuration instruction INSN_CONFIG_DIO_OUTPUT. That doesn't make any sense for a counter. Remove GPCT_RESET from the insn_cmd test. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index 5312e0f..d200ad5 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -558,7 +558,7 @@ static int vmk80xx_cnt_insn_config(struct comedi_device *dev, int n; insn_cmd = data[0]; - if (insn_cmd != INSN_CONFIG_RESET && insn_cmd != GPCT_RESET) + if (insn_cmd != INSN_CONFIG_RESET) return -EINVAL; down(&devpriv->limit_sem); -- cgit v0.10.2 From a4a75b21014bfb4ab977e461e17d2c759472f84b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 21 Jan 2015 17:22:14 -0700 Subject: staging: comedi: vmk80xx: tidy up vmk80xx_cnt_insn_config() Tidy up this (*insn_config) function to follow the normal format in comedi drivers. INSN_CONFIG_RESET instructions do not have any extra parameters (insn->n is always 1) so the for loop used to write the packet doesn't make any sense. Remove it and just write the single packet. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index d200ad5..eb76460 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -551,41 +551,35 @@ static int vmk80xx_cnt_insn_config(struct comedi_device *dev, unsigned int *data) { struct vmk80xx_private *devpriv = dev->private; - unsigned int insn_cmd; - int chan; + unsigned int chan = CR_CHAN(insn->chanspec); int cmd; int reg; - int n; - - insn_cmd = data[0]; - if (insn_cmd != INSN_CONFIG_RESET) - return -EINVAL; + int ret; down(&devpriv->limit_sem); - - chan = CR_CHAN(insn->chanspec); - - if (devpriv->model == VMK8055_MODEL) { - if (!chan) { - cmd = VMK8055_CMD_RST_CNT1; - reg = VMK8055_CNT1_REG; + switch (data[0]) { + case INSN_CONFIG_RESET: + if (devpriv->model == VMK8055_MODEL) { + if (!chan) { + cmd = VMK8055_CMD_RST_CNT1; + reg = VMK8055_CNT1_REG; + } else { + cmd = VMK8055_CMD_RST_CNT2; + reg = VMK8055_CNT2_REG; + } + devpriv->usb_tx_buf[reg] = 0x00; } else { - cmd = VMK8055_CMD_RST_CNT2; - reg = VMK8055_CNT2_REG; + cmd = VMK8061_CMD_RST_CNT; } - - devpriv->usb_tx_buf[reg] = 0x00; - } else { - cmd = VMK8061_CMD_RST_CNT; + ret = vmk80xx_write_packet(dev, cmd); + break; + default: + ret = -EINVAL; + break; } - - for (n = 0; n < insn->n; n++) - if (vmk80xx_write_packet(dev, cmd)) - break; - up(&devpriv->limit_sem); - return n; + return ret ? ret : insn->n; } static int vmk80xx_cnt_insn_write(struct comedi_device *dev, -- cgit v0.10.2 From 9ef6a8331219b0242ac423cf9629d4f6377d4993 Mon Sep 17 00:00:00 2001 From: jitendra kumar khasdev Date: Sat, 24 Jan 2015 00:41:19 +0530 Subject: Staging: comedi: fix line over 80 characters warning This is patch to file jr3_pci.h that fix up warning line over 80 character which is found by checkpatch tool. Signed-off-by: Jitendra Kumar Khasdev Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/jr3_pci.h b/drivers/staging/comedi/drivers/jr3_pci.h index 20478ae..356811d 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.h +++ b/drivers/staging/comedi/drivers/jr3_pci.h @@ -261,8 +261,9 @@ struct intern_transform { } link[8]; }; -/* JR3 force/torque sensor data definition. For more information see sensor and */ -/* hardware manuals. */ +/* JR3 force/torque sensor data definition. For more information see sensor + * and hardware manuals. + */ struct jr3_channel { /* Raw_channels is the area used to store the raw data coming from */ -- cgit v0.10.2 From 41dff7ac1a7c97f5532931154bfdf505d7ce1631 Mon Sep 17 00:00:00 2001 From: Tristan Lelong Date: Sat, 17 Jan 2015 23:44:49 -0800 Subject: staging: lustre: remove kmalloc from fld_proc_hash_seq_write This patch simplifies the fld_proc_hash_seq_write function by removing the dynamic memory allocation. The longest fh_name used so far in lustre is 4 characters. We use a 8 bytes variable to be on the safe side. Signed-off-by: Tristan Lelong Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/fld/lproc_fld.c b/drivers/staging/lustre/lustre/fld/lproc_fld.c index 74b4db9..9b26bb5 100644 --- a/drivers/staging/lustre/lustre/fld/lproc_fld.c +++ b/drivers/staging/lustre/lustre/fld/lproc_fld.c @@ -93,17 +93,13 @@ fld_proc_hash_seq_write(struct file *file, { struct lu_client_fld *fld; struct lu_fld_hash *hash = NULL; - char *name; + char fh_name[8]; int i; - if (count > 80) + if (count > sizeof(fh_name)) return -ENAMETOOLONG; - name = kmalloc(count, GFP_KERNEL); - if (!name) - return -ENOMEM; - - if (copy_from_user(name, buffer, count) != 0) + if (copy_from_user(fh_name, buffer, count) != 0) return -EFAULT; fld = ((struct seq_file *)file->private_data)->private; @@ -113,7 +109,7 @@ fld_proc_hash_seq_write(struct file *file, if (count != strlen(fld_hash[i].fh_name)) continue; - if (!strncmp(fld_hash[i].fh_name, name, count)) { + if (!strncmp(fld_hash[i].fh_name, fh_name, count)) { hash = &fld_hash[i]; break; } @@ -128,7 +124,6 @@ fld_proc_hash_seq_write(struct file *file, fld->lcf_name, hash->fh_name); } - kfree(name); return count; } -- cgit v0.10.2 From a1ccbf9cc4f6828c4615642bbe664aed2103247b Mon Sep 17 00:00:00 2001 From: Jeremiah Mahler Date: Sun, 18 Jan 2015 03:17:52 -0800 Subject: staging: lustre: fix min() comparison types lacks cast build warning Recent changes to use the builtin min functions [1] introduced type checking which wasn't present before. This resulted in "comparision of distinct pointer types lacks a cast" build warnings on non X86 architectures [2,3]. [1]: https://lkml.org/lkml/2014/12/25/145 [2]: https://lists.01.org/pipermail/kbuild-all/2015-January/008588.html [3]: https://lists.01.org/pipermail/kbuild-all/2015-January/008589.html The call to min() which resulted in this warning took the result of kiblnd_rd_frag_size(), which returned a __u32, and the variable 'resid', which is an int. 'resid' is inside a while loop which is only entered if it is positive. Casting it as a __u32 can be perormed without a loss of data or change in functionality. Fix the warning by casting 'resid' as a __u32. Reported-by: kbuild test robot Signed-off-by: Jeremiah Mahler Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 4fd5d94..48d885d 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -1126,7 +1126,8 @@ kiblnd_init_rdma (kib_conn_t *conn, kib_tx_t *tx, int type, } wrknob = min(min(kiblnd_rd_frag_size(srcrd, srcidx), - kiblnd_rd_frag_size(dstrd, dstidx)), resid); + kiblnd_rd_frag_size(dstrd, dstidx)), + (__u32) resid); sge = &tx->tx_sge[tx->tx_nwrq]; sge->addr = kiblnd_rd_frag_addr(srcrd, srcidx); -- cgit v0.10.2 From f6219c16b10a590b9d8180b382f276ded8da3224 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Sun, 18 Jan 2015 15:06:47 +0100 Subject: staging: lustre: mdc: declare internal symbols as static Fixes sparse warnings like: warning: symbol '...' was not declared. Should it be static? Signed-off-by: Luca Ceresoli Cc: Peng Tao Cc: Jinshan Xiong Cc: Srikrishan Malik Cc: HPDD-discuss@lists.01.org Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 05d05ce..ef27447 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -855,8 +855,8 @@ static void mdc_close_handle_reply(struct ptlrpc_request *req, } } -int mdc_close(struct obd_export *exp, struct md_op_data *op_data, - struct md_open_data *mod, struct ptlrpc_request **request) +static int mdc_close(struct obd_export *exp, struct md_op_data *op_data, + struct md_open_data *mod, struct ptlrpc_request **request) { struct obd_device *obd = class_exp2obd(exp); struct ptlrpc_request *req; @@ -974,8 +974,8 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data, return rc < 0 ? rc : saved_rc; } -int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, - struct md_open_data *mod) +static int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, + struct md_open_data *mod) { struct obd_device *obd = class_exp2obd(exp); struct ptlrpc_request *req; @@ -1044,8 +1044,8 @@ int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, } -int mdc_readpage(struct obd_export *exp, struct md_op_data *op_data, - struct page **pages, struct ptlrpc_request **request) +static int mdc_readpage(struct obd_export *exp, struct md_op_data *op_data, + struct page **pages, struct ptlrpc_request **request) { struct ptlrpc_request *req; struct ptlrpc_bulk_desc *desc; @@ -1974,9 +1974,9 @@ out: return rc; } -int mdc_get_info_rpc(struct obd_export *exp, - u32 keylen, void *key, - int vallen, void *val) +static int mdc_get_info_rpc(struct obd_export *exp, + u32 keylen, void *key, + int vallen, void *val) { struct obd_import *imp = class_exp2cliimp(exp); struct ptlrpc_request *req; @@ -2148,11 +2148,11 @@ static int mdc_kuc_reregister(struct obd_import *imp) (void *)imp); } -int mdc_set_info_async(const struct lu_env *env, - struct obd_export *exp, - u32 keylen, void *key, - u32 vallen, void *val, - struct ptlrpc_request_set *set) +static int mdc_set_info_async(const struct lu_env *env, + struct obd_export *exp, + u32 keylen, void *key, + u32 vallen, void *val, + struct ptlrpc_request_set *set) { struct obd_import *imp = class_exp2cliimp(exp); int rc; @@ -2199,9 +2199,9 @@ int mdc_set_info_async(const struct lu_env *env, return -EINVAL; } -int mdc_get_info(const struct lu_env *env, struct obd_export *exp, - __u32 keylen, void *key, __u32 *vallen, void *val, - struct lov_stripe_md *lsm) +static int mdc_get_info(const struct lu_env *env, struct obd_export *exp, + __u32 keylen, void *key, __u32 *vallen, void *val, + struct lov_stripe_md *lsm) { int rc = -EINVAL; @@ -2263,8 +2263,8 @@ int mdc_get_info(const struct lu_env *env, struct obd_export *exp, return rc; } -int mdc_sync(struct obd_export *exp, const struct lu_fid *fid, - struct obd_capa *oc, struct ptlrpc_request **request) +static int mdc_sync(struct obd_export *exp, const struct lu_fid *fid, + struct obd_capa *oc, struct ptlrpc_request **request) { struct ptlrpc_request *req; int rc; @@ -2356,7 +2356,7 @@ int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid, return seq_client_alloc_fid(NULL, seq, fid); } -struct obd_uuid *mdc_get_uuid(struct obd_export *exp) +static struct obd_uuid *mdc_get_uuid(struct obd_export *exp) { struct client_obd *cli = &exp->exp_obd->u.cli; @@ -2390,7 +2390,7 @@ static int mdc_resource_inode_free(struct ldlm_resource *res) return 0; } -struct ldlm_valblock_ops inode_lvbo = { +static struct ldlm_valblock_ops inode_lvbo = { .lvbo_free = mdc_resource_inode_free, }; @@ -2550,9 +2550,9 @@ static int mdc_process_config(struct obd_device *obd, u32 len, void *buf) /* get remote permission for current user on fid */ -int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid, - struct obd_capa *oc, __u32 suppgid, - struct ptlrpc_request **request) +static int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid, + struct obd_capa *oc, __u32 suppgid, + struct ptlrpc_request **request) { struct ptlrpc_request *req; int rc; @@ -2647,7 +2647,7 @@ static int mdc_renew_capa(struct obd_export *exp, struct obd_capa *oc, return 0; } -struct obd_ops mdc_obd_ops = { +static struct obd_ops mdc_obd_ops = { .o_owner = THIS_MODULE, .o_setup = mdc_setup, .o_precleanup = mdc_precleanup, @@ -2670,7 +2670,7 @@ struct obd_ops mdc_obd_ops = { .o_quotacheck = mdc_quotacheck }; -struct md_ops mdc_md_ops = { +static struct md_ops mdc_md_ops = { .m_getstatus = mdc_getstatus, .m_null_inode = mdc_null_inode, .m_find_cbdata = mdc_find_cbdata, @@ -2705,7 +2705,7 @@ struct md_ops mdc_md_ops = { .m_revalidate_lock = mdc_revalidate_lock }; -int __init mdc_init(void) +static int __init mdc_init(void) { int rc; struct lprocfs_static_vars lvars = { NULL }; -- cgit v0.10.2 From 5dc8d7b43673f64b1dcc1e3bd7cff1a4ea1e5394 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Sun, 18 Jan 2015 15:06:48 +0100 Subject: staging: lustre: lmv: declare internal symbols as static Fixes sparse warnings like: warning: symbol '...' was not declared. Should it be static? Signed-off-by: Luca Ceresoli Cc: Peng Tao Cc: Jinshan Xiong Cc: Srikrishan Malik Cc: HPDD-discuss@lists.01.org Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 9f38374..b779f47 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -128,7 +128,7 @@ static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid, return rc; } -struct obd_uuid *lmv_get_uuid(struct obd_export *exp) +static struct obd_uuid *lmv_get_uuid(struct obd_export *exp) { struct lmv_obd *lmv = &exp->exp_obd->u.lmv; @@ -335,7 +335,7 @@ static int lmv_init_ea_size(struct obd_export *exp, int easize, #define MAX_STRING_SIZE 128 -int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) +static int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) { struct proc_dir_entry *lmv_proc_dir; struct lmv_obd *lmv = &obd->u.lmv; @@ -1663,10 +1663,10 @@ struct lmv_tgt_desc return tgt; } -int lmv_create(struct obd_export *exp, struct md_op_data *op_data, - const void *data, int datalen, int mode, __u32 uid, - __u32 gid, cfs_cap_t cap_effective, __u64 rdev, - struct ptlrpc_request **request) +static int lmv_create(struct obd_export *exp, struct md_op_data *op_data, + const void *data, int datalen, int mode, __u32 uid, + __u32 gid, cfs_cap_t cap_effective, __u64 rdev, + struct ptlrpc_request **request) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2387,9 +2387,9 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp, return -EINVAL; } -int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, - u32 keylen, void *key, u32 vallen, - void *val, struct ptlrpc_request_set *set) +static int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, + u32 keylen, void *key, u32 vallen, + void *val, struct ptlrpc_request_set *set) { struct lmv_tgt_desc *tgt; struct obd_device *obd; @@ -2425,8 +2425,8 @@ int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, return -EINVAL; } -int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, - struct lov_stripe_md *lsm) +static int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, + struct lov_stripe_md *lsm) { struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; @@ -2473,8 +2473,8 @@ int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, return mea_size; } -int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, - struct lov_mds_md *lmm, int lmm_size) +static int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, + struct lov_mds_md *lmm, int lmm_size) { struct obd_device *obd = class_exp2obd(exp); struct lmv_stripe_md **tmea = (struct lmv_stripe_md **)lsmp; @@ -2551,8 +2551,8 @@ static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid, return rc; } -int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, - __u64 *bits) +static int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, + __u64 *bits) { struct lmv_obd *lmv = &exp->exp_obd->u.lmv; int rc; @@ -2561,10 +2561,10 @@ int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, return rc; } -ldlm_mode_t lmv_lock_match(struct obd_export *exp, __u64 flags, - const struct lu_fid *fid, ldlm_type_t type, - ldlm_policy_data_t *policy, ldlm_mode_t mode, - struct lustre_handle *lockh) +static ldlm_mode_t lmv_lock_match(struct obd_export *exp, __u64 flags, + const struct lu_fid *fid, ldlm_type_t type, + ldlm_policy_data_t *policy, ldlm_mode_t mode, + struct lustre_handle *lockh) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2594,16 +2594,18 @@ ldlm_mode_t lmv_lock_match(struct obd_export *exp, __u64 flags, return 0; } -int lmv_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req, - struct obd_export *dt_exp, struct obd_export *md_exp, - struct lustre_md *md) +static int lmv_get_lustre_md(struct obd_export *exp, + struct ptlrpc_request *req, + struct obd_export *dt_exp, + struct obd_export *md_exp, + struct lustre_md *md) { struct lmv_obd *lmv = &exp->exp_obd->u.lmv; return md_get_lustre_md(lmv->tgts[0]->ltd_exp, req, dt_exp, md_exp, md); } -int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md) +static int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2613,9 +2615,9 @@ int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md) return md_free_lustre_md(lmv->tgts[0]->ltd_exp, md); } -int lmv_set_open_replay_data(struct obd_export *exp, - struct obd_client_handle *och, - struct lookup_intent *it) +static int lmv_set_open_replay_data(struct obd_export *exp, + struct obd_client_handle *och, + struct lookup_intent *it) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2628,8 +2630,8 @@ int lmv_set_open_replay_data(struct obd_export *exp, return md_set_open_replay_data(tgt->ltd_exp, och, it); } -int lmv_clear_open_replay_data(struct obd_export *exp, - struct obd_client_handle *och) +static int lmv_clear_open_replay_data(struct obd_export *exp, + struct obd_client_handle *och) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2684,17 +2686,18 @@ static int lmv_renew_capa(struct obd_export *exp, struct obd_capa *oc, return rc; } -int lmv_unpack_capa(struct obd_export *exp, struct ptlrpc_request *req, - const struct req_msg_field *field, struct obd_capa **oc) +static int lmv_unpack_capa(struct obd_export *exp, struct ptlrpc_request *req, + const struct req_msg_field *field, + struct obd_capa **oc) { struct lmv_obd *lmv = &exp->exp_obd->u.lmv; return md_unpack_capa(lmv->tgts[0]->ltd_exp, req, field, oc); } -int lmv_intent_getattr_async(struct obd_export *exp, - struct md_enqueue_info *minfo, - struct ldlm_enqueue_info *einfo) +static int lmv_intent_getattr_async(struct obd_export *exp, + struct md_enqueue_info *minfo, + struct ldlm_enqueue_info *einfo) { struct md_op_data *op_data = &minfo->mi_data; struct obd_device *obd = exp->exp_obd; @@ -2714,8 +2717,8 @@ int lmv_intent_getattr_async(struct obd_export *exp, return rc; } -int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, - struct lu_fid *fid, __u64 *bits) +static int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, + struct lu_fid *fid, __u64 *bits) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; @@ -2739,8 +2742,8 @@ int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, * process with other slave MDTs. The only exception is Q_GETOQUOTA for which * we directly fetch data from the slave MDTs. */ -int lmv_quotactl(struct obd_device *unused, struct obd_export *exp, - struct obd_quotactl *oqctl) +static int lmv_quotactl(struct obd_device *unused, struct obd_export *exp, + struct obd_quotactl *oqctl) { struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; @@ -2786,8 +2789,8 @@ int lmv_quotactl(struct obd_device *unused, struct obd_export *exp, return rc; } -int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, - struct obd_quotactl *oqctl) +static int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, + struct obd_quotactl *oqctl) { struct obd_device *obd = class_exp2obd(exp); struct lmv_obd *lmv = &obd->u.lmv; @@ -2810,7 +2813,7 @@ int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, return rc; } -struct obd_ops lmv_obd_ops = { +static struct obd_ops lmv_obd_ops = { .o_owner = THIS_MODULE, .o_setup = lmv_setup, .o_cleanup = lmv_cleanup, @@ -2830,7 +2833,7 @@ struct obd_ops lmv_obd_ops = { .o_quotactl = lmv_quotactl }; -struct md_ops lmv_md_ops = { +static struct md_ops lmv_md_ops = { .m_getstatus = lmv_getstatus, .m_null_inode = lmv_null_inode, .m_find_cbdata = lmv_find_cbdata, @@ -2864,7 +2867,7 @@ struct md_ops lmv_md_ops = { .m_revalidate_lock = lmv_revalidate_lock }; -int __init lmv_init(void) +static int __init lmv_init(void) { struct lprocfs_static_vars lvars; int rc; diff --git a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c index 1170020..5be4176 100644 --- a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c +++ b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c @@ -175,7 +175,7 @@ static int lmv_tgt_seq_show(struct seq_file *p, void *v) tgt->ltd_uuid.uuid, tgt->ltd_active ? "" : "IN"); } -struct seq_operations lmv_tgt_sops = { +static struct seq_operations lmv_tgt_sops = { .start = lmv_tgt_seq_start, .stop = lmv_tgt_seq_stop, .next = lmv_tgt_seq_next, @@ -199,7 +199,7 @@ static int lmv_target_seq_open(struct inode *inode, struct file *file) LPROC_SEQ_FOPS_RO_TYPE(lmv, uuid); -struct lprocfs_vars lprocfs_lmv_obd_vars[] = { +static struct lprocfs_vars lprocfs_lmv_obd_vars[] = { { "numobd", &lmv_numobd_fops, NULL, 0 }, { "placement", &lmv_placement_fops, NULL, 0 }, { "activeobd", &lmv_activeobd_fops, NULL, 0 }, -- cgit v0.10.2 From 2a74b9bda64be239745ec146de3e1dc1ad2abd82 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Sun, 18 Jan 2015 15:06:49 +0100 Subject: staging: lustre: libcfs: declare internal symbols as static Fixes sparse warnings like: warning: symbol '...' was not declared. Should it be static? Signed-off-by: Luca Ceresoli Cc: Peng Tao Cc: Jinshan Xiong Cc: Srikrishan Malik Cc: HPDD-discuss@lists.01.org Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/debug.c b/drivers/staging/lustre/lustre/libcfs/debug.c index a7a7ac6..7170088 100644 --- a/drivers/staging/lustre/lustre/libcfs/debug.c +++ b/drivers/staging/lustre/lustre/libcfs/debug.c @@ -115,7 +115,7 @@ static wait_queue_head_t debug_ctlwq; char libcfs_debug_file_path_arr[PATH_MAX] = LIBCFS_DEBUG_FILE_PATH_DEFAULT; /* We need to pass a pointer here, but elsewhere this must be a const */ -char *libcfs_debug_file_path; +static char *libcfs_debug_file_path; module_param(libcfs_debug_file_path, charp, 0644); MODULE_PARM_DESC(libcfs_debug_file_path, "Path for dumping debug logs, set 'NONE' to prevent log dumping"); @@ -124,7 +124,7 @@ int libcfs_panic_in_progress; /* libcfs_debug_token2mask() expects the returned * string in lower-case */ -const char * +static const char * libcfs_debug_subsys2str(int subsys) { switch (1 << subsys) { @@ -185,7 +185,7 @@ libcfs_debug_subsys2str(int subsys) /* libcfs_debug_token2mask() expects the returned * string in lower-case */ -const char * +static const char * libcfs_debug_dbg2str(int debug) { switch (1 << debug) { @@ -350,7 +350,7 @@ void libcfs_debug_dumplog_internal(void *arg) current->journal_info = journal_info; } -int libcfs_debug_dumplog_thread(void *arg) +static int libcfs_debug_dumplog_thread(void *arg) { libcfs_debug_dumplog_internal(arg); wake_up(&debug_ctlwq); diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c index 9515347..277f6b8 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c @@ -82,7 +82,7 @@ int cfs_cap_raised(cfs_cap_t cap) return cap_raised(current_cap(), cap); } -void cfs_kernel_cap_pack(kernel_cap_t kcap, cfs_cap_t *cap) +static void cfs_kernel_cap_pack(kernel_cap_t kcap, cfs_cap_t *cap) { /* XXX lost high byte */ *cap = kcap.cap[0]; diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c index 83d3f08..c539e37 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c @@ -232,8 +232,9 @@ static int proc_debug_mb(struct ctl_table *table, int write, __proc_debug_mb); } -int proc_console_max_delay_cs(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) +static int proc_console_max_delay_cs(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) { int rc, max_delay_cs; struct ctl_table dummy = *table; @@ -264,8 +265,9 @@ int proc_console_max_delay_cs(struct ctl_table *table, int write, return rc; } -int proc_console_min_delay_cs(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) +static int proc_console_min_delay_cs(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) { int rc, min_delay_cs; struct ctl_table dummy = *table; @@ -296,8 +298,8 @@ int proc_console_min_delay_cs(struct ctl_table *table, int write, return rc; } -int proc_console_backoff(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) +static int proc_console_backoff(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) { int rc, backoff; struct ctl_table dummy = *table; @@ -324,16 +326,18 @@ int proc_console_backoff(struct ctl_table *table, int write, return rc; } -int libcfs_force_lbug(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int libcfs_force_lbug(struct ctl_table *table, int write, + void __user *buffer, + size_t *lenp, loff_t *ppos) { if (write) LBUG(); return 0; } -int proc_fail_loc(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int proc_fail_loc(struct ctl_table *table, int write, + void __user *buffer, + size_t *lenp, loff_t *ppos) { int rc; long old_fail_loc = cfs_fail_loc; diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c index b91a1f9..cd2fc01 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c @@ -43,7 +43,7 @@ /* For sys_open & sys_close */ #include -int +static int libcfs_sock_ioctl(int cmd, unsigned long arg) { mm_segment_t oldmm = get_fs(); diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.c b/drivers/staging/lustre/lustre/libcfs/tracefile.c index 5917c31..d18de04 100644 --- a/drivers/staging/lustre/lustre/libcfs/tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/tracefile.c @@ -55,7 +55,7 @@ static struct tracefiled_ctl trace_tctl; struct mutex cfs_trace_thread_mutex; static int thread_running = 0; -atomic_t cfs_tage_allocated = ATOMIC_INIT(0); +static atomic_t cfs_tage_allocated = ATOMIC_INIT(0); static void put_pages_on_tcd_daemon_list(struct page_collection *pc, struct cfs_trace_cpu_data *tcd); -- cgit v0.10.2 From 920b4f2eca925559d6a873e6bc695fa6c627321e Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Sun, 18 Jan 2015 15:06:50 +0100 Subject: staging: lustre: llite: declare internal symbols as static Fixes sparse warnings like: warning: symbol '...' was not declared. Should it be static? Signed-off-by: Luca Ceresoli Cc: Peng Tao Cc: Jinshan Xiong Cc: Srikrishan Malik Cc: HPDD-discuss@lists.01.org Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 1ac7a70..babba60 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -652,8 +652,8 @@ static int ll_send_mgc_param(struct obd_export *mgc, char *string) return rc; } -int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump, - char *filename) +static int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump, + char *filename) { struct ptlrpc_request *request = NULL; struct md_op_data *op_data; diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 35a2df0..ca270f4 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1587,7 +1587,8 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) return 0; } -int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg) +static int ll_put_grouplock(struct inode *inode, struct file *file, + unsigned long arg) { struct ll_inode_info *lli = ll_i2info(inode); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); -- cgit v0.10.2 From 02a7b84301da547e63a234bf80e45cae780a6ac0 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Sun, 18 Jan 2015 15:06:51 +0100 Subject: staging: lustre: fld: declare internal symbols as static Fixes sparse warnings like: warning: symbol '...' was not declared. Should it be static? Signed-off-by: Luca Ceresoli Cc: Peng Tao Cc: Jinshan Xiong Cc: Srikrishan Malik Cc: HPDD-discuss@lists.01.org Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c index 5d95d0b..0d0a737 100644 --- a/drivers/staging/lustre/lustre/fld/fld_cache.c +++ b/drivers/staging/lustre/lustre/fld/fld_cache.c @@ -257,9 +257,9 @@ void fld_cache_flush(struct fld_cache *cache) * entry accordingly. */ -void fld_cache_punch_hole(struct fld_cache *cache, - struct fld_cache_entry *f_curr, - struct fld_cache_entry *f_new) +static void fld_cache_punch_hole(struct fld_cache *cache, + struct fld_cache_entry *f_curr, + struct fld_cache_entry *f_new) { const struct lu_seq_range *range = &f_new->fce_range; const u64 new_start = range->lsr_start; diff --git a/drivers/staging/lustre/lustre/fld/lproc_fld.c b/drivers/staging/lustre/lustre/fld/lproc_fld.c index 9b26bb5..8c5a657 100644 --- a/drivers/staging/lustre/lustre/fld/lproc_fld.c +++ b/drivers/staging/lustre/lustre/fld/lproc_fld.c @@ -154,7 +154,7 @@ static int fld_proc_cache_flush_release(struct inode *inode, struct file *file) return 0; } -struct file_operations fld_proc_cache_flush_fops = { +static struct file_operations fld_proc_cache_flush_fops = { .owner = THIS_MODULE, .open = fld_proc_cache_flush_open, .write = fld_proc_cache_flush_write, -- cgit v0.10.2 From f3731cdb23bd0a4c982346a90a466c59b0dee10d Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Sun, 18 Jan 2015 15:06:52 +0100 Subject: staging: lustre: lnet: declare internal symbols as static Fixes sparse warnings like: warning: symbol '...' was not declared. Should it be static? Signed-off-by: Luca Ceresoli Cc: Peng Tao Cc: Jinshan Xiong Cc: Srikrishan Malik Cc: HPDD-discuss@lists.01.org Cc: devel@driverdev.osuosl.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/lnet/module.c b/drivers/staging/lustre/lnet/lnet/module.c index 3c23677..72b7fbc 100644 --- a/drivers/staging/lustre/lnet/lnet/module.c +++ b/drivers/staging/lustre/lnet/lnet/module.c @@ -108,7 +108,7 @@ lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_data *data) } } -DECLARE_IOCTL_HANDLER(lnet_ioctl_handler, lnet_ioctl); +static DECLARE_IOCTL_HANDLER(lnet_ioctl_handler, lnet_ioctl); static int __init init_lnet(void) diff --git a/drivers/staging/lustre/lnet/selftest/conctl.c b/drivers/staging/lustre/lnet/selftest/conctl.c index 5bc6153..fbff84c 100644 --- a/drivers/staging/lustre/lnet/selftest/conctl.c +++ b/drivers/staging/lustre/lnet/selftest/conctl.c @@ -721,7 +721,7 @@ lst_stat_query_ioctl(lstio_stat_args_t *args) return rc; } -int lst_test_add_ioctl(lstio_test_args_t *args) +static int lst_test_add_ioctl(lstio_test_args_t *args) { char *batch_name; char *src_name = NULL; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 9999b0d..77f02b7 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -703,7 +703,7 @@ lstcon_statrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc) return 0; } -lnet_process_id_packed_t * +static lnet_process_id_packed_t * lstcon_next_id(int idx, int nkiov, lnet_kiov_t *kiov) { lnet_process_id_packed_t *pid; diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 49cb654..3bb47fa 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -1986,7 +1986,7 @@ static void lstcon_init_acceptor_service(void) extern int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_data *data); -DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry); +static DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry); /* initialize console */ int -- cgit v0.10.2 From f8bd34d21622c4550179aeb28715c2fd35e82451 Mon Sep 17 00:00:00 2001 From: Loic Pefferkorn Date: Tue, 20 Jan 2015 20:39:11 +0100 Subject: staging: lustre: fix sparse warnings related to lock context imbalance Applies against next-20150120. Add __acquires() and __releases() function annotations, to fix sparse warnings related to lock context imbalance. This patch fixes the following warnings: drivers/staging/lustre//lustre/libcfs/linux/linux-tracefile.c:153:5: warning: context imbalance in 'cfs_trace_lock_tcd' - wrong count at exit drivers/staging/lustre//lustre/libcfs/linux/linux-tracefile.c:171:39: warning: context imbalance in 'cfs_trace_unlock_tcd' - unexpected unlock drivers/staging/lustre//lustre/libcfs/hash.c:128:1: warning: context imbalance in 'cfs_hash_spin_lock' - wrong count at exit drivers/staging/lustre//lustre/libcfs/hash.c:134:1: warning: context imbalance in 'cfs_hash_spin_unlock' - unexpected unlock drivers/staging/lustre//lustre/libcfs/hash.c:142:9: warning: context imbalance in 'cfs_hash_rw_lock' - wrong count at exit include/linux/rwlock_api_smp.h:219:9: warning: context imbalance in 'cfs_hash_rw_unlock' - unexpected unlock drivers/staging/lustre//lustre/obdclass/cl_object.c:195:6: warning: context imbalance in 'cl_object_attr_lock' - wrong count at exit drivers/staging/lustre//lustre/obdclass/cl_object.c:204:6: warning: context imbalance in 'cl_object_attr_unlock' - unexpected unlock Signed-off-by: Loic Pefferkorn Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/hash.c b/drivers/staging/lustre/lustre/libcfs/hash.c index 2d1e672..d89f81a 100644 --- a/drivers/staging/lustre/lustre/libcfs/hash.c +++ b/drivers/staging/lustre/lustre/libcfs/hash.c @@ -126,18 +126,21 @@ cfs_hash_nl_unlock(union cfs_hash_lock *lock, int exclusive) {} static inline void cfs_hash_spin_lock(union cfs_hash_lock *lock, int exclusive) + __acquires(&lock->spin) { spin_lock(&lock->spin); } static inline void cfs_hash_spin_unlock(union cfs_hash_lock *lock, int exclusive) + __releases(&lock->spin) { spin_unlock(&lock->spin); } static inline void cfs_hash_rw_lock(union cfs_hash_lock *lock, int exclusive) + __acquires(&lock->rw) { if (!exclusive) read_lock(&lock->rw); @@ -147,6 +150,7 @@ cfs_hash_rw_lock(union cfs_hash_lock *lock, int exclusive) static inline void cfs_hash_rw_unlock(union cfs_hash_lock *lock, int exclusive) + __releases(&lock->rw) { if (!exclusive) read_unlock(&lock->rw); diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c index fdc7189..c8e2930 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c @@ -151,6 +151,7 @@ cfs_trace_buf_type_t cfs_trace_buf_idx_get(void) * for details. */ int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking) + __acquires(&tcd->tc_lock) { __LASSERT(tcd->tcd_type < CFS_TCD_TYPE_MAX); if (tcd->tcd_type == CFS_TCD_TYPE_IRQ) @@ -165,6 +166,7 @@ int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking) } void cfs_trace_unlock_tcd(struct cfs_trace_cpu_data *tcd, int walking) + __releases(&tcd->tcd_lock) { __LASSERT(tcd->tcd_type < CFS_TCD_TYPE_MAX); if (tcd->tcd_type == CFS_TCD_TYPE_IRQ) diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index c40bb6c..f13d1fb 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -193,6 +193,7 @@ static spinlock_t *cl_object_attr_guard(struct cl_object *o) * cl_object_attr_get(), cl_object_attr_set(). */ void cl_object_attr_lock(struct cl_object *o) + __acquires(cl_object_attr_guard(o)) { spin_lock(cl_object_attr_guard(o)); } @@ -202,6 +203,7 @@ EXPORT_SYMBOL(cl_object_attr_lock); * Releases data-attributes lock, acquired by cl_object_attr_lock(). */ void cl_object_attr_unlock(struct cl_object *o) + __releases(cl_object_attr_guard(o)) { spin_unlock(cl_object_attr_guard(o)); } -- cgit v0.10.2 From 052f4f61ecb14119709f928984c347ef6a2ec35c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 22 Jan 2015 10:49:54 +0300 Subject: staging: lustre: remove the CFS_HOP() macro CFS_HOP() is a terrible macro. It chops the struct member name in half so that it's not possible to use tools like grep or to search for how a function pointer is used. I removed a couple calls to: LASSERT(CFS_HOP(hs, put_locked) != NULL); because they isn't a need for them. Anyway dereferencing a NULL pointer generates a pretty good stack trace already without adding extra debug code. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h index 375586b..808e494 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_hash.h @@ -454,25 +454,23 @@ cfs_hash_bkt_size(struct cfs_hash *hs) hs->hs_extra_bytes; } -#define CFS_HOP(hs, op) (hs)->hs_ops->hs_ ## op - static inline unsigned cfs_hash_id(struct cfs_hash *hs, const void *key, unsigned mask) { - return CFS_HOP(hs, hash)(hs, key, mask); + return hs->hs_ops->hs_hash(hs, key, mask); } static inline void * cfs_hash_key(struct cfs_hash *hs, struct hlist_node *hnode) { - return CFS_HOP(hs, key)(hnode); + return hs->hs_ops->hs_key(hnode); } static inline void cfs_hash_keycpy(struct cfs_hash *hs, struct hlist_node *hnode, void *key) { - if (CFS_HOP(hs, keycpy) != NULL) - CFS_HOP(hs, keycpy)(hnode, key); + if (hs->hs_ops->hs_keycpy) + hs->hs_ops->hs_keycpy(hnode, key); } /** @@ -481,42 +479,38 @@ cfs_hash_keycpy(struct cfs_hash *hs, struct hlist_node *hnode, void *key) static inline int cfs_hash_keycmp(struct cfs_hash *hs, const void *key, struct hlist_node *hnode) { - return CFS_HOP(hs, keycmp)(key, hnode); + return hs->hs_ops->hs_keycmp(key, hnode); } static inline void * cfs_hash_object(struct cfs_hash *hs, struct hlist_node *hnode) { - return CFS_HOP(hs, object)(hnode); + return hs->hs_ops->hs_object(hnode); } static inline void cfs_hash_get(struct cfs_hash *hs, struct hlist_node *hnode) { - return CFS_HOP(hs, get)(hs, hnode); + return hs->hs_ops->hs_get(hs, hnode); } static inline void cfs_hash_put_locked(struct cfs_hash *hs, struct hlist_node *hnode) { - LASSERT(CFS_HOP(hs, put_locked) != NULL); - - return CFS_HOP(hs, put_locked)(hs, hnode); + return hs->hs_ops->hs_put_locked(hs, hnode); } static inline void cfs_hash_put(struct cfs_hash *hs, struct hlist_node *hnode) { - LASSERT(CFS_HOP(hs, put) != NULL); - - return CFS_HOP(hs, put)(hs, hnode); + return hs->hs_ops->hs_put(hs, hnode); } static inline void cfs_hash_exit(struct cfs_hash *hs, struct hlist_node *hnode) { - if (CFS_HOP(hs, exit)) - CFS_HOP(hs, exit)(hs, hnode); + if (hs->hs_ops->hs_exit) + hs->hs_ops->hs_exit(hs, hnode); } static inline void cfs_hash_lock(struct cfs_hash *hs, int excl) diff --git a/drivers/staging/lustre/lustre/libcfs/hash.c b/drivers/staging/lustre/lustre/libcfs/hash.c index d89f81a..ec3a2a8 100644 --- a/drivers/staging/lustre/lustre/libcfs/hash.c +++ b/drivers/staging/lustre/lustre/libcfs/hash.c @@ -1584,7 +1584,7 @@ cfs_hash_for_each_relax(struct cfs_hash *hs, cfs_hash_for_each_cb_t func, stop_on_change = cfs_hash_with_rehash_key(hs) || !cfs_hash_with_no_itemref(hs) || - CFS_HOP(hs, put_locked) == NULL; + hs->hs_ops->hs_put_locked == NULL; cfs_hash_lock(hs, 0); LASSERT(!cfs_hash_is_rehashing(hs)); @@ -1639,9 +1639,9 @@ cfs_hash_for_each_nolock(struct cfs_hash *hs, !cfs_hash_with_no_itemref(hs)) return -EOPNOTSUPP; - if (CFS_HOP(hs, get) == NULL || - (CFS_HOP(hs, put) == NULL && - CFS_HOP(hs, put_locked) == NULL)) + if (hs->hs_ops->hs_get == NULL || + (hs->hs_ops->hs_put == NULL && + hs->hs_ops->hs_put_locked == NULL)) return -EOPNOTSUPP; cfs_hash_for_each_enter(hs); @@ -1671,9 +1671,9 @@ cfs_hash_for_each_empty(struct cfs_hash *hs, if (cfs_hash_with_no_lock(hs)) return -EOPNOTSUPP; - if (CFS_HOP(hs, get) == NULL || - (CFS_HOP(hs, put) == NULL && - CFS_HOP(hs, put_locked) == NULL)) + if (hs->hs_ops->hs_get == NULL || + (hs->hs_ops->hs_put == NULL && + hs->hs_ops->hs_put_locked == NULL)) return -EOPNOTSUPP; cfs_hash_for_each_enter(hs); -- cgit v0.10.2 From b3c986d3c17983e8a04d2660bc92037d753c3dd7 Mon Sep 17 00:00:00 2001 From: Jon Bernard Date: Tue, 20 Jan 2015 14:55:28 -0500 Subject: staging: lustre: ptlrpc: fix lproc_ptlrpc static declarations This patch fixes the following sparse warnings: drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c:51:3:warning: symbol 'll_rpc_opcode_table' was not declared. Should it be static? drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c:142:3: warning: symbol 'll_eopcode_table' was not declared. Should it be static? drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c:178:12: warning: symbol 'll_eopcode2str' was not declared. Should it be static? drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c:731:1: warning: symbol 'ptlrpc_lprocfs_svc_req_history_seek' was not declared. Should it be static? Signed-off-by: Jon Bernard Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index 90448e9..0e2071b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -45,7 +45,7 @@ #include "ptlrpc_internal.h" -struct ll_rpc_opcode { +static struct ll_rpc_opcode { __u32 opcode; const char *opname; } ll_rpc_opcode_table[LUSTRE_MAX_OPCODES] = { @@ -136,7 +136,7 @@ struct ll_rpc_opcode { { UPDATE_OBJ, "update_obj" }, }; -struct ll_eopcode { +static struct ll_eopcode { __u32 opcode; const char *opname; } ll_eopcode_table[EXTRA_LAST_OPC] = { @@ -175,11 +175,12 @@ const char *ll_opcode2str(__u32 opcode) return ll_rpc_opcode_table[offset].opname; } -const char *ll_eopcode2str(__u32 opcode) +static const char *ll_eopcode2str(__u32 opcode) { LASSERT(ll_eopcode_table[opcode].opcode == opcode); return ll_eopcode_table[opcode].opname; } + #if defined (CONFIG_PROC_FS) static void ptlrpc_lprocfs_register(struct proc_dir_entry *root, char *dir, char *name, @@ -727,7 +728,7 @@ struct ptlrpc_srh_iterator { struct ptlrpc_request *srhi_req; }; -int +static int ptlrpc_lprocfs_svc_req_history_seek(struct ptlrpc_service_part *svcpt, struct ptlrpc_srh_iterator *srhi, __u64 seq) -- cgit v0.10.2 From 074e6fd13377e78e788fbcf986a887d460ea8b39 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 23 Jan 2015 17:20:25 +0300 Subject: staging: fbtft: fix allyesconfig build There are two functions call reset() so the allyesconfig breaks. Let's make this one static. Reported-by: Jim Davis Signed-off-by: Dan Carpenter Tested-by: Jim Davis Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c index 7fe4fa0..9cc7d25 100644 --- a/drivers/staging/fbtft/fb_agm1264k-fl.c +++ b/drivers/staging/fbtft/fb_agm1264k-fl.c @@ -89,7 +89,7 @@ static int init_display(struct fbtft_par *par) return 0; } -void reset(struct fbtft_par *par) +static void reset(struct fbtft_par *par) { if (par->gpio.reset == -1) return; -- cgit v0.10.2 From 75b4d52bae59aba0e4cd28bd88a42680d270ea6b Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Mon, 19 Jan 2015 12:16:30 +0200 Subject: staging: vt6655: fix space prohibited before that ',' This patch fixes the following checkpatch.pl error: fix space prohibited before that ',' Signed-off-by: Heba Aamer Reviewed-by: Aya Mahfouz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 63c9c7e..3653a2b 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -789,7 +789,7 @@ bool MACbPSWakeup(void __iomem *dwIoBase) // Check if SyncFlushOK for (ww = 0; ww < W_MAX_TIMEOUT; ww++) { - VNSvInPortB(dwIoBase + MAC_REG_PSCTL , &byOrgValue); + VNSvInPortB(dwIoBase + MAC_REG_PSCTL, &byOrgValue); if (byOrgValue & PSCTL_WAKEDONE) break; } -- cgit v0.10.2 From 2a0a7b3dfa888bf578486e352efd7eb5ce4aed87 Mon Sep 17 00:00:00 2001 From: Ahmad Hassan Date: Mon, 19 Jan 2015 13:13:58 -0900 Subject: staging: vt6655: fix space prohibted before that ',' This patch fixes the following checkpatch.pl error: fix space prohibited before that ',' Signed-off-by: Ahmad Hassan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index c755ec2..e5ed9e6 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1090,7 +1090,7 @@ static irqreturn_t device_intr(int irq, void *dev_instance) // Must do this after doing rx/tx, cause ISR bit is slow // than RD/TD write back // update ISR counter - STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic , dwMIBCounter); + STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic, dwMIBCounter); while (pDevice->dwIsr != 0) { STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr); MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr); -- cgit v0.10.2 From d7a4cfa8c18c5622da0bf87661963e13cc3de9b0 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 19 Jan 2015 18:24:10 +0000 Subject: staging: vt6655: set_channel replace parameter with ieee80211_channel replacing uConnectionChannel for hw_value as set in vnt_init_bands. This allows other signaling of ieee80211_channel to move deeper into driver. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index d593f5f..3fc09f4 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -174,12 +174,12 @@ void vnt_init_bands(struct vnt_private *priv) * Return Value: true if succeeded; false if failed. * */ -bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel) +bool set_channel(void *pDeviceHandler, struct ieee80211_channel *ch) { struct vnt_private *pDevice = pDeviceHandler; bool bResult = true; - if (pDevice->byCurrentCh == uConnectionChannel) + if (pDevice->byCurrentCh == ch->hw_value) return bResult; /* Set VGA to max sensitivity */ @@ -197,15 +197,15 @@ bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel) if (pDevice->byRFType == RF_AIROHA7230) RFbAL7230SelectChannelPostProcess(pDevice, pDevice->byCurrentCh, - (unsigned char)uConnectionChannel); + (unsigned char)ch->hw_value); - pDevice->byCurrentCh = (unsigned char)uConnectionChannel; + pDevice->byCurrentCh = (unsigned char)ch->hw_value; bResult &= RFbSelectChannel(pDevice, pDevice->byRFType, - (unsigned char)uConnectionChannel); + (unsigned char)ch->hw_value); /* Init Synthesizer Table */ if (pDevice->bEnablePSMode) - RFvWriteWakeProgSyn(pDevice, pDevice->byRFType, uConnectionChannel); + RFvWriteWakeProgSyn(pDevice, pDevice->byRFType, ch->hw_value); BBvSoftwareReset(pDevice); diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h index 4f4264e..e2be6fc 100644 --- a/drivers/staging/vt6655/channel.h +++ b/drivers/staging/vt6655/channel.h @@ -27,6 +27,6 @@ void vnt_init_bands(struct vnt_private *); -bool set_channel(void *pDeviceHandler, unsigned int uConnectionChannel); +bool set_channel(void *pDeviceHandler, struct ieee80211_channel *); #endif /* _CHANNEL_H_ */ diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index e5ed9e6..05be34b 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1420,7 +1420,7 @@ static int vnt_config(struct ieee80211_hw *hw, u32 changed) if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || (conf->flags & IEEE80211_CONF_OFFCHANNEL)) { - set_channel(priv, conf->chandef.chan->hw_value); + set_channel(priv, conf->chandef.chan); if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) bb_type = BB_TYPE_11A; -- cgit v0.10.2 From 63e8d787b0bbfc9bfca6d7ecdeb6548e6baa6f9e Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 19 Jan 2015 18:24:11 +0000 Subject: staging: vt6655: common variable size channel numbers to ieee80211_channel->hw_value hw_value is u16 so fix all to the same size. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index 3fc09f4..3c17725 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -197,11 +197,11 @@ bool set_channel(void *pDeviceHandler, struct ieee80211_channel *ch) if (pDevice->byRFType == RF_AIROHA7230) RFbAL7230SelectChannelPostProcess(pDevice, pDevice->byCurrentCh, - (unsigned char)ch->hw_value); + ch->hw_value); - pDevice->byCurrentCh = (unsigned char)ch->hw_value; + pDevice->byCurrentCh = ch->hw_value; bResult &= RFbSelectChannel(pDevice, pDevice->byRFType, - (unsigned char)ch->hw_value); + ch->hw_value); /* Init Synthesizer Table */ if (pDevice->bEnablePSMode) diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 83efbfb..96d8e62 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -367,7 +367,7 @@ struct vnt_private { bool bIsBeaconBufReadySet; unsigned int cbBeaconBufReadySetCnt; bool bFixRate; - unsigned char byCurrentCh; + u16 byCurrentCh; bool bAES; diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 32ef993..27841aa 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -651,7 +651,8 @@ bool RFbInit( * Return Value: true if succeeded; false if failed. * */ -bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, unsigned char byChannel) +bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, + u16 byChannel) { bool bResult = true; @@ -687,7 +688,8 @@ bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, unsigned * Return Value: None. * */ -bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, unsigned int uChannel) +bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, + u16 uChannel) { void __iomem *dwIoBase = priv->PortOffset; int ii; @@ -767,7 +769,7 @@ bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, unsig bool RFbSetPower( struct vnt_private *priv, unsigned int uRATE, - unsigned int uCH + u16 uCH ) { bool bResult = true; @@ -937,8 +939,8 @@ RFvRSSITodBm( /* Post processing for the 11b/g and 11a. * for save time on changing Reg2,3,5,7,10,12,15 */ bool RFbAL7230SelectChannelPostProcess(struct vnt_private *priv, - unsigned char byOldChannel, - unsigned char byNewChannel) + u16 byOldChannel, + u16 byNewChannel) { bool bResult; diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h index 8a6e2cf..2ea21e2 100644 --- a/drivers/staging/vt6655/rf.h +++ b/drivers/staging/vt6655/rf.h @@ -74,12 +74,12 @@ /*--------------------- Export Functions --------------------------*/ bool IFRFbWriteEmbedded(struct vnt_private *, unsigned long dwData); -bool RFbSelectChannel(struct vnt_private *, unsigned char byRFType, unsigned char byChannel); +bool RFbSelectChannel(struct vnt_private *, unsigned char byRFType, u16); bool RFbInit( struct vnt_private * ); -bool RFvWriteWakeProgSyn(struct vnt_private *, unsigned char byRFType, unsigned int uChannel); -bool RFbSetPower(struct vnt_private *, unsigned int uRATE, unsigned int uCH); +bool RFvWriteWakeProgSyn(struct vnt_private *, unsigned char byRFType, u16); +bool RFbSetPower(struct vnt_private *, unsigned int uRATE, u16); bool RFbRawSetPower( struct vnt_private *, unsigned char byPwr, @@ -94,7 +94,7 @@ RFvRSSITodBm( ); //{{ RobertYu: 20050104 -bool RFbAL7230SelectChannelPostProcess(struct vnt_private *, unsigned char byOldChannel, unsigned char byNewChannel); +bool RFbAL7230SelectChannelPostProcess(struct vnt_private *, u16, u16); //}} RobertYu #endif // __RF_H__ -- cgit v0.10.2 From e6f534bc2fbda029ddc43d816151893454224e52 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 19 Jan 2015 18:24:12 +0000 Subject: staging: vt6655: remove antenna diversity functions The vendor had disabled these functions in their last version. On test this can be troublesome, so remove this from the driver along with its macros and timers. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c index ecf7dac..565ba18 100644 --- a/drivers/staging/vt6655/baseband.c +++ b/drivers/staging/vt6655/baseband.c @@ -1699,46 +1699,6 @@ static const unsigned short awcFrameTime[MAX_RATE] = { 10, 20, 55, 110, 24, 36, 48, 72, 96, 144, 192, 216 }; -/*--------------------- Static Functions --------------------------*/ - -static -unsigned long -s_ulGetRatio(struct vnt_private *priv); - -static -void -s_vChangeAntenna( - struct vnt_private *priv -); - -static -void -s_vChangeAntenna( - struct vnt_private *priv -) -{ - if (priv->dwRxAntennaSel == 0) { - priv->dwRxAntennaSel = 1; - if (priv->bTxRxAntInv == true) - BBvSetRxAntennaMode(priv, ANT_A); - else - BBvSetRxAntennaMode(priv, ANT_B); - } else { - priv->dwRxAntennaSel = 0; - if (priv->bTxRxAntInv == true) - BBvSetRxAntennaMode(priv, ANT_B); - else - BBvSetRxAntennaMode(priv, ANT_A); - } - if (priv->dwTxAntennaSel == 0) { - priv->dwTxAntennaSel = 1; - BBvSetTxAntennaMode(priv, ANT_B); - } else { - priv->dwTxAntennaSel = 0; - BBvSetTxAntennaMode(priv, ANT_A); - } -} - /*--------------------- Export Variables --------------------------*/ /* * Description: Calculate data frame transmitting time @@ -2413,303 +2373,3 @@ BBvExitDeepSleep(struct vnt_private *priv, unsigned char byLocalID) BBbWriteEmbedded(priv, 0x0C, 0x00); /* CR12 */ BBbWriteEmbedded(priv, 0x0D, 0x01); /* CR13 */ } - -static -unsigned long -s_ulGetRatio(struct vnt_private *priv) -{ - unsigned long ulRatio = 0; - unsigned long ulMaxPacket; - unsigned long ulPacketNum; - - /* This is a thousand-ratio */ - ulMaxPacket = priv->uNumSQ3[RATE_54M]; - if (priv->uNumSQ3[RATE_54M] != 0) { - ulPacketNum = priv->uNumSQ3[RATE_54M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_54M; - } - if (priv->uNumSQ3[RATE_48M] > ulMaxPacket) { - ulPacketNum = priv->uNumSQ3[RATE_54M] + priv->uNumSQ3[RATE_48M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_48M; - ulMaxPacket = priv->uNumSQ3[RATE_48M]; - } - if (priv->uNumSQ3[RATE_36M] > ulMaxPacket) { - ulPacketNum = priv->uNumSQ3[RATE_54M] + priv->uNumSQ3[RATE_48M] + - priv->uNumSQ3[RATE_36M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_36M; - ulMaxPacket = priv->uNumSQ3[RATE_36M]; - } - if (priv->uNumSQ3[RATE_24M] > ulMaxPacket) { - ulPacketNum = priv->uNumSQ3[RATE_54M] + priv->uNumSQ3[RATE_48M] + - priv->uNumSQ3[RATE_36M] + priv->uNumSQ3[RATE_24M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_24M; - ulMaxPacket = priv->uNumSQ3[RATE_24M]; - } - if (priv->uNumSQ3[RATE_18M] > ulMaxPacket) { - ulPacketNum = priv->uNumSQ3[RATE_54M] + priv->uNumSQ3[RATE_48M] + - priv->uNumSQ3[RATE_36M] + priv->uNumSQ3[RATE_24M] + - priv->uNumSQ3[RATE_18M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_18M; - ulMaxPacket = priv->uNumSQ3[RATE_18M]; - } - if (priv->uNumSQ3[RATE_12M] > ulMaxPacket) { - ulPacketNum = priv->uNumSQ3[RATE_54M] + priv->uNumSQ3[RATE_48M] + - priv->uNumSQ3[RATE_36M] + priv->uNumSQ3[RATE_24M] + - priv->uNumSQ3[RATE_18M] + priv->uNumSQ3[RATE_12M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_12M; - ulMaxPacket = priv->uNumSQ3[RATE_12M]; - } - if (priv->uNumSQ3[RATE_11M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt - priv->uNumSQ3[RATE_1M] - - priv->uNumSQ3[RATE_2M] - priv->uNumSQ3[RATE_5M] - - priv->uNumSQ3[RATE_6M] - priv->uNumSQ3[RATE_9M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_11M; - ulMaxPacket = priv->uNumSQ3[RATE_11M]; - } - if (priv->uNumSQ3[RATE_9M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt - priv->uNumSQ3[RATE_1M] - - priv->uNumSQ3[RATE_2M] - priv->uNumSQ3[RATE_5M] - - priv->uNumSQ3[RATE_6M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_9M; - ulMaxPacket = priv->uNumSQ3[RATE_9M]; - } - if (priv->uNumSQ3[RATE_6M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt - priv->uNumSQ3[RATE_1M] - - priv->uNumSQ3[RATE_2M] - priv->uNumSQ3[RATE_5M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_6M; - ulMaxPacket = priv->uNumSQ3[RATE_6M]; - } - if (priv->uNumSQ3[RATE_5M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt - priv->uNumSQ3[RATE_1M] - - priv->uNumSQ3[RATE_2M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_55M; - ulMaxPacket = priv->uNumSQ3[RATE_5M]; - } - if (priv->uNumSQ3[RATE_2M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt - priv->uNumSQ3[RATE_1M]; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_2M; - ulMaxPacket = priv->uNumSQ3[RATE_2M]; - } - if (priv->uNumSQ3[RATE_1M] > ulMaxPacket) { - ulPacketNum = priv->uDiversityCnt; - ulRatio = (ulPacketNum * 1000 / priv->uDiversityCnt); - ulRatio += TOP_RATE_1M; - } - - return ulRatio; -} - -void -BBvClearAntDivSQ3Value(struct vnt_private *priv) -{ - unsigned int ii; - - priv->uDiversityCnt = 0; - for (ii = 0; ii < MAX_RATE; ii++) - priv->uNumSQ3[ii] = 0; -} - -/* - * Description: Antenna Diversity - * - * Parameters: - * In: - * priv - Device Structure - * byRSR - RSR from received packet - * bySQ3 - SQ3 value from received packet - * Out: - * none - * - * Return Value: none - * - */ - -void BBvAntennaDiversity(struct vnt_private *priv, - unsigned char byRxRate, unsigned char bySQ3) -{ - if ((byRxRate >= MAX_RATE) || (priv->wAntDiversityMaxRate >= MAX_RATE)) - return; - - priv->uDiversityCnt++; - - priv->uNumSQ3[byRxRate]++; - - if (priv->byAntennaState == 0) { - if (priv->uDiversityCnt > priv->ulDiversityNValue) { - pr_debug("ulDiversityNValue=[%d],54M-[%d]\n", - (int)priv->ulDiversityNValue, - (int)priv->uNumSQ3[(int)priv->wAntDiversityMaxRate]); - - if (priv->uNumSQ3[priv->wAntDiversityMaxRate] < priv->uDiversityCnt/2) { - priv->ulRatio_State0 = s_ulGetRatio(priv); - pr_debug("SQ3_State0, rate = [%08x]\n", - (int)priv->ulRatio_State0); - - if (priv->byTMax == 0) - return; - pr_debug("1.[%08x], uNumSQ3[%d]=%d, %d\n", - (int)priv->ulRatio_State0, - (int)priv->wAntDiversityMaxRate, - (int)priv->uNumSQ3[(int)priv->wAntDiversityMaxRate], - (int)priv->uDiversityCnt); - - s_vChangeAntenna(priv); - priv->byAntennaState = 1; - del_timer(&priv->TimerSQ3Tmax3); - del_timer(&priv->TimerSQ3Tmax2); - priv->TimerSQ3Tmax1.expires = RUN_AT(priv->byTMax * HZ); - add_timer(&priv->TimerSQ3Tmax1); - - } else { - priv->TimerSQ3Tmax3.expires = RUN_AT(priv->byTMax3 * HZ); - add_timer(&priv->TimerSQ3Tmax3); - } - BBvClearAntDivSQ3Value(priv); - - } - } else { /* byAntennaState == 1 */ - - if (priv->uDiversityCnt > priv->ulDiversityMValue) { - del_timer(&priv->TimerSQ3Tmax1); - - priv->ulRatio_State1 = s_ulGetRatio(priv); - pr_debug("RX:SQ3_State1, rate0 = %08x,rate1 = %08x\n", - (int)priv->ulRatio_State0, - (int)priv->ulRatio_State1); - - if (priv->ulRatio_State1 < priv->ulRatio_State0) { - pr_debug("2.[%08x][%08x], uNumSQ3[%d]=%d, %d\n", - (int)priv->ulRatio_State0, - (int)priv->ulRatio_State1, - (int)priv->wAntDiversityMaxRate, - (int)priv->uNumSQ3[(int)priv->wAntDiversityMaxRate], - (int)priv->uDiversityCnt); - - s_vChangeAntenna(priv); - priv->TimerSQ3Tmax3.expires = RUN_AT(priv->byTMax3 * HZ); - priv->TimerSQ3Tmax2.expires = RUN_AT(priv->byTMax2 * HZ); - add_timer(&priv->TimerSQ3Tmax3); - add_timer(&priv->TimerSQ3Tmax2); - } - priv->byAntennaState = 0; - BBvClearAntDivSQ3Value(priv); - } - } /* byAntennaState */ -} - -/*+ - * - * Description: - * Timer for SQ3 antenna diversity - * - * Parameters: - * In: - * Out: - * none - * - * Return Value: none - * - -*/ - -void -TimerSQ3CallBack( - unsigned long data -) -{ - struct vnt_private *priv = (struct vnt_private *)data; - unsigned long flags; - - pr_debug("TimerSQ3CallBack...\n"); - - spin_lock_irqsave(&priv->lock, flags); - - pr_debug("3.[%08x][%08x], %d\n", - (int)priv->ulRatio_State0, (int)priv->ulRatio_State1, - (int)priv->uDiversityCnt); - - s_vChangeAntenna(priv); - priv->byAntennaState = 0; - BBvClearAntDivSQ3Value(priv); - - priv->TimerSQ3Tmax3.expires = RUN_AT(priv->byTMax3 * HZ); - priv->TimerSQ3Tmax2.expires = RUN_AT(priv->byTMax2 * HZ); - add_timer(&priv->TimerSQ3Tmax3); - add_timer(&priv->TimerSQ3Tmax2); - - spin_unlock_irqrestore(&priv->lock, flags); -} - -/*+ - * - * Description: - * Timer for SQ3 antenna diversity - * - * Parameters: - * In: - * pvSysSpec1 - * hDeviceContext - Pointer to the adapter - * pvSysSpec2 - * pvSysSpec3 - * Out: - * none - * - * Return Value: none - * - -*/ - -void -TimerState1CallBack( - unsigned long data -) -{ - struct vnt_private *priv = (struct vnt_private *)data; - unsigned long flags; - - pr_debug("TimerState1CallBack...\n"); - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->uDiversityCnt < priv->ulDiversityMValue/100) { - s_vChangeAntenna(priv); - priv->TimerSQ3Tmax3.expires = RUN_AT(priv->byTMax3 * HZ); - priv->TimerSQ3Tmax2.expires = RUN_AT(priv->byTMax2 * HZ); - add_timer(&priv->TimerSQ3Tmax3); - add_timer(&priv->TimerSQ3Tmax2); - } else { - priv->ulRatio_State1 = s_ulGetRatio(priv); - pr_debug("SQ3_State1, rate0 = %08x,rate1 = %08x\n", - (int)priv->ulRatio_State0, - (int)priv->ulRatio_State1); - - if (priv->ulRatio_State1 < priv->ulRatio_State0) { - pr_debug("2.[%08x][%08x], uNumSQ3[%d]=%d, %d\n", - (int)priv->ulRatio_State0, - (int)priv->ulRatio_State1, - (int)priv->wAntDiversityMaxRate, - (int)priv->uNumSQ3[(int)priv->wAntDiversityMaxRate], - (int)priv->uDiversityCnt); - - s_vChangeAntenna(priv); - - priv->TimerSQ3Tmax3.expires = RUN_AT(priv->byTMax3 * HZ); - priv->TimerSQ3Tmax2.expires = RUN_AT(priv->byTMax2 * HZ); - add_timer(&priv->TimerSQ3Tmax3); - add_timer(&priv->TimerSQ3Tmax2); - } - } - priv->byAntennaState = 0; - BBvClearAntDivSQ3Value(priv); - - spin_unlock_irqrestore(&priv->lock, flags); -} diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h index d9f6d63..43a4fb1 100644 --- a/drivers/staging/vt6655/baseband.h +++ b/drivers/staging/vt6655/baseband.h @@ -93,21 +93,4 @@ void BBvSetRxAntennaMode(struct vnt_private *, unsigned char byAntennaMode); void BBvSetDeepSleep(struct vnt_private *, unsigned char byLocalID); void BBvExitDeepSleep(struct vnt_private *, unsigned char byLocalID); -/* timer for antenna diversity */ - -void -TimerSQ3CallBack( - unsigned long -); - -void -TimerState1CallBack( - unsigned long -); - -void BBvAntennaDiversity(struct vnt_private *, - unsigned char byRxRate, unsigned char bySQ3); -void -BBvClearAntDivSQ3Value(struct vnt_private *); - #endif /* __BASEBAND_H__ */ diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h index 96d8e62..440537e4 100644 --- a/drivers/staging/vt6655/device.h +++ b/drivers/staging/vt6655/device.h @@ -407,29 +407,6 @@ struct vnt_private { unsigned char byBBCR88; unsigned char byBBCR09; - bool bDiversityRegCtlON; - bool bDiversityEnable; - unsigned long ulDiversityNValue; - unsigned long ulDiversityMValue; - unsigned char byTMax; - unsigned char byTMax2; - unsigned char byTMax3; - unsigned long ulSQ3TH; - - /* ANT diversity */ - unsigned long uDiversityCnt; - unsigned char byAntennaState; - unsigned long ulRatio_State0; - unsigned long ulRatio_State1; - - /* SQ3 functions for antenna diversity */ - struct timer_list TimerSQ3Tmax1; - struct timer_list TimerSQ3Tmax2; - struct timer_list TimerSQ3Tmax3; - - unsigned long uNumSQ3[MAX_RATE]; - unsigned short wAntDiversityMaxRate; - unsigned char abyEEPROM[EEP_MAX_CONTEXT_SIZE]; /* unsigned long alignment */ unsigned short wBeaconInterval; diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 05be34b..0408e91 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -126,10 +126,6 @@ DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); DEVICE_PARAM(BasebandType, "baseband type"); -#define DIVERSITY_ANT_DEF 0 - -DEVICE_PARAM(bDiversityANTEnable, "ANT diversity mode"); - // // Static vars definitions // @@ -152,7 +148,6 @@ static void vt6655_init_info(struct pci_dev *pcid, static void device_free_info(struct vnt_private *pDevice); static bool device_get_pci_info(struct vnt_private *, struct pci_dev *pcid); static void device_print_info(struct vnt_private *pDevice); -static void device_init_diversity_timer(struct vnt_private *pDevice); static irqreturn_t device_intr(int irq, void *dev_instance); #ifdef CONFIG_PM @@ -216,7 +211,6 @@ static void device_get_options(struct vnt_private *pDevice) pOpts->short_retry = SHORT_RETRY_DEF; pOpts->long_retry = LONG_RETRY_DEF; pOpts->bbp_type = BBP_TYPE_DEF; - pOpts->flags |= DEVICE_FLAGS_DiversityANT; } static void @@ -224,7 +218,6 @@ device_set_options(struct vnt_private *pDevice) { pDevice->byShortRetryLimit = pDevice->sOpts.short_retry; pDevice->byLongRetryLimit = pDevice->sOpts.long_retry; - pDevice->bDiversityRegCtlON = (pDevice->sOpts.flags & DEVICE_FLAGS_DiversityANT) ? 1 : 0; pDevice->byBBType = pDevice->sOpts.bbp_type; pDevice->byPacketType = pDevice->byBBType; pDevice->byAutoFBCtrl = AUTO_FB_0; @@ -236,8 +229,6 @@ device_set_options(struct vnt_private *pDevice) pr_debug(" byPreambleType= %d\n", (int)pDevice->byPreambleType); pr_debug(" byShortPreamble= %d\n", (int)pDevice->byShortPreamble); pr_debug(" byBBType= %d\n", (int)pDevice->byBBType); - pr_debug(" pDevice->bDiversityRegCtlON= %d\n", - (int)pDevice->bDiversityRegCtlON); } // @@ -249,7 +240,6 @@ static void device_init_registers(struct vnt_private *pDevice) unsigned long flags; unsigned int ii; unsigned char byValue; - unsigned char byValue1; unsigned char byCCKPwrdBm = 0; unsigned char byOFDMPwrdBm = 0; @@ -301,13 +291,6 @@ static void device_init_registers(struct vnt_private *pDevice) if (byValue == 0) byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); - pDevice->ulDiversityNValue = 100*260; - pDevice->ulDiversityMValue = 100*16; - pDevice->byTMax = 1; - pDevice->byTMax2 = 4; - pDevice->ulSQ3TH = 0; - pDevice->byTMax3 = 64; - if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { pDevice->byAntennaCount = 2; pDevice->byTxAntennaMode = ANT_B; @@ -318,16 +301,7 @@ static void device_init_registers(struct vnt_private *pDevice) pDevice->byRxAntennaMode = ANT_A; else pDevice->byRxAntennaMode = ANT_B; - - byValue1 = SROMbyReadEmbedded(pDevice->PortOffset, - EEP_OFS_ANTENNA); - - if ((byValue1 & 0x08) == 0) - pDevice->bDiversityEnable = false; - else - pDevice->bDiversityEnable = true; } else { - pDevice->bDiversityEnable = false; pDevice->byAntennaCount = 1; pDevice->dwTxAntennaSel = 0; pDevice->dwRxAntennaSel = 0; @@ -349,11 +323,6 @@ static void device_init_registers(struct vnt_private *pDevice) } } - pr_debug("bDiversityEnable=[%d],NValue=[%d],MValue=[%d],TMax=[%d],TMax2=[%d]\n", - pDevice->bDiversityEnable, (int)pDevice->ulDiversityNValue, - (int)pDevice->ulDiversityMValue, pDevice->byTMax, - pDevice->byTMax2); - /* zonetype initial */ pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; @@ -493,24 +462,6 @@ static void device_init_registers(struct vnt_private *pDevice) MACvStart(pDevice->PortOffset); } -static void device_init_diversity_timer(struct vnt_private *pDevice) -{ - init_timer(&pDevice->TimerSQ3Tmax1); - pDevice->TimerSQ3Tmax1.data = (unsigned long) pDevice; - pDevice->TimerSQ3Tmax1.function = TimerSQ3CallBack; - pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ); - - init_timer(&pDevice->TimerSQ3Tmax2); - pDevice->TimerSQ3Tmax2.data = (unsigned long) pDevice; - pDevice->TimerSQ3Tmax2.function = TimerSQ3CallBack; - pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ); - - init_timer(&pDevice->TimerSQ3Tmax3); - pDevice->TimerSQ3Tmax3.data = (unsigned long) pDevice; - pDevice->TimerSQ3Tmax3.function = TimerState1CallBack; - pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ); -} - static void device_print_info(struct vnt_private *pDevice) { dev_info(&pDevice->pcid->dev, "%s\n", get_chip_name(pDevice->chip_id)); @@ -1348,8 +1299,6 @@ static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) switch (vif->type) { case NL80211_IFTYPE_STATION: - if (priv->bDiversityRegCtlON) - device_init_diversity_timer(priv); break; case NL80211_IFTYPE_ADHOC: MACvRegBitsOff(priv->PortOffset, MAC_REG_RCR, RCR_UNICAST); @@ -1379,11 +1328,6 @@ static void vnt_remove_interface(struct ieee80211_hw *hw, switch (vif->type) { case NL80211_IFTYPE_STATION: - if (priv->bDiversityRegCtlON) { - del_timer(&priv->TimerSQ3Tmax1); - del_timer(&priv->TimerSQ3Tmax2); - del_timer(&priv->TimerSQ3Tmax3); - } break; case NL80211_IFTYPE_ADHOC: MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 977683c..11cc090 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -116,12 +116,6 @@ static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, rx_status.flag = RX_FLAG_DECRYPTED; } - if (priv->vif && priv->bDiversityEnable) { - if (ieee80211_is_data(fc) && - (frame_size > 50) && priv->vif->bss_conf.assoc) - BBvAntennaDiversity(priv, priv->rx_rate, 0); - } - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); ieee80211_rx_irqsafe(priv->hw, skb); -- cgit v0.10.2 From 918185f6662379f570e29c86c0229d8036ef4fa7 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 19 Jan 2015 18:24:13 +0000 Subject: staging: vt6655: device_init_registers alway set initial antenna mode BBvSetTxAntennaMode and BBvSetRxAntennaMode need to be set correcty on start up Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 0408e91..58559fa 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -323,6 +323,10 @@ static void device_init_registers(struct vnt_private *pDevice) } } + /* Set initial antenna mode */ + BBvSetTxAntennaMode(pDevice, pDevice->byTxAntennaMode); + BBvSetRxAntennaMode(pDevice, pDevice->byRxAntennaMode); + /* zonetype initial */ pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; -- cgit v0.10.2 From b0c5881e78b31ff7e90fb8fef23d65c078fec18e Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 19 Jan 2015 18:24:14 +0000 Subject: staging: vt6655: Fix RFbSetPower() error: buffer overflow 'priv->abyCCKPwrTbl' 15 <= 56 Check uCH is not more than CB_MAX_CHANNEL_24G(14) on rates RATE_1M to RATE_11M Return false as the call is invalid as these rates do not exist above channel 14. Reported-by: Dan Carpenter Cc: Dan Carpenter Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 27841aa..a6eabde 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -788,6 +788,9 @@ bool RFbSetPower( case RATE_2M: case RATE_5M: case RATE_11M: + if (uCH > CB_MAX_CHANNEL_24G) + return false; + byPwr = priv->abyCCKPwrTbl[uCH]; byPwrdBm = priv->abyCCKDefaultPwr[uCH]; break; -- cgit v0.10.2 From 7a9331c0c0fcd57ae3966946188e1416fe415351 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Mon, 19 Jan 2015 18:24:15 +0000 Subject: staging: vt6655: RFbSetPower remove unused variable byPwrdBm byPwrdBm is set but never used. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index a6eabde..941b2ad 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -775,7 +775,6 @@ bool RFbSetPower( bool bResult = true; unsigned char byPwr = 0; unsigned char byDec = 0; - unsigned char byPwrdBm = 0; if (priv->dwDiagRefCount != 0) return true; @@ -792,7 +791,6 @@ bool RFbSetPower( return false; byPwr = priv->abyCCKPwrTbl[uCH]; - byPwrdBm = priv->abyCCKDefaultPwr[uCH]; break; case RATE_6M: case RATE_9M: @@ -806,15 +804,6 @@ bool RFbSetPower( if (byDec >= priv->byMaxPwrLevel) byDec = priv->byMaxPwrLevel-1; - if (priv->byRFType == RF_UW2452) { - byPwrdBm = byDec - byPwr; - byPwrdBm /= 3; - } else { - byPwrdBm = byDec - byPwr; - byPwrdBm >>= 1; - } - - byPwrdBm += priv->abyOFDMDefaultPwr[uCH]; byPwr = byDec; break; case RATE_24M: @@ -822,7 +811,6 @@ bool RFbSetPower( case RATE_48M: case RATE_54M: byPwr = priv->abyOFDMPwrTbl[uCH]; - byPwrdBm = priv->abyOFDMDefaultPwr[uCH]; break; } -- cgit v0.10.2 From 48eaa7f59649eb4d371ad5e75c606f65e80a93ad Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Wed, 21 Jan 2015 13:08:48 +0200 Subject: staging: vt6656: fix Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2) This patch fixes the following checkpatch.pl warning: fix Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2) Pahole showed that the 2 structs are aligned to u16 struct vnt_mic_hdr { u8 id; /* 0 1 */ u8 tx_priority; /* 1 1 */ u8 mic_addr2[6]; /* 2 6 */ u8 ccmp_pn[6]; /* 8 6 */ __be16 payload_len; /* 14 2 */ __be16 hlen; /* 16 2 */ __le16 frame_control; /* 18 2 */ u8 addr1[6]; /* 20 6 */ u8 addr2[6]; /* 26 6 */ u8 addr3[6]; /* 32 6 */ __le16 seq_ctrl; /* 38 2 */ u8 addr4[6]; /* 40 6 */ u16 packing; /* 46 2 */ /* size: 48, cachelines: 1, members: 13 */ /* last cacheline: 48 bytes */ }; struct ieee80211_hdr { __le16 frame_control; /* 0 2 */ __le16 duration_id; /* 2 2 */ u8 addr1[6]; /* 4 6 */ u8 addr2[6]; /* 10 6 */ u8 addr3[6]; /* 16 6 */ __le16 seq_ctrl; /* 22 2 */ u8 addr4[6]; /* 24 6 */ /* size: 30, cachelines: 1, members: 7 */ /* last cacheline: 30 bytes */ }; Signed-off-by: Heba Aamer Reviewed-by: Aya Mahfouz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index bb6a4d4..b74f672 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -738,7 +738,7 @@ static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context, mic_hdr->id = 0x59; mic_hdr->payload_len = cpu_to_be16(payload_len); - memcpy(mic_hdr->mic_addr2, hdr->addr2, ETH_ALEN); + ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2); ieee80211_get_key_tx_seq(tx_key, &seq); -- cgit v0.10.2 From 396beed6253d1a5257f7ae757b4e9a8423966c55 Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:07 -0500 Subject: staging: unisys: Remove unneeded spaces after casts in virthba.c This patch removes all unnecessary spaces after casts, as reported by the checkpatch script. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 82fcb3b..3c36653 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -260,7 +260,7 @@ add_scsipending_entry(struct virthba_info *vhbainfo, char cmdtype, void *new) insert_location = vhbainfo->nextinsert; while (vhbainfo->pending[insert_location].sent != NULL) { insert_location = (insert_location + 1) % MAX_PENDING_REQUESTS; - if (insert_location == (int) vhbainfo->nextinsert) { + if (insert_location == (int)vhbainfo->nextinsert) { LOGERR("Queue should be full. insert_location<<%d>> Unable to find open slot for pending commands.\n", insert_location); spin_unlock_irqrestore(&vhbainfo->privlock, flags); @@ -289,7 +289,7 @@ add_scsipending_entry_with_wait(struct virthba_info *vhbainfo, char cmdtype, insert_location = add_scsipending_entry(vhbainfo, cmdtype, new); } - return (unsigned int) insert_location; + return (unsigned int)insert_location; } static void * @@ -300,13 +300,13 @@ del_scsipending_entry(struct virthba_info *vhbainfo, uintptr_t del) if (del >= MAX_PENDING_REQUESTS) { LOGERR("Invalid queue position <<%lu>> given to delete. MAX_PENDING_REQUESTS <<%d>>\n", - (unsigned long) del, MAX_PENDING_REQUESTS); + (unsigned long)del, MAX_PENDING_REQUESTS); } else { spin_lock_irqsave(&vhbainfo->privlock, flags); if (vhbainfo->pending[del].sent == NULL) LOGERR("Deleting already cleared queue entry at <<%lu>>.\n", - (unsigned long) del); + (unsigned long)del); sent = vhbainfo->pending[del].sent; @@ -418,7 +418,7 @@ process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp) static irqreturn_t virthba_ISR(int irq, void *dev_id) { - struct virthba_info *virthbainfo = (struct virthba_info *) dev_id; + struct virthba_info *virthbainfo = (struct virthba_info *)dev_id; struct channel_header __iomem *pChannelHeader; struct signal_queue_header __iomem *pqhdr; u64 mask; @@ -442,7 +442,7 @@ virthba_ISR(int irq, void *dev_id) return IRQ_NONE; } pqhdr = (struct signal_queue_header __iomem *) - ((char __iomem *) pChannelHeader + + ((char __iomem *)pChannelHeader + readq(&pChannelHeader->ch_space_offset)) + IOCHAN_FROM_IOPART; writeq(readq(&pqhdr->num_irq_received) + 1, &pqhdr->num_irq_received); @@ -501,19 +501,19 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) * the max-channel value. */ LOGINF("virtpcidev->scsi.max.max_channel=%u, max_id=%u, max_lun=%u, cmd_per_lun=%u, max_io_size=%u\n", - (unsigned) virtpcidev->scsi.max.max_channel - 1, - (unsigned) virtpcidev->scsi.max.max_id, - (unsigned) virtpcidev->scsi.max.max_lun, - (unsigned) virtpcidev->scsi.max.cmd_per_lun, - (unsigned) virtpcidev->scsi.max.max_io_size); - scsihost->max_channel = (unsigned) virtpcidev->scsi.max.max_channel; - scsihost->max_id = (unsigned) virtpcidev->scsi.max.max_id; - scsihost->max_lun = (unsigned) virtpcidev->scsi.max.max_lun; - scsihost->cmd_per_lun = (unsigned) virtpcidev->scsi.max.cmd_per_lun; + (unsigned)virtpcidev->scsi.max.max_channel - 1, + (unsigned)virtpcidev->scsi.max.max_id, + (unsigned)virtpcidev->scsi.max.max_lun, + (unsigned)virtpcidev->scsi.max.cmd_per_lun, + (unsigned)virtpcidev->scsi.max.max_io_size); + scsihost->max_channel = (unsigned)virtpcidev->scsi.max.max_channel; + scsihost->max_id = (unsigned)virtpcidev->scsi.max.max_id; + scsihost->max_lun = (unsigned)virtpcidev->scsi.max.max_lun; + scsihost->cmd_per_lun = (unsigned)virtpcidev->scsi.max.cmd_per_lun; scsihost->max_sectors = - (unsigned short) (virtpcidev->scsi.max.max_io_size >> 9); + (unsigned short)(virtpcidev->scsi.max.max_io_size >> 9); scsihost->sg_tablesize = - (unsigned short) (virtpcidev->scsi.max.max_io_size / PAGE_SIZE); + (unsigned short)(virtpcidev->scsi.max.max_io_size / PAGE_SIZE); if (scsihost->sg_tablesize > MAX_PHYS_INFO) scsihost->sg_tablesize = MAX_PHYS_INFO; LOGINF("scsihost->max_channel=%u, max_id=%u, max_lun=%llu, cmd_per_lun=%u, max_sectors=%hu, sg_tablesize=%hu\n", @@ -544,7 +544,7 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) return -ENODEV; } - virthbainfo = (struct virthba_info *) scsihost->hostdata; + virthbainfo = (struct virthba_info *)scsihost->hostdata; memset(virthbainfo, 0, sizeof(struct virthba_info)); for (i = 0; i < VIRTHBASOPENMAX; i++) { if (VirtHbasOpen[i].virthbainfo == NULL) { @@ -646,11 +646,11 @@ virthba_remove(struct virtpci_dev *virtpcidev) { struct virthba_info *virthbainfo; struct Scsi_Host *scsihost = - (struct Scsi_Host *) virtpcidev->scsi.scsihost; + (struct Scsi_Host *)virtpcidev->scsi.scsihost; LOGINF("virtpcidev bus_no<<%d>>devNo<<%d>>", virtpcidev->bus_no, virtpcidev->device_no); - virthbainfo = (struct virthba_info *) scsihost->hostdata; + virthbainfo = (struct virthba_info *)scsihost->hostdata; if (virthbainfo->interrupt_vector != -1) free_irq(virthbainfo->interrupt_vector, virthbainfo); LOGINF("Removing virtpcidev: 0x%p, virthbainfo: 0x%p\n", virtpcidev, @@ -679,7 +679,7 @@ forward_vdiskmgmt_command(enum vdisk_mgmt_types vdiskcmdtype, { struct uiscmdrsp *cmdrsp; struct virthba_info *virthbainfo = - (struct virthba_info *) scsihost->hostdata; + (struct virthba_info *)scsihost->hostdata; int notifyresult = 0xffff; wait_queue_head_t notifyevent; @@ -706,8 +706,8 @@ forward_vdiskmgmt_command(enum vdisk_mgmt_types vdiskcmdtype, /* specify the event that has to be triggered when this cmd is * complete */ - cmdrsp->vdiskmgmt.notify = (void *) ¬ifyevent; - cmdrsp->vdiskmgmt.notifyresult = (void *) ¬ifyresult; + cmdrsp->vdiskmgmt.notify = (void *)¬ifyevent; + cmdrsp->vdiskmgmt.notifyresult = (void *)¬ifyresult; /* save destination */ cmdrsp->vdiskmgmt.vdisktype = vdiskcmdtype; @@ -715,14 +715,14 @@ forward_vdiskmgmt_command(enum vdisk_mgmt_types vdiskcmdtype, cmdrsp->vdiskmgmt.vdest.id = vdest->id; cmdrsp->vdiskmgmt.vdest.lun = vdest->lun; cmdrsp->vdiskmgmt.scsicmd = - (void *) (uintptr_t) + (void *)(uintptr_t) add_scsipending_entry_with_wait(virthbainfo, CMD_VDISKMGMT_TYPE, - (void *) cmdrsp); + (void *)cmdrsp); uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo, cmdrsp, IOCHAN_TO_IOPART, &virthbainfo->chinfo.insertlock, - DONT_ISSUE_INTERRUPT, (u64) NULL, + DONT_ISSUE_INTERRUPT, (u64)NULL, OK_TO_WAIT, "vhba"); LOGINF("VdiskMgmt waiting on event notifyevent=0x%p\n", cmdrsp->scsitaskmgmt.notify); @@ -742,7 +742,7 @@ forward_taskmgmt_command(enum task_mgmt_types tasktype, { struct uiscmdrsp *cmdrsp; struct virthba_info *virthbainfo = - (struct virthba_info *) scsidev->host->hostdata; + (struct virthba_info *)scsidev->host->hostdata; int notifyresult = 0xffff; wait_queue_head_t notifyevent; @@ -767,8 +767,8 @@ forward_taskmgmt_command(enum task_mgmt_types tasktype, cmdrsp->cmdtype = CMD_SCSITASKMGMT_TYPE; /* specify the event that has to be triggered when this */ /* cmd is complete */ - cmdrsp->scsitaskmgmt.notify = (void *) ¬ifyevent; - cmdrsp->scsitaskmgmt.notifyresult = (void *) ¬ifyresult; + cmdrsp->scsitaskmgmt.notify = (void *)¬ifyevent; + cmdrsp->scsitaskmgmt.notifyresult = (void *)¬ifyresult; /* save destination */ cmdrsp->scsitaskmgmt.tasktype = tasktype; @@ -776,15 +776,15 @@ forward_taskmgmt_command(enum task_mgmt_types tasktype, cmdrsp->scsitaskmgmt.vdest.id = scsidev->id; cmdrsp->scsitaskmgmt.vdest.lun = scsidev->lun; cmdrsp->scsitaskmgmt.scsicmd = - (void *) (uintptr_t) + (void *)(uintptr_t) add_scsipending_entry_with_wait(virthbainfo, CMD_SCSITASKMGMT_TYPE, - (void *) cmdrsp); + (void *)cmdrsp); uisqueue_put_cmdrsp_with_lock_client(virthbainfo->chinfo.queueinfo, cmdrsp, IOCHAN_TO_IOPART, &virthbainfo->chinfo.insertlock, - DONT_ISSUE_INTERRUPT, (u64) NULL, + DONT_ISSUE_INTERRUPT, (u64)NULL, OK_TO_WAIT, "vhba"); LOGINF("TaskMgmt waiting on event notifyevent=0x%p\n", cmdrsp->scsitaskmgmt.notify); @@ -805,7 +805,7 @@ virthba_abort_handler(struct scsi_cmnd *scsicmd) struct virtdisk_info *vdisk; scsidev = scsicmd->device; - for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; + for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { if ((scsidev->channel == vdisk->channel) && (scsidev->id == vdisk->id) @@ -831,7 +831,7 @@ virthba_bus_reset_handler(struct scsi_cmnd *scsicmd) struct virtdisk_info *vdisk; scsidev = scsicmd->device; - for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; + for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { if ((scsidev->channel == vdisk->channel) && (scsidev->id == vdisk->id) @@ -857,7 +857,7 @@ virthba_device_reset_handler(struct scsi_cmnd *scsicmd) struct virtdisk_info *vdisk; scsidev = scsicmd->device; - for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; + for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { if ((scsidev->channel == vdisk->channel) && (scsidev->id == vdisk->id) @@ -915,7 +915,7 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, struct uiscmdrsp *cmdrsp; unsigned int i; struct virthba_info *virthbainfo = - (struct virthba_info *) scsihost->hostdata; + (struct virthba_info *)scsihost->hostdata; struct scatterlist *sg = NULL; struct scatterlist *sgl = NULL; int sg_failed = 0; @@ -940,9 +940,9 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, * will return the scsicmd pointer for completion */ insert_location = - add_scsipending_entry(virthbainfo, CMD_SCSI_TYPE, (void *) scsicmd); + add_scsipending_entry(virthbainfo, CMD_SCSI_TYPE, (void *)scsicmd); if (insert_location != -1) { - cmdrsp->scsi.scsicmd = (void *) (uintptr_t) insert_location; + cmdrsp->scsi.scsicmd = (void *)(uintptr_t)insert_location; } else { LOGERR("Queue is full. Returning busy.\n"); kfree(cmdrsp); @@ -967,7 +967,7 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, if (scsi_sg_count(scsicmd) > MAX_PHYS_INFO) { LOGERR("scsicmd use_sg:%d greater than MAX:%d\n", scsi_sg_count(scsicmd), MAX_PHYS_INFO); - del_scsipending_entry(virthbainfo, (uintptr_t) insert_location); + del_scsipending_entry(virthbainfo, (uintptr_t)insert_location); kfree(cmdrsp); return 1; /* reject the command */ } @@ -1003,7 +1003,7 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) { LOGERR(" Entry(%d): page->[0x%p], phys->[0x%Lx], off(%d), len(%d)\n", i, sg_page(sg), - (unsigned long long) sg_phys(sg), + (unsigned long long)sg_phys(sg), sg->offset, sg->length); } LOGERR("Done sg_list dump.\n"); @@ -1022,12 +1022,12 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, &virthbainfo->chinfo. insertlock, DONT_ISSUE_INTERRUPT, - (u64) NULL, DONT_WAIT, "vhba"); + (u64)NULL, DONT_WAIT, "vhba"); if (i == 0) { /* queue must be full - and we said don't wait - return busy */ LOGERR("uisqueue_put_cmdrsp_with_lock ****FAILED\n"); kfree(cmdrsp); - del_scsipending_entry(virthbainfo, (uintptr_t) insert_location); + del_scsipending_entry(virthbainfo, (uintptr_t)insert_location); return SCSI_MLQUEUE_DEVICE_BUSY; } @@ -1047,9 +1047,9 @@ virthba_slave_alloc(struct scsi_device *scsidev) struct virtdisk_info *vdisk; struct virtdisk_info *tmpvdisk; struct virthba_info *virthbainfo; - struct Scsi_Host *scsihost = (struct Scsi_Host *) scsidev->host; + struct Scsi_Host *scsihost = (struct Scsi_Host *)scsidev->host; - virthbainfo = (struct virthba_info *) scsihost->hostdata; + virthbainfo = (struct virthba_info *)scsihost->hostdata; if (!virthbainfo) { LOGERR("Could not find virthba_info for scsihost\n"); return 0; /* even though we errored, treat as success */ @@ -1089,9 +1089,9 @@ virthba_slave_destroy(struct scsi_device *scsidev) */ struct virtdisk_info *vdisk, *delvdisk; struct virthba_info *virthbainfo; - struct Scsi_Host *scsihost = (struct Scsi_Host *) scsidev->host; + struct Scsi_Host *scsihost = (struct Scsi_Host *)scsidev->host; - virthbainfo = (struct virthba_info *) scsihost->hostdata; + virthbainfo = (struct virthba_info *)scsihost->hostdata; if (!virthbainfo) LOGERR("Could not find virthba_info for scsihost\n"); for (vdisk = &virthbainfo->head; vdisk->next; vdisk = vdisk->next) { @@ -1120,7 +1120,7 @@ do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) scsidev = scsicmd->device; memcpy(scsicmd->sense_buffer, cmdrsp->scsi.sensebuf, MAX_SENSE_SIZE); - sd = (struct sense_data *) scsicmd->sense_buffer; + sd = (struct sense_data *)scsicmd->sense_buffer; /* Do not log errors for disk-not-present inquiries */ if ((cmdrsp->scsi.cmnd[0] == INQUIRY) && @@ -1129,7 +1129,7 @@ do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) return; /* Okay see what our error_count is here.... */ - for (vdisk = &((struct virthba_info *) scsidev->host->hostdata)->head; + for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { if ((scsidev->channel != vdisk->channel) || (scsidev->id != vdisk->id) @@ -1200,7 +1200,7 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) DBGVER("copying OUT OF buf into 0x%p %d\n", sg_page(sg + i), sg[i].length); thispage_orig = kmap_atomic(sg_page(sg + i)); - thispage = (void *) ((unsigned long)thispage_orig | + thispage = (void *)((unsigned long)thispage_orig | sg[i].offset); memcpy(thispage, buf + bufind, sg[i].length); kunmap_atomic(thispage_orig); @@ -1249,8 +1249,8 @@ complete_vdiskmgmt_command(struct uiscmdrsp *cmdrsp) { /* copy the result of the taskmgmt and */ /* wake up the error handler that is waiting for this */ - *(int *) cmdrsp->vdiskmgmt.notifyresult = cmdrsp->vdiskmgmt.result; - wake_up_all((wait_queue_head_t *) cmdrsp->vdiskmgmt.notify); + *(int *)cmdrsp->vdiskmgmt.notifyresult = cmdrsp->vdiskmgmt.result; + wake_up_all((wait_queue_head_t *)cmdrsp->vdiskmgmt.notify); LOGINF("set notify result to %d\n", cmdrsp->vdiskmgmt.result); } @@ -1259,9 +1259,9 @@ complete_taskmgmt_command(struct uiscmdrsp *cmdrsp) { /* copy the result of the taskmgmt and */ /* wake up the error handler that is waiting for this */ - *(int *) cmdrsp->scsitaskmgmt.notifyresult = + *(int *)cmdrsp->scsitaskmgmt.notifyresult = cmdrsp->scsitaskmgmt.result; - wake_up_all((wait_queue_head_t *) cmdrsp->scsitaskmgmt.notify); + wake_up_all((wait_queue_head_t *)cmdrsp->scsitaskmgmt.notify); LOGINF("set notify result to %d\n", cmdrsp->scsitaskmgmt.result); } @@ -1294,14 +1294,14 @@ drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, * deletion */ scsicmd = del_scsipending_entry(virthbainfo, - (uintptr_t) cmdrsp->scsi.scsicmd); + (uintptr_t)cmdrsp->scsi.scsicmd); if (!scsicmd) break; /* complete the orig cmd */ complete_scsi_command(cmdrsp, scsicmd); } else if (cmdrsp->cmdtype == CMD_SCSITASKMGMT_TYPE) { if (!del_scsipending_entry(virthbainfo, - (uintptr_t) cmdrsp->scsitaskmgmt.scsicmd)) + (uintptr_t)cmdrsp->scsitaskmgmt.scsicmd)) break; complete_taskmgmt_command(cmdrsp); } else if (cmdrsp->cmdtype == CMD_NOTIFYGUEST_TYPE) { @@ -1313,7 +1313,7 @@ drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, process_disk_notify(shost, cmdrsp); } else if (cmdrsp->cmdtype == CMD_VDISKMGMT_TYPE) { if (!del_scsipending_entry(virthbainfo, - (uintptr_t) cmdrsp->vdiskmgmt.scsicmd)) + (uintptr_t)cmdrsp->vdiskmgmt.scsicmd)) break; complete_vdiskmgmt_command(cmdrsp); } else @@ -1434,7 +1434,7 @@ static ssize_t enable_ints_write(struct file *file, buf[count] = '\0'; if (copy_from_user(buf, buffer, count)) { LOGERR("copy_from_user failed. buf<<%.*s>> count<<%lu>>\n", - (int) count, buf, count); + (int)count, buf, count); return -EFAULT; } @@ -1442,7 +1442,7 @@ static ssize_t enable_ints_write(struct file *file, if (i != 0) { LOGERR("Failed to scan value for enable_ints, buf<<%.*s>>", - (int) count, buf); + (int)count, buf); return -EFAULT; } @@ -1477,7 +1477,7 @@ static int virthba_serverup(struct virtpci_dev *virtpcidev) { struct virthba_info *virthbainfo = - (struct virthba_info *) ((struct Scsi_Host *) virtpcidev->scsi. + (struct virthba_info *)((struct Scsi_Host *)virtpcidev->scsi. scsihost)->hostdata; DBGINF("virtpcidev bus_no<<%d>>devNo<<%d>>", virtpcidev->bus_no, @@ -1538,23 +1538,23 @@ virthba_serverdown_complete(struct work_struct *work) pendingdel = &(virthbainfo->pending[i]); switch (pendingdel->cmdtype) { case CMD_SCSI_TYPE: - scsicmd = (struct scsi_cmnd *) pendingdel->sent; + scsicmd = (struct scsi_cmnd *)pendingdel->sent; scsicmd->result = (DID_RESET << 16); if (scsicmd->scsi_done) scsicmd->scsi_done(scsicmd); break; case CMD_SCSITASKMGMT_TYPE: - cmdrsp = (struct uiscmdrsp *) pendingdel->sent; + cmdrsp = (struct uiscmdrsp *)pendingdel->sent; DBGINF("cmdrsp=0x%x, notify=0x%x\n", cmdrsp, cmdrsp->scsitaskmgmt.notify); - *(int *) cmdrsp->scsitaskmgmt.notifyresult = + *(int *)cmdrsp->scsitaskmgmt.notifyresult = TASK_MGMT_FAILED; wake_up_all((wait_queue_head_t *) cmdrsp->scsitaskmgmt.notify); break; case CMD_VDISKMGMT_TYPE: - cmdrsp = (struct uiscmdrsp *) pendingdel->sent; - *(int *) cmdrsp->vdiskmgmt.notifyresult = + cmdrsp = (struct uiscmdrsp *)pendingdel->sent; + *(int *)cmdrsp->vdiskmgmt.notifyresult = VDISK_MGMT_FAILED; wake_up_all((wait_queue_head_t *) cmdrsp->vdiskmgmt.notify); @@ -1585,7 +1585,7 @@ static int virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state) { struct virthba_info *virthbainfo = - (struct virthba_info *) ((struct Scsi_Host *) virtpcidev->scsi. + (struct virthba_info *)((struct Scsi_Host *)virtpcidev->scsi. scsihost)->hostdata; DBGINF("virthba_serverdown"); -- cgit v0.10.2 From 836600fa9554ef1915faa82aaa4af60bebf2b566 Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:08 -0500 Subject: staging: unisys: Fix open parenthesis alignment checks in virthba.c This patch fixes the "alignment should match open parenthesis" checks from the checkpatch script. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 3c36653..9ed858d 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -110,9 +110,10 @@ static int virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state); static void doDiskAddRemove(struct work_struct *work); static void virthba_serverdown_complete(struct work_struct *work); static ssize_t info_debugfs_read(struct file *file, char __user *buf, - size_t len, loff_t *offset); + size_t len, loff_t *offset); static ssize_t enable_ints_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos); + const char __user *buffer, size_t count, + loff_t *ppos); /*****************************************************/ /* Globals */ @@ -994,17 +995,17 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, cmdrsp->scsi.gpi_list[i].length = sg->length; if ((i != 0) && (sg->offset != 0)) LOGINF("Offset on a sg_entry other than zero =<<%d>>.\n", - sg->offset); + sg->offset); } if (sg_failed) { LOGERR("Start sg_list dump (entries %d, bufflen %d)...\n", - scsi_sg_count(scsicmd), cmdrsp->scsi.bufflen); + scsi_sg_count(scsicmd), cmdrsp->scsi.bufflen); for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) { LOGERR(" Entry(%d): page->[0x%p], phys->[0x%Lx], off(%d), len(%d)\n", - i, sg_page(sg), - (unsigned long long)sg_phys(sg), - sg->offset, sg->length); + i, sg_page(sg), + (unsigned long long)sg_phys(sg), + sg->offset, sg->length); } LOGERR("Done sg_list dump.\n"); /* BUG(); ***** For now, let it fail in uissd @@ -1148,8 +1149,8 @@ do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) if (atomic_read(&vdisk->error_count) == VIRTHBA_ERROR_COUNT) { LOGERR("Throtling SCSICMD errors disk <%d:%d:%d:%llu>\n", - scsidev->host->host_no, scsidev->id, - scsidev->channel, scsidev->lun); + scsidev->host->host_no, scsidev->id, + scsidev->channel, scsidev->lun); } atomic_set(&vdisk->ios_threshold, IOS_ERROR_THRESHOLD); } @@ -1198,7 +1199,7 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) sg = scsi_sglist(scsicmd); for (i = 0; i < scsi_sg_count(scsicmd); i++) { DBGVER("copying OUT OF buf into 0x%p %d\n", - sg_page(sg + i), sg[i].length); + sg_page(sg + i), sg[i].length); thispage_orig = kmap_atomic(sg_page(sg + i)); thispage = (void *)((unsigned long)thispage_orig | sg[i].offset); @@ -1267,7 +1268,7 @@ complete_taskmgmt_command(struct uiscmdrsp *cmdrsp) static void drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, - struct uiscmdrsp *cmdrsp) + struct uiscmdrsp *cmdrsp) { unsigned long flags; int qrslt = 0; @@ -1277,7 +1278,7 @@ drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, while (1) { spin_lock_irqsave(&virthbainfo->chinfo.insertlock, flags); if (!spar_channel_client_acquire_os(dc->queueinfo->chan, - "vhba")) { + "vhba")) { spin_unlock_irqrestore(&virthbainfo->chinfo.insertlock, flags); virthbainfo->acquire_failed_cnt++; @@ -1347,7 +1348,7 @@ process_incoming_rsps(void *v) while (1) { wait_event_interruptible_timeout(virthbainfo->rsp_queue, (atomic_read(&virthbainfo->interrupt_rcvd) == 1), - usecs_to_jiffies(rsltq_wait_usecs)); + usecs_to_jiffies(rsltq_wait_usecs)); atomic_set(&virthbainfo->interrupt_rcvd, 0); /* drain queue */ drain_queue(virthbainfo, dc, cmdrsp); @@ -1367,7 +1368,7 @@ process_incoming_rsps(void *v) /*****************************************************/ static ssize_t info_debugfs_read(struct file *file, - char __user *buf, size_t len, loff_t *offset) + char __user *buf, size_t len, loff_t *offset) { ssize_t bytes_read = 0; int str_pos = 0; @@ -1418,8 +1419,8 @@ static ssize_t info_debugfs_read(struct file *file, return bytes_read; } -static ssize_t enable_ints_write(struct file *file, - const char __user *buffer, size_t count, loff_t *ppos) +static ssize_t enable_ints_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) { char buf[4]; int i, new_value; @@ -1659,13 +1660,13 @@ virthba_mod_init(void) /* create the debugfs directories and entries */ virthba_debugfs_dir = debugfs_create_dir("virthba", NULL); debugfs_create_file("info", S_IRUSR, virthba_debugfs_dir, - NULL, &debugfs_info_fops); + NULL, &debugfs_info_fops); debugfs_create_u32("rqwait_usecs", S_IRUSR | S_IWUSR, - virthba_debugfs_dir, &rsltq_wait_usecs); + virthba_debugfs_dir, &rsltq_wait_usecs); debugfs_create_file("enable_ints", S_IWUSR, - virthba_debugfs_dir, NULL, - &debugfs_enable_ints_fops); - /* Initialize DARWorkQ */ + virthba_debugfs_dir, NULL, + &debugfs_enable_ints_fops); + /* Initialize dar_work_queue */ INIT_WORK(&DARWorkQ, doDiskAddRemove); spin_lock_init(&DARWorkQLock); -- cgit v0.10.2 From 45104bf9937d3d2751872ef091d3a2dbf7b524aa Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:09 -0500 Subject: staging: unisys: Fix logical continuation checks in virthba.c This patch fixes checkpatch checks where the logical operator should be at the end of the line above, not beginning the next line. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 9ed858d..7dd9573 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -430,8 +430,8 @@ virthba_ISR(int irq, void *dev_id) virthbainfo->interrupts_rcvd++; pChannelHeader = virthbainfo->chinfo.queueinfo->chan; if (((readq(&pChannelHeader->features) - & ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS) != 0) - && ((readq(&pChannelHeader->features) & + & ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS) != 0) && + ((readq(&pChannelHeader->features) & ULTRA_IO_DRIVER_DISABLES_INTS) != 0)) { virthbainfo->interrupts_disabled++; @@ -808,9 +808,9 @@ virthba_abort_handler(struct scsi_cmnd *scsicmd) scsidev = scsicmd->device; for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel == vdisk->channel) - && (scsidev->id == vdisk->id) - && (scsidev->lun == vdisk->lun)) { + if ((scsidev->channel == vdisk->channel) && + (scsidev->id == vdisk->id) && + (scsidev->lun == vdisk->lun)) { if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) { atomic_inc(&vdisk->error_count); @@ -834,9 +834,9 @@ virthba_bus_reset_handler(struct scsi_cmnd *scsicmd) scsidev = scsicmd->device; for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel == vdisk->channel) - && (scsidev->id == vdisk->id) - && (scsidev->lun == vdisk->lun)) { + if ((scsidev->channel == vdisk->channel) && + (scsidev->id == vdisk->id) && + (scsidev->lun == vdisk->lun)) { if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) { atomic_inc(&vdisk->error_count); @@ -860,9 +860,9 @@ virthba_device_reset_handler(struct scsi_cmnd *scsicmd) scsidev = scsicmd->device; for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel == vdisk->channel) - && (scsidev->id == vdisk->id) - && (scsidev->lun == vdisk->lun)) { + if ((scsidev->channel == vdisk->channel) && + (scsidev->id == vdisk->id) && + (scsidev->lun == vdisk->lun)) { if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) { atomic_inc(&vdisk->error_count); @@ -1132,9 +1132,9 @@ do_scsi_linuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) /* Okay see what our error_count is here.... */ for (vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel != vdisk->channel) - || (scsidev->id != vdisk->id) - || (scsidev->lun != vdisk->lun)) + if ((scsidev->channel != vdisk->channel) || + (scsidev->id != vdisk->id) || + (scsidev->lun != vdisk->lun)) continue; if (atomic_read(&vdisk->error_count) < VIRTHBA_ERROR_COUNT) { @@ -1170,8 +1170,8 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) struct virtdisk_info *vdisk; scsidev = scsicmd->device; - if ((cmdrsp->scsi.cmnd[0] == INQUIRY) - && (cmdrsp->scsi.bufflen >= MIN_INQUIRY_RESULT_LEN)) { + if ((cmdrsp->scsi.cmnd[0] == INQUIRY) && + (cmdrsp->scsi.bufflen >= MIN_INQUIRY_RESULT_LEN)) { if (cmdrsp->scsi.no_disk_result == 0) return; @@ -1211,9 +1211,9 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; for ( ; vdisk->next; vdisk = vdisk->next) { - if ((scsidev->channel != vdisk->channel) - || (scsidev->id != vdisk->id) - || (scsidev->lun != vdisk->lun)) + if ((scsidev->channel != vdisk->channel) || + (scsidev->id != vdisk->id) || + (scsidev->lun != vdisk->lun)) continue; if (atomic_read(&vdisk->ios_threshold) > 0) { -- cgit v0.10.2 From 79b8cc83af5ae7314c25a7640e8abd03d2e90fae Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:10 -0500 Subject: staging: unisys: Remove blank lines before/after braces in virthba.c This patch removes unnecessary blank lines either before opening braces or after closing braces, as reported by the checkpatch script. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 7dd9573..3ebbbcb 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -990,7 +990,6 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, sgl = scsi_sglist(scsicmd); for_each_sg(sgl, sg, scsi_sg_count(scsicmd), i) { - cmdrsp->scsi.gpi_list[i].address = sg_phys(sg); cmdrsp->scsi.gpi_list[i].length = sg->length; if ((i != 0) && (sg->offset != 0)) @@ -1208,7 +1207,6 @@ do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp, struct scsi_cmnd *scsicmd) bufind += sg[i].length; } } else { - vdisk = &((struct virthba_info *)scsidev->host->hostdata)->head; for ( ; vdisk->next; vdisk = vdisk->next) { if ((scsidev->channel != vdisk->channel) || @@ -1656,7 +1654,6 @@ virthba_mod_init(void) POSTCODE_LINUX_3(VHBA_CREATE_FAILURE_PC, error, POSTCODE_SEVERITY_ERR); } else { - /* create the debugfs directories and entries */ virthba_debugfs_dir = debugfs_create_dir("virthba", NULL); debugfs_create_file("info", S_IRUSR, virthba_debugfs_dir, @@ -1747,7 +1744,6 @@ virthba_mod_exit(void) debugfs_remove_recursive(virthba_debugfs_dir); LOGINF("Leaving virthba_mod_exit\n"); - } /* specify function to be run at module insertion time */ -- cgit v0.10.2 From c7553dad93107f0450be2733b3f62d3d77d17bf9 Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:11 -0500 Subject: staging: unisys: Change alloc calls to use var name instead of type in virthba.c This patch changes a couple of kzalloc calls to pass the variable name to the call, rather than the variable struct type. This is a result of checks generated during the checkpatch script. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 3ebbbcb..28d11af 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -398,7 +398,7 @@ process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp) struct diskaddremove *dar; unsigned long flags; - dar = kzalloc(sizeof(struct diskaddremove), GFP_ATOMIC); + dar = kzalloc(sizeof(*dar), GFP_ATOMIC); if (dar) { dar->add = cmdrsp->disknotify.add; dar->shost = shost; @@ -1061,7 +1061,7 @@ virthba_slave_alloc(struct scsi_device *scsidev) (vdisk->next->lun == scsidev->lun)) return 0; } - tmpvdisk = kzalloc(sizeof(struct virtdisk_info), GFP_ATOMIC); + tmpvdisk = kzalloc(sizeof(*tmpvdisk), GFP_ATOMIC); if (!tmpvdisk) { /* error allocating */ LOGERR("Could not allocate memory for disk\n"); return 0; -- cgit v0.10.2 From 1cc598c75b72174d125ea2a7568cd231ba9fed27 Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:12 -0500 Subject: staging: unisys: fix checkpatch checks for structs in virthba.c This patch fixes a couple small issues reported by the checkpatch script: Adds a blank line after a struct definition. Removes unnecessary parentheses surrounding a dereference of a struct member. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 28d11af..55017f5d 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -166,6 +166,7 @@ struct virtdisk_info { atomic_t error_count; struct virtdisk_info *next; }; + /* Each Scsi_Host has a host_data area that contains this struct. */ struct virthba_info { struct Scsi_Host *scsihost; @@ -1534,7 +1535,7 @@ virthba_serverdown_complete(struct work_struct *work) /* Fail Commands that weren't completed */ spin_lock_irqsave(&virthbainfo->privlock, flags); for (i = 0; i < MAX_PENDING_REQUESTS; i++) { - pendingdel = &(virthbainfo->pending[i]); + pendingdel = &virthbainfo->pending[i]; switch (pendingdel->cmdtype) { case CMD_SCSI_TYPE: scsicmd = (struct scsi_cmnd *)pendingdel->sent; -- cgit v0.10.2 From 20078e4859dc0776c7e76c97adaebcf15a0f98de Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:13 -0500 Subject: staging: unisys: Fix "else not useful after return" warning in virthba.c This patch fixes a warning generated during the checkpatch script that stated "else not useful after return". I modified the code to return a designated status at the end of the function, and replaced the return statement in the "else if" to set the status accordingly. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 55017f5d..30c62fb 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -1584,6 +1584,8 @@ virthba_serverdown_complete(struct work_struct *work) static int virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state) { + int stat = 1; + struct virthba_info *virthbainfo = (struct virthba_info *)((struct Scsi_Host *)virtpcidev->scsi. scsihost)->hostdata; @@ -1598,11 +1600,12 @@ virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state) &virthbainfo->serverdown_completion); } else if (virthbainfo->serverchangingstate) { LOGERR("Server already processing change state message\n"); - return 0; - } else + stat = 0; + } else { LOGERR("Server already down, but another server down message received."); + } - return 1; + return stat; } /*****************************************************/ -- cgit v0.10.2 From fb649950f9342c11b2b4d595f257bb1b909e3b96 Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:14 -0500 Subject: staging: unisys: Fix warnings regarding lines over 80 characters in virthba.c This patch fixes warnings generated by checkpatch script regarding lines over 80 characters long. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 30c62fb..9a6e67d 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -85,7 +85,8 @@ static int virthba_host_reset_handler(struct scsi_cmnd *scsicmd); static const char *virthba_get_info(struct Scsi_Host *shp); static int virthba_ioctl(struct scsi_device *dev, int cmd, void __user *arg); static int virthba_queue_command_lck(struct scsi_cmnd *scsicmd, - void (*virthba_cmnd_done)(struct scsi_cmnd *)); + void (*virthba_cmnd_done) + (struct scsi_cmnd *)); static const struct x86_cpu_id unisys_spar_ids[] = { { X86_VENDOR_INTEL, 6, 62, X86_FEATURE_ANY }, -- cgit v0.10.2 From a57fc10e8d284c16f4eb43403ddfa2626266e8ac Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:15 -0500 Subject: staging: unisys: Fix open parenthesis alignment issues in virthba.c This patch fixes a couple checkpatch checks where alignment of the parameters did not match the open parenthesis of the function. Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 9a6e67d..ee11d89 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -1295,7 +1295,8 @@ drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, * deletion */ scsicmd = del_scsipending_entry(virthbainfo, - (uintptr_t)cmdrsp->scsi.scsicmd); + (uintptr_t) + cmdrsp->scsi.scsicmd); if (!scsicmd) break; /* complete the orig cmd */ @@ -1314,7 +1315,8 @@ drain_queue(struct virthba_info *virthbainfo, struct chaninfo *dc, process_disk_notify(shost, cmdrsp); } else if (cmdrsp->cmdtype == CMD_VDISKMGMT_TYPE) { if (!del_scsipending_entry(virthbainfo, - (uintptr_t)cmdrsp->vdiskmgmt.scsicmd)) + (uintptr_t) + cmdrsp->vdiskmgmt.scsicmd)) break; complete_vdiskmgmt_command(cmdrsp); } else -- cgit v0.10.2 From 83afa3493d6b52614ea57b9bfeab0286bf578f9a Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:16 -0500 Subject: staging: unisys: Fix CamelCase for Disk Add/Remove global variables in virthba.c This patch fixes the Disk Add/Remove (DAR) related CamelCase global variables in virthba.c, reported by the checkpatch script: DARWorkQ --> dar_work_queue DARWorkQHead --> dar_work_queue_head DARWorkQLock --> dar_work_queue_lock DARWorkQSched --> dar_work_queue_sched Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index ee11d89..5176e35 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -196,7 +196,7 @@ struct virthba_info { struct virtdisk_info head; }; -/* Work Data for DARWorkQ */ +/* Work Data for dar_work_queue */ struct diskaddremove { u8 add; /* 0-remove, 1-add */ struct Scsi_Host *shost; /* Scsi Host for this virthba instance */ @@ -321,26 +321,26 @@ del_scsipending_entry(struct virthba_info *vhbainfo, uintptr_t del) return sent; } -/* DARWorkQ (Disk Add/Remove) */ -static struct work_struct DARWorkQ; -static struct diskaddremove *DARWorkQHead; -static spinlock_t DARWorkQLock; -static unsigned short DARWorkQSched; +/* dar_work_queue (Disk Add/Remove) */ +static struct work_struct dar_work_queue; +static struct diskaddremove *dar_work_queue_head; +static spinlock_t dar_work_queue_lock; +static unsigned short dar_work_queue_sched; #define QUEUE_DISKADDREMOVE(dar) { \ - spin_lock_irqsave(&DARWorkQLock, flags); \ - if (!DARWorkQHead) { \ - DARWorkQHead = dar; \ + spin_lock_irqsave(&dar_work_queue_lock, flags); \ + if (!dar_work_queue_head) { \ + dar_work_queue_head = dar; \ dar->next = NULL; \ } \ else { \ - dar->next = DARWorkQHead; \ - DARWorkQHead = dar; \ + dar->next = dar_work_queue_head; \ + dar_work_queue_head = dar; \ } \ - if (!DARWorkQSched) { \ - schedule_work(&DARWorkQ); \ - DARWorkQSched = 1; \ + if (!dar_work_queue_sched) { \ + schedule_work(&dar_work_queue); \ + dar_work_queue_sched = 1; \ } \ - spin_unlock_irqrestore(&DARWorkQLock, flags); \ + spin_unlock_irqrestore(&dar_work_queue_lock, flags); \ } static inline void @@ -368,7 +368,7 @@ SendDiskAddRemove(struct diskaddremove *dar) } /*****************************************************/ -/* DARWorkQ Handler Thread */ +/* dar_work_queue Handler Thread */ /*****************************************************/ static void doDiskAddRemove(struct work_struct *work) @@ -378,11 +378,11 @@ doDiskAddRemove(struct work_struct *work) int i = 0; unsigned long flags; - spin_lock_irqsave(&DARWorkQLock, flags); - tmphead = DARWorkQHead; - DARWorkQHead = NULL; - DARWorkQSched = 0; - spin_unlock_irqrestore(&DARWorkQLock, flags); + spin_lock_irqsave(&dar_work_queue_lock, flags); + tmphead = dar_work_queue_head; + dar_work_queue_head = NULL; + dar_work_queue_sched = 0; + spin_unlock_irqrestore(&dar_work_queue_lock, flags); while (tmphead) { dar = tmphead; tmphead = dar->next; @@ -392,7 +392,7 @@ doDiskAddRemove(struct work_struct *work) } /*****************************************************/ -/* Routine to add entry to DARWorkQ */ +/* Routine to add entry to dar_work_queue */ /*****************************************************/ static void process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp) @@ -1671,8 +1671,8 @@ virthba_mod_init(void) virthba_debugfs_dir, NULL, &debugfs_enable_ints_fops); /* Initialize dar_work_queue */ - INIT_WORK(&DARWorkQ, doDiskAddRemove); - spin_lock_init(&DARWorkQLock); + INIT_WORK(&dar_work_queue, doDiskAddRemove); + spin_lock_init(&dar_work_queue_lock); /* clear out array */ for (i = 0; i < VIRTHBASOPENMAX; i++) -- cgit v0.10.2 From 366cf71a1354d5c1ba15bd46b839ce37902ea6ff Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:17 -0500 Subject: staging: unisys: Fix remaining CamelCase global variables in virthba.c This patch fixes the remaining CamelCase global variables in virthba.c reported by the checkpatch script: MaxBuffLen --> max_buff_len VirtHbasOpen --> virthbas_open Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 5176e35..a82ceb2 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -121,7 +121,7 @@ static ssize_t enable_ints_write(struct file *file, /*****************************************************/ static int rsltq_wait_usecs = 4000; /* Default 4ms */ -static unsigned int MaxBuffLen; +static unsigned int max_buff_len; /* Module options */ static char *virthba_options = "NONE"; @@ -247,7 +247,7 @@ static const struct file_operations debugfs_enable_ints_fops = { #define VIRTHBASOPENMAX 1 /* array of open devices maintained by open() and close(); */ -static struct virthba_devices_open VirtHbasOpen[VIRTHBASOPENMAX]; +static struct virthba_devices_open virthbas_open[VIRTHBASOPENMAX]; static struct dentry *virthba_debugfs_dir; /*****************************************************/ @@ -550,8 +550,8 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) virthbainfo = (struct virthba_info *)scsihost->hostdata; memset(virthbainfo, 0, sizeof(struct virthba_info)); for (i = 0; i < VIRTHBASOPENMAX; i++) { - if (VirtHbasOpen[i].virthbainfo == NULL) { - VirtHbasOpen[i].virthbainfo = virthbainfo; + if (virthbas_open[i].virthbainfo == NULL) { + virthbas_open[i].virthbainfo = virthbainfo; break; } } @@ -964,8 +964,8 @@ virthba_queue_command_lck(struct scsi_cmnd *scsicmd, cmdrsp->scsi.bufflen = scsi_bufflen(scsicmd); /* keep track of the max buffer length so far. */ - if (cmdrsp->scsi.bufflen > MaxBuffLen) - MaxBuffLen = cmdrsp->scsi.bufflen; + if (cmdrsp->scsi.bufflen > max_buff_len) + max_buff_len = cmdrsp->scsi.bufflen; if (scsi_sg_count(scsicmd) > MAX_PHYS_INFO) { LOGERR("scsicmd use_sg:%d greater than MAX:%d\n", @@ -1386,13 +1386,14 @@ static ssize_t info_debugfs_read(struct file *file, return -ENOMEM; for (i = 0; i < VIRTHBASOPENMAX; i++) { - if (VirtHbasOpen[i].virthbainfo == NULL) + if (virthbas_open[i].virthbainfo == NULL) continue; - virthbainfo = VirtHbasOpen[i].virthbainfo; + virthbainfo = virthbas_open[i].virthbainfo; str_pos += scnprintf(vbuf + str_pos, - len - str_pos, "MaxBuffLen:%u\n", MaxBuffLen); + len - str_pos, "max_buff_len:%u\n", + max_buff_len); str_pos += scnprintf(vbuf + str_pos, len - str_pos, "\nvirthba result queue poll wait:%d usecs.\n", @@ -1451,8 +1452,8 @@ static ssize_t enable_ints_write(struct file *file, const char __user *buffer, /* set all counts to new_value usually 0 */ for (i = 0; i < VIRTHBASOPENMAX; i++) { - if (VirtHbasOpen[i].virthbainfo != NULL) { - virthbainfo = VirtHbasOpen[i].virthbainfo; + if (virthbas_open[i].virthbainfo != NULL) { + virthbainfo = virthbas_open[i].virthbainfo; Features_addr = &virthbainfo->chinfo.queueinfo->chan->features; if (new_value == 1) { @@ -1676,7 +1677,7 @@ virthba_mod_init(void) /* clear out array */ for (i = 0; i < VIRTHBASOPENMAX; i++) - VirtHbasOpen[i].virthbainfo = NULL; + virthbas_open[i].virthbainfo = NULL; /* Initialize the serverdown workqueue */ virthba_serverdown_workqueue = create_singlethread_workqueue("virthba_serverdown"); -- cgit v0.10.2 From b6e0a70898970a6f0d8d3e6e610b4ae96077ad9d Mon Sep 17 00:00:00 2001 From: Ken Depro Date: Tue, 20 Jan 2015 10:01:18 -0500 Subject: staging: unisys: Fix CamelCase for function names in virthba.c This patch fixes CamelCase function names in virthba.c, reported by the checkpatch script: doDiskAddRemove --> do_disk_add_remove SendDiskAddRemove --> send_disk_add_remove Signed-off-by: Ken Depro Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index a82ceb2..63ebc53 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -108,7 +108,7 @@ static void virthba_slave_destroy(struct scsi_device *scsidev); static int process_incoming_rsps(void *); static int virthba_serverup(struct virtpci_dev *virtpcidev); static int virthba_serverdown(struct virtpci_dev *virtpcidev, u32 state); -static void doDiskAddRemove(struct work_struct *work); +static void do_disk_add_remove(struct work_struct *work); static void virthba_serverdown_complete(struct work_struct *work); static ssize_t info_debugfs_read(struct file *file, char __user *buf, size_t len, loff_t *offset); @@ -344,7 +344,7 @@ static unsigned short dar_work_queue_sched; } static inline void -SendDiskAddRemove(struct diskaddremove *dar) +send_disk_add_remove(struct diskaddremove *dar) { struct scsi_device *sdev; int error; @@ -371,7 +371,7 @@ SendDiskAddRemove(struct diskaddremove *dar) /* dar_work_queue Handler Thread */ /*****************************************************/ static void -doDiskAddRemove(struct work_struct *work) +do_disk_add_remove(struct work_struct *work) { struct diskaddremove *dar; struct diskaddremove *tmphead; @@ -386,7 +386,7 @@ doDiskAddRemove(struct work_struct *work) while (tmphead) { dar = tmphead; tmphead = dar->next; - SendDiskAddRemove(dar); + send_disk_add_remove(dar); i++; } } @@ -1672,7 +1672,7 @@ virthba_mod_init(void) virthba_debugfs_dir, NULL, &debugfs_enable_ints_fops); /* Initialize dar_work_queue */ - INIT_WORK(&dar_work_queue, doDiskAddRemove); + INIT_WORK(&dar_work_queue, do_disk_add_remove); spin_lock_init(&dar_work_queue_lock); /* clear out array */ -- cgit v0.10.2 From 347d05604f760fe1cc7814e44b2cbc7cac237b27 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Tue, 20 Jan 2015 10:01:19 -0500 Subject: staging: unisys: refactor virthba_ISR() Fix CamelCase names: virthba_ISR => virthba_isr pChannelHeader => channel_header Update all references to the modified names. Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 63ebc53..400bb7a 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -419,10 +419,10 @@ process_disk_notify(struct Scsi_Host *shost, struct uiscmdrsp *cmdrsp) /* Probe Remove Functions */ /*****************************************************/ static irqreturn_t -virthba_ISR(int irq, void *dev_id) +virthba_isr(int irq, void *dev_id) { struct virthba_info *virthbainfo = (struct virthba_info *)dev_id; - struct channel_header __iomem *pChannelHeader; + struct channel_header __iomem *channel_header; struct signal_queue_header __iomem *pqhdr; u64 mask; unsigned long long rc1; @@ -430,23 +430,23 @@ virthba_ISR(int irq, void *dev_id) if (virthbainfo == NULL) return IRQ_NONE; virthbainfo->interrupts_rcvd++; - pChannelHeader = virthbainfo->chinfo.queueinfo->chan; - if (((readq(&pChannelHeader->features) + channel_header = virthbainfo->chinfo.queueinfo->chan; + if (((readq(&channel_header->features) & ULTRA_IO_IOVM_IS_OK_WITH_DRIVER_DISABLING_INTS) != 0) && - ((readq(&pChannelHeader->features) & + ((readq(&channel_header->features) & ULTRA_IO_DRIVER_DISABLES_INTS) != 0)) { virthbainfo->interrupts_disabled++; mask = ~ULTRA_CHANNEL_ENABLE_INTS; rc1 = uisqueue_interlocked_and(virthbainfo->flags_addr, mask); } - if (spar_signalqueue_empty(pChannelHeader, IOCHAN_FROM_IOPART)) { + if (spar_signalqueue_empty(channel_header, IOCHAN_FROM_IOPART)) { virthbainfo->interrupts_notme++; return IRQ_NONE; } pqhdr = (struct signal_queue_header __iomem *) - ((char __iomem *)pChannelHeader + - readq(&pChannelHeader->ch_space_offset)) + IOCHAN_FROM_IOPART; + ((char __iomem *)channel_header + + readq(&channel_header->ch_space_offset)) + IOCHAN_FROM_IOPART; writeq(readq(&pqhdr->num_irq_received) + 1, &pqhdr->num_irq_received); atomic_set(&virthbainfo->interrupt_rcvd, 1); @@ -462,7 +462,7 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) struct virthba_info *virthbainfo; int rsp; int i; - irq_handler_t handler = virthba_ISR; + irq_handler_t handler = virthba_isr; struct channel_header __iomem *pChannelHeader; struct signal_queue_header __iomem *pqhdr; u64 mask; -- cgit v0.10.2 From 1789377089ac827f150cd2751c00b32d37e6a3b4 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Tue, 20 Jan 2015 10:01:20 -0500 Subject: staging: unisys: fix CamelCase name in virthba_probe() Fix CamelCase local variable name: pChannelHeader => channel_header Update references to use the new name. Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 400bb7a..ff780c9 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -463,7 +463,7 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) int rsp; int i; irq_handler_t handler = virthba_isr; - struct channel_header __iomem *pChannelHeader; + struct channel_header __iomem *channel_header; struct signal_queue_header __iomem *pqhdr; u64 mask; @@ -587,10 +587,10 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) DBGINF("starting rsp thread -- queueinfo: 0x%p, threadinfo: 0x%p.\n", virthbainfo->chinfo.queueinfo, &virthbainfo->chinfo.threadinfo); - pChannelHeader = virthbainfo->chinfo.queueinfo->chan; + channel_header = virthbainfo->chinfo.queueinfo->chan; pqhdr = (struct signal_queue_header __iomem *) - ((char __iomem *)pChannelHeader + - readq(&pChannelHeader->ch_space_offset)) + IOCHAN_FROM_IOPART; + ((char __iomem *)channel_header + + readq(&channel_header->ch_space_offset)) + IOCHAN_FROM_IOPART; virthbainfo->flags_addr = &pqhdr->features; if (!uisthread_start(&virthbainfo->chinfo.threadinfo, -- cgit v0.10.2 From 05f3598025aff4eac95a74e31f5f56e99aaa098b Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Tue, 20 Jan 2015 10:01:21 -0500 Subject: staging: unisys: fix CamelCase in enable_ints_write() Fix CamelCase variable name: Features_addr => features_addr Update references to use the new name. Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index ff780c9..8cd090b 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -1429,7 +1429,7 @@ static ssize_t enable_ints_write(struct file *file, const char __user *buffer, int i, new_value; struct virthba_info *virthbainfo; - u64 __iomem *Features_addr; + u64 __iomem *features_addr; u64 mask; if (count >= ARRAY_SIZE(buf)) @@ -1454,21 +1454,21 @@ static ssize_t enable_ints_write(struct file *file, const char __user *buffer, for (i = 0; i < VIRTHBASOPENMAX; i++) { if (virthbas_open[i].virthbainfo != NULL) { virthbainfo = virthbas_open[i].virthbainfo; - Features_addr = + features_addr = &virthbainfo->chinfo.queueinfo->chan->features; if (new_value == 1) { mask = ~(ULTRA_IO_CHANNEL_IS_POLLING | ULTRA_IO_DRIVER_DISABLES_INTS); - uisqueue_interlocked_and(Features_addr, mask); + uisqueue_interlocked_and(features_addr, mask); mask = ULTRA_IO_DRIVER_ENABLES_INTS; - uisqueue_interlocked_or(Features_addr, mask); + uisqueue_interlocked_or(features_addr, mask); rsltq_wait_usecs = 4000000; } else { mask = ~(ULTRA_IO_DRIVER_ENABLES_INTS | ULTRA_IO_DRIVER_DISABLES_INTS); - uisqueue_interlocked_and(Features_addr, mask); + uisqueue_interlocked_and(features_addr, mask); mask = ULTRA_IO_CHANNEL_IS_POLLING; - uisqueue_interlocked_or(Features_addr, mask); + uisqueue_interlocked_or(features_addr, mask); rsltq_wait_usecs = 4000; } } -- cgit v0.10.2 From 9994c9777d903e02b6aa44c77bab67702044e72e Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 18 Jan 2015 01:41:23 +0100 Subject: staging: rtl8723au: os_dep: usb_intf: Remove unused functions Removes some functions that are not used anywhere: rtw_hw_resume23a() rtw_hw_suspend23a() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/include/osdep_intf.h b/drivers/staging/rtl8723au/include/osdep_intf.h index 33afa62..a157eb2 100644 --- a/drivers/staging/rtl8723au/include/osdep_intf.h +++ b/drivers/staging/rtl8723au/include/osdep_intf.h @@ -19,9 +19,6 @@ #include #include -int rtw_hw_suspend23a(struct rtw_adapter *padapter); -int rtw_hw_resume23a(struct rtw_adapter *padapter); - int rtw_init_drv_sw23a(struct rtw_adapter *padapter); int rtw_free_drv_sw23a(struct rtw_adapter *padapter); int rtw_reset_drv_sw23a(struct rtw_adapter *padapter); diff --git a/drivers/staging/rtl8723au/os_dep/usb_intf.c b/drivers/staging/rtl8723au/os_dep/usb_intf.c index 5007349..05755b8 100644 --- a/drivers/staging/rtl8723au/os_dep/usb_intf.c +++ b/drivers/staging/rtl8723au/os_dep/usb_intf.c @@ -267,104 +267,6 @@ static void rtw_dev_unload(struct rtw_adapter *padapter) RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n")); } -int rtw_hw_suspend23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct net_device *pnetdev = padapter->pnetdev; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if ((!padapter->bup) || (padapter->bDriverStopped) || - (padapter->bSurpriseRemoved)) { - DBG_8723A("padapter->bup =%d bDriverStopped =%d bSurpriseRemoved = %d\n", - padapter->bup, padapter->bDriverStopped, - padapter->bSurpriseRemoved); - goto error_exit; - } - - if (padapter) { /* system suspend */ - LeaveAllPowerSaveMode23a(padapter); - - DBG_8723A("==> rtw_hw_suspend23a\n"); - down(&pwrpriv->lock); - pwrpriv->bips_processing = true; - /* padapter->net_closed = true; */ - /* s1. */ - if (pnetdev) { - netif_carrier_off(pnetdev); - netif_tx_stop_all_queues(pnetdev); - } - - /* s2. */ - rtw_disassoc_cmd23a(padapter, 500, false); - - /* s2-2. indicate disconnect to os */ - /* rtw_indicate_disconnect23a(padapter); */ - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - _clr_fwstate_(pmlmepriv, _FW_LINKED); - - rtw_os_indicate_disconnect23a(padapter); - - /* donnot enqueue cmd */ - rtw_lps_ctrl_wk_cmd23a(padapter, - LPS_CTRL_DISCONNECT, 0); - } - /* s2-3. */ - rtw_free_assoc_resources23a(padapter, 1); - - /* s2-4. */ - rtw_free_network_queue23a(padapter); - rtw_ips_dev_unload23a(padapter); - pwrpriv->rf_pwrstate = rf_off; - pwrpriv->bips_processing = false; - up(&pwrpriv->lock); - } else { - goto error_exit; - } - return 0; -error_exit: - DBG_8723A("%s, failed\n", __func__); - return -1; -} - -int rtw_hw_resume23a(struct rtw_adapter *padapter) -{ - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct net_device *pnetdev = padapter->pnetdev; - - if (padapter) { /* system resume */ - DBG_8723A("==> rtw_hw_resume23a\n"); - down(&pwrpriv->lock); - pwrpriv->bips_processing = true; - rtw_reset_drv_sw23a(padapter); - - if (pm_netdev_open23a(pnetdev, false)) { - up(&pwrpriv->lock); - goto error_exit; - } - - netif_device_attach(pnetdev); - netif_carrier_on(pnetdev); - - if (!rtw_netif_queue_stopped(pnetdev)) - netif_tx_start_all_queues(pnetdev); - else - netif_tx_wake_all_queues(pnetdev); - - pwrpriv->bkeepfwalive = false; - - pwrpriv->rf_pwrstate = rf_on; - pwrpriv->bips_processing = false; - - up(&pwrpriv->lock); - } else { - goto error_exit; - } - return 0; -error_exit: - DBG_8723A("%s, Open net dev failed\n", __func__); - return -1; -} - static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) { struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); -- cgit v0.10.2 From cd480ed64333f2a92435d0f171f7837b00de5bcf Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 18 Jan 2015 01:59:09 +0100 Subject: staging: rtl8723au: core: rtw_cmd: Remove unused functions Removes some functions that are not used anywhere: rtw_set_ch_cmd23a() rtw_cmd_clr_isr23a() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/core/rtw_cmd.c b/drivers/staging/rtl8723au/core/rtw_cmd.c index 60e0ded..2447a56 100644 --- a/drivers/staging/rtl8723au/core/rtw_cmd.c +++ b/drivers/staging/rtl8723au/core/rtw_cmd.c @@ -245,11 +245,6 @@ exit: return res; } -void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv) -{ - pcmdpriv->cmd_done_cnt++; -} - void rtw_free_cmd_obj23a(struct cmd_obj *pcmd) { @@ -852,62 +847,6 @@ exit: return res; } -/* - * This is only ever called from on_action_spct23a_ch_switch () which isn't - * called from anywhere itself - */ -int rtw_set_ch_cmd23a(struct rtw_adapter *padapter, u8 ch, u8 bw, u8 ch_offset, - u8 enqueue) -{ - struct cmd_obj *pcmdobj; - struct set_ch_parm *set_ch_parm; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - int res = _SUCCESS; - - DBG_8723A("%s(%s): ch:%u, bw:%u, ch_offset:%u\n", __func__, - padapter->pnetdev->name, ch, bw, ch_offset); - - /* check input parameter */ - - /* prepare cmd parameter */ - set_ch_parm = kzalloc(sizeof(*set_ch_parm), GFP_KERNEL); - if (!set_ch_parm) { - res = _FAIL; - goto exit; - } - set_ch_parm->ch = ch; - set_ch_parm->bw = bw; - set_ch_parm->ch_offset = ch_offset; - - if (enqueue) { - /* need enqueue, prepare cmd_obj and enqueue */ - pcmdobj = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL); - if (!pcmdobj) { - kfree(set_ch_parm); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, - GEN_CMD_CODE(_SetChannel)); - res = rtw_enqueue_cmd23a(pcmdpriv, pcmdobj); - } else { - /* no need to enqueue, do the cmd hdl directly and - free cmd parameter */ - if (H2C_SUCCESS != set_ch_hdl23a(padapter, (u8 *)set_ch_parm)) - res = _FAIL; - - kfree(set_ch_parm); - } - - /* do something based on res... */ -exit: - - DBG_8723A("%s(%s): res:%u\n", __func__, padapter->pnetdev->name, res); - - return res; -} - static void traffic_status_watchdog(struct rtw_adapter *padapter) { u8 bEnterPS; diff --git a/drivers/staging/rtl8723au/include/rtw_cmd.h b/drivers/staging/rtl8723au/include/rtw_cmd.h index 92c8ec4..775dcdc 100644 --- a/drivers/staging/rtl8723au/include/rtw_cmd.h +++ b/drivers/staging/rtl8723au/include/rtw_cmd.h @@ -99,7 +99,6 @@ int rtw_init_cmd_priv23a(struct cmd_priv *pcmdpriv); u32 rtw_init_evt_priv23a (struct evt_priv *pevtpriv); void rtw_free_evt_priv23a (struct evt_priv *pevtpriv); -void rtw_cmd_clr_isr23a(struct cmd_priv *pcmdpriv); void rtw_evt_notify_isr(struct evt_priv *pevtpriv); enum rtw_drvextra_cmd_id @@ -713,7 +712,6 @@ int rtw_ps_cmd23a(struct rtw_adapter*padapter); int rtw_chk_hi_queue_cmd23a(struct rtw_adapter*padapter); #endif -int rtw_set_ch_cmd23a(struct rtw_adapter*padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue); int rtw_set_chplan_cmd(struct rtw_adapter*padapter, u8 chplan, u8 enqueue); int rtw_led_blink_cmd(struct rtw_adapter*padapter, struct led_8723a *pLed); int rtw_set_csa_cmd(struct rtw_adapter*padapter, u8 new_ch_no); -- cgit v0.10.2 From b086d02b444dae1a0ba917abfb8ab0a88dafbf8b Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 18 Jan 2015 02:07:23 +0100 Subject: staging: rtl8712: recv_linux: Remove unused function Remove the function r8712_os_read_port() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 0631f36..409c8c8 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -137,20 +137,6 @@ _recv_indicatepkt_drop: precvpriv->rx_drop++; } -void r8712_os_read_port(struct _adapter *padapter, struct recv_buf *precvbuf) -{ - struct recv_priv *precvpriv = &padapter->recvpriv; - - precvbuf->ref_cnt--; - /*free skb in recv_buf*/ - dev_kfree_skb_any(precvbuf->pskb); - precvbuf->pskb = NULL; - precvbuf->reuse = false; - if (!precvbuf->irp_pending) - r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, - (unsigned char *)precvbuf); -} - static void _r8712_reordering_ctrl_timeout_handler (void *FunctionContext) { struct recv_reorder_ctrl *preorder_ctrl = diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h index f4384ef..1f4986e 100644 --- a/drivers/staging/rtl8712/recv_osdep.h +++ b/drivers/staging/rtl8712/recv_osdep.h @@ -46,7 +46,6 @@ int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, struct recv_buf *precvbuf); int r8712_os_recvbuf_resource_free(struct _adapter *padapter, struct recv_buf *precvbuf); -void r8712_os_read_port(struct _adapter *padapter, struct recv_buf *precvbuf); void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl); #endif -- cgit v0.10.2 From b3b366410a4b6f34932053b710734bc5bf912a02 Mon Sep 17 00:00:00 2001 From: Peter Poklop Date: Mon, 19 Jan 2015 18:26:53 +0100 Subject: Staging: rtl8723au: fix space coding style issue in os_intfs.c This patch fixes the checkpatch.pl warning: WARNING: space prohibited before semicolon Signed-off-by: Peter Poklop Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/os_dep/os_intfs.c b/drivers/staging/rtl8723au/os_dep/os_intfs.c index 9966d16..1b23eb1 100644 --- a/drivers/staging/rtl8723au/os_dep/os_intfs.c +++ b/drivers/staging/rtl8723au/os_dep/os_intfs.c @@ -91,7 +91,7 @@ static int rtw_bt_iso = 2;/* 0:Low, 1:High, 2:From Efuse */ /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter, 4.Busy, 5.OtherBusy */ static int rtw_bt_sco = 3; /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ -static int rtw_bt_ampdu = 1 ; +static int rtw_bt_ampdu = 1; #endif /* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */ -- cgit v0.10.2 From 7046808627793238b8c915af2fd2d185502e9bef Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Thu, 22 Jan 2015 12:09:16 +0530 Subject: staging: rtl8712: remove unused function mp_query_drv_var() was only being used by oid_rt_pro_query_dr_variable_hdl() but after commit mp_query_drv_var() became unused. so it is safe to remove it. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c index 49fa1d1..0b54612 100644 --- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c +++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c @@ -704,13 +704,6 @@ uint oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv) return RNDIS_STATUS_SUCCESS; } -/*--------------------------------------------------------------------------*/ -static u32 mp_query_drv_var(struct _adapter *padapter, u8 offset, u32 var) -{ - return var; -} - -/*------------------------------------------------------------------------*/ uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv) { struct _adapter *Adapter = (struct _adapter *) -- cgit v0.10.2 From a78d131265661bcc6a022b0d0cc4904a58abd362 Mon Sep 17 00:00:00 2001 From: Asaf Vertz Date: Sun, 18 Jan 2015 09:11:39 +0200 Subject: staging: wlan-ng: hfa384x_usb: fix sparse endianness warnings Fixed the following warnings (reported by sparse): drivers/staging/wlan-ng/hfa384x_usb.c:3828:36: warning: cast to restricted __le16 drivers/staging/wlan-ng/hfa384x_usb.c:3229:16: warning: cast to restricted __le16 drivers/staging/wlan-ng/hfa384x_usb.c:3430:18: warning: cast to restricted __le16 drivers/staging/wlan-ng/hfa384x_usb.c:3349:51: warning: restricted __le16 degrades to integer drivers/staging/wlan-ng/hfa384x_usb.c:3357:37: warning: cast to restricted __le16 drivers/staging/wlan-ng/hfa384x_usb.c:3358:37: warning: cast to restricted __le16 drivers/staging/wlan-ng/hfa384x_usb.c:3393:36: warning: cast to restricted __le16 drivers/staging/wlan-ng/hfa384x_usb.c:3102:28: warning: cast to restricted __le16 drivers/staging/wlan-ng/hfa384x_usb.c:3004:28: warning: cast to restricted __le16 drivers/staging/wlan-ng/hfa384x_usb.c:1308:37: warning: cast to restricted __le16 drivers/staging/wlan-ng/hfa384x_usb.c:2713:25: warning: incorrect type in assignment (different base types) drivers/staging/wlan-ng/hfa384x_usb.c:2713:25: expected unsigned short [unsigned] [usertype] type drivers/staging/wlan-ng/hfa384x_usb.c:2713:25: got restricted __le16 [usertype] Signed-off-by: Asaf Vertz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h index 5b7b408..8f20910 100644 --- a/drivers/staging/wlan-ng/hfa384x.h +++ b/drivers/staging/wlan-ng/hfa384x.h @@ -879,7 +879,7 @@ typedef struct hfa384x_usb_error { /* Unions for packaging all the known packet types together */ typedef union hfa384x_usbout { - u16 type; + __le16 type; hfa384x_usb_txfrm_t txfrm; hfa384x_usb_cmdreq_t cmdreq; hfa384x_usb_wridreq_t wridreq; @@ -889,7 +889,7 @@ typedef union hfa384x_usbout { } __packed hfa384x_usbout_t; typedef union hfa384x_usbin { - u16 type; + __le16 type; hfa384x_usb_rxfrm_t rxfrm; hfa384x_usb_txfrm_t txfrm; hfa384x_usb_infofrm_t infofrm; diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 2245339..28cd1c4 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -3346,7 +3346,7 @@ retry: if (unlocked_usbctlx_cancel_async(hw, ctlx) == 0) run_queue = 1; } else { - const u16 intype = (usbin->type & ~cpu_to_le16(0x8000)); + const __le16 intype = (usbin->type & ~cpu_to_le16(0x8000)); /* * Check that our message is what we're expecting ... -- cgit v0.10.2 From 9df56d9bdeeae16af53487d1d4e8d78cd36948bc Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Fri, 23 Jan 2015 08:15:53 +0100 Subject: staging: rts5208: use msecs_to_jiffies for timeouts This is only an API consolidation and should make things more readable Converting milliseconds to jiffies by val * HZ / 1000 is technically not wrong but msecs_to_jiffies(val) is the cleaner solution and handles corner cases correctly. Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c index 756a968..dab1995 100644 --- a/drivers/staging/rts5208/rtsx_transport.c +++ b/drivers/staging/rts5208/rtsx_transport.c @@ -271,7 +271,7 @@ int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout) /* Wait for TRANS_OK_INT */ timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n", chip->int_reg); @@ -431,7 +431,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, spin_unlock_irq(&rtsx->reg_lock); timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", __func__, __LINE__); @@ -455,7 +455,7 @@ static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card, init_completion(&trans_done); spin_unlock_irq(&rtsx->reg_lock); timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", __func__, __LINE__); @@ -575,7 +575,7 @@ static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, spin_unlock_irq(&rtsx->reg_lock); timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", __func__, __LINE__); @@ -602,7 +602,7 @@ static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card, init_completion(&trans_done); spin_unlock_irq(&rtsx->reg_lock); timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", __func__, __LINE__); @@ -688,7 +688,7 @@ static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, /* Wait for TRANS_OK_INT */ timeleft = wait_for_completion_interruptible_timeout( - &trans_done, timeout * HZ / 1000); + &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n", __func__, __LINE__); -- cgit v0.10.2 From 60e27886fd615adc81e810bec23f4b929ab81d0e Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Thu, 22 Jan 2015 20:19:26 +0100 Subject: staging: dgnc: fix long lines in PCI device table This patch fixes coding style of PCI device table declaration. Signed-off-by: Krzysztof Adamski Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index f610ae1..f177d3a 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -97,12 +97,12 @@ static uint dgnc_poll_stop; /* Used to tell poller to stop */ static struct timer_list dgnc_poll_timer; -static struct pci_device_id dgnc_pci_tbl[] = { - { DIGI_VID, PCI_DEVICE_CLASSIC_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { DIGI_VID, PCI_DEVICE_CLASSIC_4_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, - { DIGI_VID, PCI_DEVICE_CLASSIC_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, - { DIGI_VID, PCI_DEVICE_CLASSIC_8_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, - {0,} /* 0 terminated list. */ +static const struct pci_device_id dgnc_pci_tbl[] = { + {PCI_DEVICE(DIGI_VID, PCI_DEVICE_CLASSIC_4_DID), .driver_data = 0}, + {PCI_DEVICE(DIGI_VID, PCI_DEVICE_CLASSIC_4_422_DID), .driver_data = 1}, + {PCI_DEVICE(DIGI_VID, PCI_DEVICE_CLASSIC_8_DID), .driver_data = 2}, + {PCI_DEVICE(DIGI_VID, PCI_DEVICE_CLASSIC_8_422_DID), .driver_data = 3}, + {0,} }; MODULE_DEVICE_TABLE(pci, dgnc_pci_tbl); -- cgit v0.10.2 From 6f6304b85f734dab956cbacc017fcdbe48693d51 Mon Sep 17 00:00:00 2001 From: Andrew Milkovich Date: Sun, 18 Jan 2015 10:41:30 -0800 Subject: Staging: dgnc: fixed some coding style errors This patch fixes the following checkpatch.pl error: ERROR: Macros with complex values should be enclosed in parentheses Outer parentheses were added to macro definitions. Signed-off-by: Andrew Milkovich Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/dgnc/digi.h b/drivers/staging/dgnc/digi.h index 3181a35..d6e0b9f 100644 --- a/drivers/staging/dgnc/digi.h +++ b/drivers/staging/dgnc/digi.h @@ -38,8 +38,8 @@ #if !defined(TIOCMODG) -#define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */ -#define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */ +#define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */ +#define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */ #ifndef TIOCM_LE #define TIOCM_LE 0x01 /* line enable */ @@ -58,44 +58,44 @@ #endif #if !defined(TIOCMSET) -#define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */ -#define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */ +#define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */ +#define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */ #endif #if !defined(TIOCMBIC) -#define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */ -#define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */ +#define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */ +#define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */ #endif #if !defined(TIOCSDTR) -#define TIOCSDTR ('e'<<8) | 0 /* set DTR */ -#define TIOCCDTR ('e'<<8) | 1 /* clear DTR */ +#define TIOCSDTR (('e'<<8) | 0) /* set DTR */ +#define TIOCCDTR (('e'<<8) | 1) /* clear DTR */ #endif /************************************************************************ * Ioctl command arguments for DIGI parameters. ************************************************************************/ -#define DIGI_GETA ('e'<<8) | 94 /* Read params */ +#define DIGI_GETA (('e'<<8) | 94) /* Read params */ -#define DIGI_SETA ('e'<<8) | 95 /* Set params */ -#define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */ -#define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */ +#define DIGI_SETA (('e'<<8) | 95) /* Set params */ +#define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */ +#define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */ -#define DIGI_KME ('e'<<8) | 98 /* Read/Write Host */ +#define DIGI_KME (('e'<<8) | 98) /* Read/Write Host */ /* Adapter Memory */ -#define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */ +#define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */ /* control characters */ -#define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */ +#define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */ /* control characters */ -#define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */ +#define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */ /* flow control chars */ -#define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */ +#define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */ /* flow control chars */ -#define DIGI_GEDELAY ('d'<<8) | 246 /* Get edelay */ -#define DIGI_SEDELAY ('d'<<8) | 247 /* Set edelay */ +#define DIGI_GEDELAY (('d'<<8) | 246) /* Get edelay */ +#define DIGI_SEDELAY (('d'<<8) | 247) /* Set edelay */ struct digiflow_t { unsigned char startc; /* flow cntl start char */ @@ -104,8 +104,8 @@ struct digiflow_t { #ifdef FLOW_2200 -#define F2200_GETA ('e'<<8) | 104 /* Get 2x36 flow cntl flags */ -#define F2200_SETAW ('e'<<8) | 105 /* Set 2x36 flow cntl flags */ +#define F2200_GETA (('e'<<8) | 104) /* Get 2x36 flow cntl flags */ +#define F2200_SETAW (('e'<<8) | 105) /* Set 2x36 flow cntl flags */ #define F2200_MASK 0x03 /* 2200 flow cntl bit mask */ #define FCNTL_2200 0x01 /* 2x36 terminal flow cntl */ #define PCNTL_2200 0x02 /* 2x36 printer flow cntl */ @@ -241,7 +241,7 @@ struct digi_dinfo { char dinfo_version[16]; /* driver version */ }; -#define DIGI_GETDD ('d'<<8) | 248 /* get driver info */ +#define DIGI_GETDD (('d'<<8) | 248) /* get driver info */ /************************************************************************ * Structure used with ioctl commands for per-board information @@ -261,7 +261,7 @@ struct digi_info { char info_reserved[7]; /* for future expansion */ }; -#define DIGI_GETBD ('d'<<8) | 249 /* get board info */ +#define DIGI_GETBD (('d'<<8) | 249) /* get board info */ struct digi_stat { unsigned int info_chan; /* Channel number (0 based) */ @@ -276,7 +276,7 @@ struct digi_stat { unsigned int info_reserved[8]; /* for future expansion */ }; -#define DIGI_GETSTAT ('d'<<8) | 244 /* get board info */ +#define DIGI_GETSTAT (('d'<<8) | 244) /* get board info */ /************************************************************************ * * Structure used with ioctl commands for per-channel information @@ -339,7 +339,7 @@ struct digi_getcounter { #define INFO_CH_WLOW 0x0020 #define INFO_XXBUF_BUSY 0x0040 -#define DIGI_GETCH ('d'<<8) | 245 /* get board info */ +#define DIGI_GETCH (('d'<<8) | 245) /* get board info */ /* Board type definitions */ @@ -384,15 +384,15 @@ struct digi_getcounter { #define BD_TRIBOOT 0x8 #define BD_BADKME 0x80 -#define DIGI_SPOLL ('d'<<8) | 254 /* change poller rate */ +#define DIGI_SPOLL (('d'<<8) | 254) /* change poller rate */ #define DIGI_SETCUSTOMBAUD _IOW('e', 106, int) /* Set integer baud rate */ #define DIGI_GETCUSTOMBAUD _IOR('e', 107, int) /* Get integer baud rate */ -#define DIGI_REALPORT_GETBUFFERS ('e'<<8) | 108 -#define DIGI_REALPORT_SENDIMMEDIATE ('e'<<8) | 109 -#define DIGI_REALPORT_GETCOUNTERS ('e'<<8) | 110 -#define DIGI_REALPORT_GETEVENTS ('e'<<8) | 111 +#define DIGI_REALPORT_GETBUFFERS (('e'<<8) | 108) +#define DIGI_REALPORT_SENDIMMEDIATE (('e'<<8) | 109) +#define DIGI_REALPORT_GETCOUNTERS (('e'<<8) | 110) +#define DIGI_REALPORT_GETEVENTS (('e'<<8) | 111) #define EV_OPU 0x0001 /* ! Date: Thu, 22 Jan 2015 19:08:58 +0100 Subject: staging: fbtft: fbtft-core mark functions static This fixes sparse warnings like: warning: symbol XXX was not declared. Should it be static? by declaring all local functions static. Signed-off-by: Krzysztof Adamski Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index 873e2c7..37dcf7e 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -79,7 +79,7 @@ void fbtft_dbg_hex(const struct device *dev, int groupsize, } EXPORT_SYMBOL(fbtft_dbg_hex); -unsigned long fbtft_request_gpios_match(struct fbtft_par *par, +static unsigned long fbtft_request_gpios_match(struct fbtft_par *par, const struct fbtft_gpio *gpio) { int ret; @@ -123,7 +123,7 @@ unsigned long fbtft_request_gpios_match(struct fbtft_par *par, return FBTFT_GPIO_NO_MATCH; } -int fbtft_request_gpios(struct fbtft_par *par) +static int fbtft_request_gpios(struct fbtft_par *par) { struct fbtft_platform_data *pdata = par->pdata; const struct fbtft_gpio *gpio; @@ -249,7 +249,7 @@ static int fbtft_request_gpios_dt(struct fbtft_par *par) #endif #ifdef CONFIG_FB_BACKLIGHT -int fbtft_backlight_update_status(struct backlight_device *bd) +static int fbtft_backlight_update_status(struct backlight_device *bd) { struct fbtft_par *par = bl_get_data(bd); bool polarity = !!(bd->props.state & BL_CORE_DRIVER1); @@ -266,7 +266,7 @@ int fbtft_backlight_update_status(struct backlight_device *bd) return 0; } -int fbtft_backlight_get_brightness(struct backlight_device *bd) +static int fbtft_backlight_get_brightness(struct backlight_device *bd) { return bd->props.brightness; } @@ -337,7 +337,8 @@ void fbtft_unregister_backlight(struct fbtft_par *par) { }; EXPORT_SYMBOL(fbtft_register_backlight); EXPORT_SYMBOL(fbtft_unregister_backlight); -void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) +static void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, + int ye) { fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); @@ -355,7 +356,7 @@ void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) } -void fbtft_reset(struct fbtft_par *par) +static void fbtft_reset(struct fbtft_par *par) { if (par->gpio.reset == -1) return; @@ -367,7 +368,8 @@ void fbtft_reset(struct fbtft_par *par) } -void fbtft_update_display(struct fbtft_par *par, unsigned start_line, unsigned end_line) +static void fbtft_update_display(struct fbtft_par *par, unsigned start_line, + unsigned end_line) { size_t offset, len; struct timespec ts_start, ts_end, ts_fps, ts_duration; @@ -445,7 +447,7 @@ void fbtft_update_display(struct fbtft_par *par, unsigned start_line, unsigned e } -void fbtft_mkdirty(struct fb_info *info, int y, int height) +static void fbtft_mkdirty(struct fb_info *info, int y, int height) { struct fbtft_par *par = info->par; struct fb_deferred_io *fbdefio = info->fbdefio; @@ -468,7 +470,7 @@ void fbtft_mkdirty(struct fb_info *info, int y, int height) schedule_delayed_work(&info->deferred_work, fbdefio->delay); } -void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist) +static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist) { struct fbtft_par *par = info->par; unsigned dirty_lines_start, dirty_lines_end; @@ -507,7 +509,8 @@ void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist) } -void fbtft_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +static void fbtft_fb_fillrect(struct fb_info *info, + const struct fb_fillrect *rect) { struct fbtft_par *par = info->par; @@ -519,7 +522,8 @@ void fbtft_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) par->fbtftops.mkdirty(info, rect->dy, rect->height); } -void fbtft_fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) +static void fbtft_fb_copyarea(struct fb_info *info, + const struct fb_copyarea *area) { struct fbtft_par *par = info->par; @@ -531,7 +535,8 @@ void fbtft_fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) par->fbtftops.mkdirty(info, area->dy, area->height); } -void fbtft_fb_imageblit(struct fb_info *info, const struct fb_image *image) +static void fbtft_fb_imageblit(struct fb_info *info, + const struct fb_image *image) { struct fbtft_par *par = info->par; @@ -543,8 +548,8 @@ void fbtft_fb_imageblit(struct fb_info *info, const struct fb_image *image) par->fbtftops.mkdirty(info, image->dy, image->height); } -ssize_t fbtft_fb_write(struct fb_info *info, - const char __user *buf, size_t count, loff_t *ppos) +static ssize_t fbtft_fb_write(struct fb_info *info, const char __user *buf, + size_t count, loff_t *ppos) { struct fbtft_par *par = info->par; ssize_t res; @@ -561,16 +566,16 @@ ssize_t fbtft_fb_write(struct fb_info *info, } /* from pxafb.c */ -unsigned int chan_to_field(unsigned chan, struct fb_bitfield *bf) +static unsigned int chan_to_field(unsigned chan, struct fb_bitfield *bf) { chan &= 0xffff; chan >>= 16 - bf->length; return chan << bf->offset; } -int fbtft_fb_setcolreg(unsigned regno, - unsigned red, unsigned green, unsigned blue, - unsigned transp, struct fb_info *info) +static int fbtft_fb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) { struct fbtft_par *par = info->par; unsigned val; @@ -598,7 +603,7 @@ int fbtft_fb_setcolreg(unsigned regno, return ret; } -int fbtft_fb_blank(int blank, struct fb_info *info) +static int fbtft_fb_blank(int blank, struct fb_info *info) { struct fbtft_par *par = info->par; int ret = -EINVAL; @@ -623,7 +628,7 @@ int fbtft_fb_blank(int blank, struct fb_info *info) return ret; } -void fbtft_merge_fbtftops(struct fbtft_ops *dst, struct fbtft_ops *src) +static void fbtft_merge_fbtftops(struct fbtft_ops *dst, struct fbtft_ops *src) { if (src->write) dst->write = src->write; @@ -1265,7 +1270,7 @@ EXPORT_SYMBOL(fbtft_init_display); * * Return: 0 if successful, negative if error */ -int fbtft_verify_gpios(struct fbtft_par *par) +static int fbtft_verify_gpios(struct fbtft_par *par) { struct fbtft_platform_data *pdata; int i; -- cgit v0.10.2 From ce5b615bc29273de705188e8a827dd7663069602 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Fri, 23 Jan 2015 20:44:28 +0900 Subject: staging: dgap: fix "if" statement that always evaluates to true cppcheck warning: (warnning) Logical disjunction always evaluates to true Reported-by: David Binderman Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index 518ab56..7184747 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -978,8 +978,8 @@ static int dgap_parsefile(char **in) brd->u.board.conc1++; conc_type = dgap_gettok(in); - if (conc_type == 0 || conc_type != CX || - conc_type != EPC) { + if (conc_type == 0 || (conc_type != CX && + conc_type != EPC)) { pr_err("failed to set a type of concentratros"); return -1; } @@ -1019,8 +1019,8 @@ static int dgap_parsefile(char **in) brd->u.board.module1++; module_type = dgap_gettok(in); - if (module_type == 0 || module_type != PORTS || - module_type != MODEM) { + if (module_type == 0 || (module_type != PORTS && + module_type != MODEM)) { pr_err("failed to set a type of module"); return -1; } -- cgit v0.10.2 From 5da41e925656649fd970f0c205eee5fda887dc24 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 20 Jan 2015 13:42:34 -0800 Subject: staging: Remove the Android alarm-dev driver The functionality provided by the Android alarm-dev driver should now be present in the timerfd interface (thanks to Greg Hackmann and Todd Poynor). As of Lollipop, AOSP can make use of the timerfd if alarm-dev is not present (though a fixup for setting the rtc time if rtc0 isn't the backing for _ALARM clockids has been applied post-Lollipop). Thus, we should be able to remove alarm-dev from staging. Cc: Greg Hackmann Cc: Elliott Hughes Cc: Todd Poynor Cc: Android Kernel Team Signed-off-by: John Stultz Acked-by: Mark Salyzyn Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 7e012f3..2ac0b61 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -45,15 +45,6 @@ config ANDROID_LOW_MEMORY_KILLER ---help--- Registers processes to be killed when memory is low -config ANDROID_INTF_ALARM_DEV - tristate "Android alarm driver" - depends on RTC_CLASS - default n - ---help--- - Provides non-wakeup and rtc backed wakeup alarms based on rtc or - elapsed realtime, and a non-wakeup alarm on the monotonic clock. - Also exports the alarm interface to user-space. - config SYNC bool "Synchronization framework" default n diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c deleted file mode 100644 index ff4b3e8..0000000 --- a/drivers/staging/android/alarm-dev.c +++ /dev/null @@ -1,446 +0,0 @@ -/* drivers/rtc/alarm-dev.c - * - * Copyright (C) 2007-2009 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "android_alarm.h" - -#define ANDROID_ALARM_PRINT_INFO (1U << 0) -#define ANDROID_ALARM_PRINT_IO (1U << 1) -#define ANDROID_ALARM_PRINT_INT (1U << 2) - -static int debug_mask = ANDROID_ALARM_PRINT_INFO; -module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); - -#define alarm_dbg(debug_level_mask, fmt, ...) \ -do { \ - if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) \ - pr_info(fmt, ##__VA_ARGS__); \ -} while (0) - -#define ANDROID_ALARM_WAKEUP_MASK ( \ - ANDROID_ALARM_RTC_WAKEUP_MASK | \ - ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) - -static int alarm_opened; -static DEFINE_SPINLOCK(alarm_slock); -static struct wakeup_source alarm_wake_lock; -static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue); -static uint32_t alarm_pending; -static uint32_t alarm_enabled; -static uint32_t wait_pending; - -struct devalarm { - union { - struct hrtimer hrt; - struct alarm alrm; - } u; - enum android_alarm_type type; -}; - -static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT]; - -/** - * is_wakeup() - Checks to see if this alarm can wake the device - * @type: The type of alarm being checked - * - * Return: 1 if this is a wakeup alarm, otherwise 0 - */ -static int is_wakeup(enum android_alarm_type type) -{ - return type == ANDROID_ALARM_RTC_WAKEUP || - type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP; -} - -static void devalarm_start(struct devalarm *alrm, ktime_t exp) -{ - if (is_wakeup(alrm->type)) - alarm_start(&alrm->u.alrm, exp); - else - hrtimer_start(&alrm->u.hrt, exp, HRTIMER_MODE_ABS); -} - -static int devalarm_try_to_cancel(struct devalarm *alrm) -{ - if (is_wakeup(alrm->type)) - return alarm_try_to_cancel(&alrm->u.alrm); - return hrtimer_try_to_cancel(&alrm->u.hrt); -} - -static void devalarm_cancel(struct devalarm *alrm) -{ - if (is_wakeup(alrm->type)) - alarm_cancel(&alrm->u.alrm); - else - hrtimer_cancel(&alrm->u.hrt); -} - -static void alarm_clear(enum android_alarm_type alarm_type) -{ - uint32_t alarm_type_mask = 1U << alarm_type; - unsigned long flags; - - spin_lock_irqsave(&alarm_slock, flags); - alarm_dbg(IO, "alarm %d clear\n", alarm_type); - devalarm_try_to_cancel(&alarms[alarm_type]); - if (alarm_pending) { - alarm_pending &= ~alarm_type_mask; - if (!alarm_pending && !wait_pending) - __pm_relax(&alarm_wake_lock); - } - alarm_enabled &= ~alarm_type_mask; - spin_unlock_irqrestore(&alarm_slock, flags); -} - -static void alarm_set(enum android_alarm_type alarm_type, - struct timespec *ts) -{ - uint32_t alarm_type_mask = 1U << alarm_type; - unsigned long flags; - - spin_lock_irqsave(&alarm_slock, flags); - alarm_dbg(IO, "alarm %d set %ld.%09ld\n", - alarm_type, ts->tv_sec, ts->tv_nsec); - alarm_enabled |= alarm_type_mask; - devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts)); - spin_unlock_irqrestore(&alarm_slock, flags); -} - -static int alarm_wait(void) -{ - unsigned long flags; - int rv = 0; - - spin_lock_irqsave(&alarm_slock, flags); - alarm_dbg(IO, "alarm wait\n"); - if (!alarm_pending && wait_pending) { - __pm_relax(&alarm_wake_lock); - wait_pending = 0; - } - spin_unlock_irqrestore(&alarm_slock, flags); - - rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); - if (rv) - return rv; - - spin_lock_irqsave(&alarm_slock, flags); - rv = alarm_pending; - wait_pending = 1; - alarm_pending = 0; - spin_unlock_irqrestore(&alarm_slock, flags); - - return rv; -} - -static int alarm_set_rtc(struct timespec *ts) -{ - struct rtc_time new_rtc_tm; - struct rtc_device *rtc_dev; - unsigned long flags; - int rv = 0; - - rtc_time_to_tm(ts->tv_sec, &new_rtc_tm); - rtc_dev = alarmtimer_get_rtcdev(); - rv = do_settimeofday(ts); - if (rv < 0) - return rv; - if (rtc_dev) - rv = rtc_set_time(rtc_dev, &new_rtc_tm); - - spin_lock_irqsave(&alarm_slock, flags); - alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; - wake_up(&alarm_wait_queue); - spin_unlock_irqrestore(&alarm_slock, flags); - - return rv; -} - -static int alarm_get_time(enum android_alarm_type alarm_type, - struct timespec *ts) -{ - int rv = 0; - - switch (alarm_type) { - case ANDROID_ALARM_RTC_WAKEUP: - case ANDROID_ALARM_RTC: - getnstimeofday(ts); - break; - case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP: - case ANDROID_ALARM_ELAPSED_REALTIME: - get_monotonic_boottime(ts); - break; - case ANDROID_ALARM_SYSTEMTIME: - ktime_get_ts(ts); - break; - default: - rv = -EINVAL; - } - return rv; -} - -static long alarm_do_ioctl(struct file *file, unsigned int cmd, - struct timespec *ts) -{ - int rv = 0; - unsigned long flags; - enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); - - if (alarm_type >= ANDROID_ALARM_TYPE_COUNT) - return -EINVAL; - - if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) { - if ((file->f_flags & O_ACCMODE) == O_RDONLY) - return -EPERM; - if (file->private_data == NULL && - cmd != ANDROID_ALARM_SET_RTC) { - spin_lock_irqsave(&alarm_slock, flags); - if (alarm_opened) { - spin_unlock_irqrestore(&alarm_slock, flags); - return -EBUSY; - } - alarm_opened = 1; - file->private_data = (void *)1; - spin_unlock_irqrestore(&alarm_slock, flags); - } - } - - switch (ANDROID_ALARM_BASE_CMD(cmd)) { - case ANDROID_ALARM_CLEAR(0): - alarm_clear(alarm_type); - break; - case ANDROID_ALARM_SET(0): - alarm_set(alarm_type, ts); - break; - case ANDROID_ALARM_SET_AND_WAIT(0): - alarm_set(alarm_type, ts); - /* fall though */ - case ANDROID_ALARM_WAIT: - rv = alarm_wait(); - break; - case ANDROID_ALARM_SET_RTC: - rv = alarm_set_rtc(ts); - break; - case ANDROID_ALARM_GET_TIME(0): - rv = alarm_get_time(alarm_type, ts); - break; - - default: - rv = -EINVAL; - } - return rv; -} - -static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - - struct timespec ts; - int rv; - - switch (ANDROID_ALARM_BASE_CMD(cmd)) { - case ANDROID_ALARM_SET_AND_WAIT(0): - case ANDROID_ALARM_SET(0): - case ANDROID_ALARM_SET_RTC: - if (copy_from_user(&ts, (void __user *)arg, sizeof(ts))) - return -EFAULT; - break; - } - - rv = alarm_do_ioctl(file, cmd, &ts); - if (rv) - return rv; - - switch (ANDROID_ALARM_BASE_CMD(cmd)) { - case ANDROID_ALARM_GET_TIME(0): - if (copy_to_user((void __user *)arg, &ts, sizeof(ts))) - return -EFAULT; - break; - } - - return 0; -} - -#ifdef CONFIG_COMPAT -static long alarm_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - - struct timespec ts; - int rv; - - switch (ANDROID_ALARM_BASE_CMD(cmd)) { - case ANDROID_ALARM_SET_AND_WAIT_COMPAT(0): - case ANDROID_ALARM_SET_COMPAT(0): - case ANDROID_ALARM_SET_RTC_COMPAT: - if (compat_get_timespec(&ts, (void __user *)arg)) - return -EFAULT; - /* fall through */ - case ANDROID_ALARM_GET_TIME_COMPAT(0): - cmd = ANDROID_ALARM_COMPAT_TO_NORM(cmd); - break; - } - - rv = alarm_do_ioctl(file, cmd, &ts); - if (rv) - return rv; - - switch (ANDROID_ALARM_BASE_CMD(cmd)) { - case ANDROID_ALARM_GET_TIME(0): /* NOTE: we modified cmd above */ - if (compat_put_timespec(&ts, (void __user *)arg)) - return -EFAULT; - break; - } - - return 0; -} -#endif - -static int alarm_open(struct inode *inode, struct file *file) -{ - file->private_data = NULL; - return 0; -} - -static int alarm_release(struct inode *inode, struct file *file) -{ - int i; - unsigned long flags; - - spin_lock_irqsave(&alarm_slock, flags); - if (file->private_data) { - for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { - uint32_t alarm_type_mask = 1U << i; - - if (alarm_enabled & alarm_type_mask) { - alarm_dbg(INFO, - "%s: clear alarm, pending %d\n", - __func__, - !!(alarm_pending & alarm_type_mask)); - alarm_enabled &= ~alarm_type_mask; - } - spin_unlock_irqrestore(&alarm_slock, flags); - devalarm_cancel(&alarms[i]); - spin_lock_irqsave(&alarm_slock, flags); - } - if (alarm_pending | wait_pending) { - if (alarm_pending) - alarm_dbg(INFO, "%s: clear pending alarms %x\n", - __func__, alarm_pending); - __pm_relax(&alarm_wake_lock); - wait_pending = 0; - alarm_pending = 0; - } - alarm_opened = 0; - } - spin_unlock_irqrestore(&alarm_slock, flags); - return 0; -} - -static void devalarm_triggered(struct devalarm *alarm) -{ - unsigned long flags; - uint32_t alarm_type_mask = 1U << alarm->type; - - alarm_dbg(INT, "%s: type %d\n", __func__, alarm->type); - spin_lock_irqsave(&alarm_slock, flags); - if (alarm_enabled & alarm_type_mask) { - __pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */ - alarm_enabled &= ~alarm_type_mask; - alarm_pending |= alarm_type_mask; - wake_up(&alarm_wait_queue); - } - spin_unlock_irqrestore(&alarm_slock, flags); -} - -static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt) -{ - struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt); - - devalarm_triggered(devalrm); - return HRTIMER_NORESTART; -} - -static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm, - ktime_t now) -{ - struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm); - - devalarm_triggered(devalrm); - return ALARMTIMER_NORESTART; -} - - -static const struct file_operations alarm_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = alarm_ioctl, - .open = alarm_open, - .release = alarm_release, -#ifdef CONFIG_COMPAT - .compat_ioctl = alarm_compat_ioctl, -#endif -}; - -static struct miscdevice alarm_device = { - .minor = MISC_DYNAMIC_MINOR, - .name = "alarm", - .fops = &alarm_fops, -}; - -static int __init alarm_dev_init(void) -{ - int err; - int i; - - err = misc_register(&alarm_device); - if (err) - return err; - - alarm_init(&alarms[ANDROID_ALARM_RTC_WAKEUP].u.alrm, - ALARM_REALTIME, devalarm_alarmhandler); - hrtimer_init(&alarms[ANDROID_ALARM_RTC].u.hrt, - CLOCK_REALTIME, HRTIMER_MODE_ABS); - alarm_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].u.alrm, - ALARM_BOOTTIME, devalarm_alarmhandler); - hrtimer_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME].u.hrt, - CLOCK_BOOTTIME, HRTIMER_MODE_ABS); - hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt, - CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - - for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { - alarms[i].type = i; - if (!is_wakeup(i)) - alarms[i].u.hrt.function = devalarm_hrthandler; - } - - wakeup_source_init(&alarm_wake_lock, "alarm"); - return 0; -} - -static void __exit alarm_dev_exit(void) -{ - misc_deregister(&alarm_device); - wakeup_source_trash(&alarm_wake_lock); -} - -module_init(alarm_dev_init); -module_exit(alarm_dev_exit); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h deleted file mode 100644 index 495b20c..0000000 --- a/drivers/staging/android/android_alarm.h +++ /dev/null @@ -1,41 +0,0 @@ -/* include/linux/android_alarm.h - * - * Copyright (C) 2006-2007 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _LINUX_ANDROID_ALARM_H -#define _LINUX_ANDROID_ALARM_H - -#include -#include - -#include "uapi/android_alarm.h" - -#ifdef CONFIG_COMPAT -#define ANDROID_ALARM_SET_COMPAT(type) ALARM_IOW(2, type, \ - struct compat_timespec) -#define ANDROID_ALARM_SET_AND_WAIT_COMPAT(type) ALARM_IOW(3, type, \ - struct compat_timespec) -#define ANDROID_ALARM_GET_TIME_COMPAT(type) ALARM_IOW(4, type, \ - struct compat_timespec) -#define ANDROID_ALARM_SET_RTC_COMPAT _IOW('a', 5, \ - struct compat_timespec) -#define ANDROID_ALARM_IOCTL_NR(cmd) (_IOC_NR(cmd) & ((1<<4)-1)) -#define ANDROID_ALARM_COMPAT_TO_NORM(cmd) \ - ALARM_IOW(ANDROID_ALARM_IOCTL_NR(cmd), \ - ANDROID_ALARM_IOCTL_TO_TYPE(cmd), \ - struct timespec) - -#endif - -#endif diff --git a/drivers/staging/android/uapi/android_alarm.h b/drivers/staging/android/uapi/android_alarm.h deleted file mode 100644 index aa013f6..0000000 --- a/drivers/staging/android/uapi/android_alarm.h +++ /dev/null @@ -1,62 +0,0 @@ -/* drivers/staging/android/uapi/android_alarm.h - * - * Copyright (C) 2006-2007 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _UAPI_LINUX_ANDROID_ALARM_H -#define _UAPI_LINUX_ANDROID_ALARM_H - -#include -#include - -enum android_alarm_type { - /* return code bit numbers or set alarm arg */ - ANDROID_ALARM_RTC_WAKEUP, - ANDROID_ALARM_RTC, - ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, - ANDROID_ALARM_ELAPSED_REALTIME, - ANDROID_ALARM_SYSTEMTIME, - - ANDROID_ALARM_TYPE_COUNT, - - /* return code bit numbers */ - /* ANDROID_ALARM_TIME_CHANGE = 16 */ -}; - -enum android_alarm_return_flags { - ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP, - ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC, - ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK = - 1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, - ANDROID_ALARM_ELAPSED_REALTIME_MASK = - 1U << ANDROID_ALARM_ELAPSED_REALTIME, - ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME, - ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16 -}; - -/* Disable alarm */ -#define ANDROID_ALARM_CLEAR(type) _IO('a', 0 | ((type) << 4)) - -/* Ack last alarm and wait for next */ -#define ANDROID_ALARM_WAIT _IO('a', 1) - -#define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) -/* Set alarm */ -#define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) -#define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) -#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) -#define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) -#define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) -#define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) - -#endif -- cgit v0.10.2 From a8e8f89dadee04f6f5d1a681b14d046e9f921400 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 19 Jan 2015 13:41:00 +0530 Subject: Revert "staging: sm7xxfb: remove driver" This reverts commit "dc93c85235efa5201e9a3c116bc3fbd1afc1a182" Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index ce8f420..071ac11 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -58,6 +58,8 @@ source "drivers/staging/vt6656/Kconfig" source "drivers/staging/iio/Kconfig" +source "drivers/staging/sm7xxfb/Kconfig" + source "drivers/staging/xgifb/Kconfig" source "drivers/staging/emxx_udc/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index c242787..b65ca37 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_VT6655) += vt6655/ obj-$(CONFIG_VT6656) += vt6656/ obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_IIO) += iio/ +obj-$(CONFIG_FB_SM7XX) += sm7xxfb/ obj-$(CONFIG_FB_XGI) += xgifb/ obj-$(CONFIG_USB_EMXX) += emxx_udc/ obj-$(CONFIG_FT1000) += ft1000/ diff --git a/drivers/staging/sm7xxfb/Kconfig b/drivers/staging/sm7xxfb/Kconfig new file mode 100644 index 0000000..e2922ae --- /dev/null +++ b/drivers/staging/sm7xxfb/Kconfig @@ -0,0 +1,13 @@ +config FB_SM7XX + tristate "Silicon Motion SM7XX framebuffer support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Frame buffer driver for the Silicon Motion SM710, SM712, SM721 + and SM722 chips. + + This driver is also available as a module. The module will be + called sm7xxfb. If you want to compile it as a module, say M + here and read . diff --git a/drivers/staging/sm7xxfb/Makefile b/drivers/staging/sm7xxfb/Makefile new file mode 100644 index 0000000..48f471c --- /dev/null +++ b/drivers/staging/sm7xxfb/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FB_SM7XX) += sm7xxfb.o diff --git a/drivers/staging/sm7xxfb/TODO b/drivers/staging/sm7xxfb/TODO new file mode 100644 index 0000000..1fcead5 --- /dev/null +++ b/drivers/staging/sm7xxfb/TODO @@ -0,0 +1,9 @@ +TODO: +- Dual head support +- 2D acceleration support +- use kernel coding style +- refine the code and remove unused code +- move it to drivers/video/sm7xxfb.c + +Please send any patches to Greg Kroah-Hartman and +Teddy Wang . diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/staging/sm7xxfb/sm7xx.h new file mode 100644 index 0000000..8599861 --- /dev/null +++ b/drivers/staging/sm7xxfb/sm7xx.h @@ -0,0 +1,779 @@ +/* + * Silicon Motion SM712 frame buffer device + * + * Copyright (C) 2006 Silicon Motion Technology Corp. + * Authors: Ge Wang, gewang@siliconmotion.com + * Boyod boyod.yang@siliconmotion.com.cn + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzhangjin@gmail.com + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#define NR_PALETTE 256 + +#define FB_ACCEL_SMI_LYNX 88 + +#define SCREEN_X_RES 1024 +#define SCREEN_Y_RES 600 +#define SCREEN_BPP 16 + +/*Assume SM712 graphics chip has 4MB VRAM */ +#define SM712_VIDEOMEMORYSIZE 0x00400000 +/*Assume SM722 graphics chip has 8MB VRAM */ +#define SM722_VIDEOMEMORYSIZE 0x00800000 + +#define dac_reg (0x3c8) +#define dac_val (0x3c9) + +extern void __iomem *smtc_RegBaseAddress; +#define smtc_mmiowb(dat, reg) writeb(dat, smtc_RegBaseAddress + reg) +#define smtc_mmioww(dat, reg) writew(dat, smtc_RegBaseAddress + reg) +#define smtc_mmiowl(dat, reg) writel(dat, smtc_RegBaseAddress + reg) + +#define smtc_mmiorb(reg) readb(smtc_RegBaseAddress + reg) +#define smtc_mmiorw(reg) readw(smtc_RegBaseAddress + reg) +#define smtc_mmiorl(reg) readl(smtc_RegBaseAddress + reg) + +#define SIZE_SR00_SR04 (0x04 - 0x00 + 1) +#define SIZE_SR10_SR24 (0x24 - 0x10 + 1) +#define SIZE_SR30_SR75 (0x75 - 0x30 + 1) +#define SIZE_SR80_SR93 (0x93 - 0x80 + 1) +#define SIZE_SRA0_SRAF (0xAF - 0xA0 + 1) +#define SIZE_GR00_GR08 (0x08 - 0x00 + 1) +#define SIZE_AR00_AR14 (0x14 - 0x00 + 1) +#define SIZE_CR00_CR18 (0x18 - 0x00 + 1) +#define SIZE_CR30_CR4D (0x4D - 0x30 + 1) +#define SIZE_CR90_CRA7 (0xA7 - 0x90 + 1) +#define SIZE_VPR (0x6C + 1) +#define SIZE_DPR (0x44 + 1) + +static inline void smtc_crtcw(int reg, int val) +{ + smtc_mmiowb(reg, 0x3d4); + smtc_mmiowb(val, 0x3d5); +} + +static inline unsigned int smtc_crtcr(int reg) +{ + smtc_mmiowb(reg, 0x3d4); + return smtc_mmiorb(0x3d5); +} + +static inline void smtc_grphw(int reg, int val) +{ + smtc_mmiowb(reg, 0x3ce); + smtc_mmiowb(val, 0x3cf); +} + +static inline unsigned int smtc_grphr(int reg) +{ + smtc_mmiowb(reg, 0x3ce); + return smtc_mmiorb(0x3cf); +} + +static inline void smtc_attrw(int reg, int val) +{ + smtc_mmiorb(0x3da); + smtc_mmiowb(reg, 0x3c0); + smtc_mmiorb(0x3c1); + smtc_mmiowb(val, 0x3c0); +} + +static inline void smtc_seqw(int reg, int val) +{ + smtc_mmiowb(reg, 0x3c4); + smtc_mmiowb(val, 0x3c5); +} + +static inline unsigned int smtc_seqr(int reg) +{ + smtc_mmiowb(reg, 0x3c4); + return smtc_mmiorb(0x3c5); +} + +/* The next structure holds all information relevant for a specific video mode. + */ + +struct ModeInit { + int mmSizeX; + int mmSizeY; + int bpp; + int hz; + unsigned char Init_MISC; + unsigned char Init_SR00_SR04[SIZE_SR00_SR04]; + unsigned char Init_SR10_SR24[SIZE_SR10_SR24]; + unsigned char Init_SR30_SR75[SIZE_SR30_SR75]; + unsigned char Init_SR80_SR93[SIZE_SR80_SR93]; + unsigned char Init_SRA0_SRAF[SIZE_SRA0_SRAF]; + unsigned char Init_GR00_GR08[SIZE_GR00_GR08]; + unsigned char Init_AR00_AR14[SIZE_AR00_AR14]; + unsigned char Init_CR00_CR18[SIZE_CR00_CR18]; + unsigned char Init_CR30_CR4D[SIZE_CR30_CR4D]; + unsigned char Init_CR90_CRA7[SIZE_CR90_CRA7]; +}; + +/********************************************************************** + SM712 Mode table. + **********************************************************************/ +struct ModeInit VGAMode[] = { + { + /* mode#0: 640 x 480 16Bpp 60Hz */ + 640, 480, 16, 60, + /* Init_MISC */ + 0xE3, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, + }, + }, + { + /* mode#1: 640 x 480 24Bpp 60Hz */ + 640, 480, 24, 60, + /* Init_MISC */ + 0xE3, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, + }, + }, + { + /* mode#0: 640 x 480 32Bpp 60Hz */ + 640, 480, 32, 60, + /* Init_MISC */ + 0xE3, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, + }, + }, + + { /* mode#2: 800 x 600 16Bpp 60Hz */ + 800, 600, 16, 60, + /* Init_MISC */ + 0x2B, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24, + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, + 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24, + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, + 0x02, 0x45, 0x30, 0x35, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, + }, + }, + { /* mode#3: 800 x 600 24Bpp 60Hz */ + 800, 600, 24, 60, + 0x2B, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36, + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, + 0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, + 0x02, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, + }, + }, + { /* mode#7: 800 x 600 32Bpp 60Hz */ + 800, 600, 32, 60, + /* Init_MISC */ + 0x2B, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24, + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, + 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24, + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, + 0x02, 0x45, 0x30, 0x35, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, + }, + }, + /* We use 1024x768 table to light 1024x600 panel for lemote */ + { /* mode#4: 1024 x 600 16Bpp 60Hz */ + 1024, 600, 16, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20, + 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x00, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22, + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02, + 0x04, 0x45, 0x3F, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00, + 0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + { /* mode#5: 1024 x 768 24Bpp 60Hz */ + 1024, 768, 24, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00, + 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + { /* mode#4: 1024 x 768 32Bpp 60Hz */ + 1024, 768, 32, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x32, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00, + 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + { /* mode#6: 320 x 240 16Bpp 60Hz */ + 320, 240, 16, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x32, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00, + 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + + { /* mode#8: 320 x 240 32Bpp 60Hz */ + 320, 240, 32, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x32, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00, + 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, +}; + +#define numVGAModes ARRAY_SIZE(VGAMode) diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c new file mode 100644 index 0000000..c550b71 --- /dev/null +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -0,0 +1,1026 @@ +/* + * Silicon Motion SM7XX frame buffer device + * + * Copyright (C) 2006 Silicon Motion Technology Corp. + * Authors: Ge Wang, gewang@siliconmotion.com + * Boyod boyod.yang@siliconmotion.com.cn + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzhangjin@gmail.com + * + * Copyright (C) 2011 Igalia, S.L. + * Author: Javier M. Mellid + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PM +#include +#endif + +#include "sm7xx.h" + +/* +* Private structure +*/ +struct smtcfb_info { + struct pci_dev *pdev; + struct fb_info fb; + u16 chip_id; + u8 chip_rev_id; + + void __iomem *lfb; /* linear frame buffer */ + void __iomem *dp_regs; /* drawing processor control regs */ + void __iomem *vp_regs; /* video processor control regs */ + void __iomem *cp_regs; /* capture processor control regs */ + void __iomem *mmio; /* memory map IO port */ + + u_int width; + u_int height; + u_int hz; + + u32 colreg[17]; +}; + +void __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */ + +static struct fb_var_screeninfo smtcfb_var = { + .xres = 1024, + .yres = 600, + .xres_virtual = 1024, + .yres_virtual = 600, + .bits_per_pixel = 16, + .red = {16, 8, 0}, + .green = {8, 8, 0}, + .blue = {0, 8, 0}, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .vmode = FB_VMODE_NONINTERLACED, + .nonstd = 0, + .accel_flags = FB_ACCELF_TEXT, +}; + +static struct fb_fix_screeninfo smtcfb_fix = { + .id = "smXXXfb", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .line_length = 800 * 3, + .accel = FB_ACCEL_SMI_LYNX, + .type_aux = 0, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, +}; + +struct vesa_mode { + char index[6]; + u16 lfb_width; + u16 lfb_height; + u16 lfb_depth; +}; + +static struct vesa_mode vesa_mode_table[] = { + {"0x301", 640, 480, 8}, + {"0x303", 800, 600, 8}, + {"0x305", 1024, 768, 8}, + {"0x307", 1280, 1024, 8}, + + {"0x311", 640, 480, 16}, + {"0x314", 800, 600, 16}, + {"0x317", 1024, 768, 16}, + {"0x31A", 1280, 1024, 16}, + + {"0x312", 640, 480, 24}, + {"0x315", 800, 600, 24}, + {"0x318", 1024, 768, 24}, + {"0x31B", 1280, 1024, 24}, +}; + +struct screen_info smtc_scr_info; + +/* process command line options, get vga parameter */ +static int __init sm7xx_vga_setup(char *options) +{ + int i; + + if (!options || !*options) + return -EINVAL; + + smtc_scr_info.lfb_width = 0; + smtc_scr_info.lfb_height = 0; + smtc_scr_info.lfb_depth = 0; + + pr_debug("sm7xx_vga_setup = %s\n", options); + + for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) { + if (strstr(options, vesa_mode_table[i].index)) { + smtc_scr_info.lfb_width = vesa_mode_table[i].lfb_width; + smtc_scr_info.lfb_height = + vesa_mode_table[i].lfb_height; + smtc_scr_info.lfb_depth = vesa_mode_table[i].lfb_depth; + return 0; + } + } + + return -1; +} +__setup("vga=", sm7xx_vga_setup); + +static void sm712_setpalette(int regno, unsigned red, unsigned green, + unsigned blue, struct fb_info *info) +{ + /* set bit 5:4 = 01 (write LCD RAM only) */ + smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10); + + smtc_mmiowb(regno, dac_reg); + smtc_mmiowb(red >> 10, dac_val); + smtc_mmiowb(green >> 10, dac_val); + smtc_mmiowb(blue >> 10, dac_val); +} + +/* chan_to_field + * + * convert a colour value into a field position + * + * from pxafb.c + */ + +static inline unsigned int chan_to_field(unsigned int chan, + struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int smtc_blank(int blank_mode, struct fb_info *info) +{ + /* clear DPMS setting */ + switch (blank_mode) { + case FB_BLANK_UNBLANK: + /* Screen On: HSync: On, VSync : On */ + smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20))); + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77)); + smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30))); + smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0))); + smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01)); + smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03)); + break; + case FB_BLANK_NORMAL: + /* Screen Off: HSync: On, VSync : On Soft blank */ + smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20))); + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30))); + smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0))); + smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01)); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + break; + case FB_BLANK_VSYNC_SUSPEND: + /* Screen On: HSync: On, VSync : Off */ + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); + smtc_seqw(0x6a, 0x0c); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20)); + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20)); + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); + break; + case FB_BLANK_HSYNC_SUSPEND: + /* Screen On: HSync: Off, VSync : On */ + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); + smtc_seqw(0x6a, 0x0c); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10)); + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8)); + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); + break; + case FB_BLANK_POWERDOWN: + /* Screen On: HSync: Off, VSync : Off */ + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); + smtc_seqw(0x6a, 0x0c); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30)); + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8)); + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned trans, struct fb_info *info) +{ + struct smtcfb_info *sfb; + u32 val; + + sfb = info->par; + + if (regno > 255) + return 1; + + switch (sfb->fb.fix.visual) { + case FB_VISUAL_DIRECTCOLOR: + case FB_VISUAL_TRUECOLOR: + /* + * 16/32 bit true-colour, use pseudo-palette for 16 base color + */ + if (regno < 16) { + if (sfb->fb.var.bits_per_pixel == 16) { + u32 *pal = sfb->fb.pseudo_palette; + val = chan_to_field(red, &sfb->fb.var.red); + val |= chan_to_field(green, &sfb->fb.var.green); + val |= chan_to_field(blue, &sfb->fb.var.blue); +#ifdef __BIG_ENDIAN + pal[regno] = + ((red & 0xf800) >> 8) | + ((green & 0xe000) >> 13) | + ((green & 0x1c00) << 3) | + ((blue & 0xf800) >> 3); +#else + pal[regno] = val; +#endif + } else { + u32 *pal = sfb->fb.pseudo_palette; + val = chan_to_field(red, &sfb->fb.var.red); + val |= chan_to_field(green, &sfb->fb.var.green); + val |= chan_to_field(blue, &sfb->fb.var.blue); +#ifdef __BIG_ENDIAN + val = + (val & 0xff00ff00 >> 8) | + (val & 0x00ff00ff << 8); +#endif + pal[regno] = val; + } + } + break; + + case FB_VISUAL_PSEUDOCOLOR: + /* color depth 8 bit */ + sm712_setpalette(regno, red, green, blue, info); + break; + + default: + return 1; /* unknown type */ + } + + return 0; + +} + +#ifdef __BIG_ENDIAN +static ssize_t smtcfb_read(struct fb_info *info, char __user *buf, size_t + count, loff_t *ppos) +{ + unsigned long p = *ppos; + + u32 *buffer, *dst; + u32 __iomem *src; + int c, i, cnt = 0, err = 0; + unsigned long total_size; + + if (!info || !info->screen_base) + return -ENODEV; + + if (info->state != FBINFO_STATE_RUNNING) + return -EPERM; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p >= total_size) + return 0; + + if (count >= total_size) + count = total_size; + + if (count + p > total_size) + count = total_size - p; + + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + src = (u32 __iomem *) (info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + while (count) { + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; + dst = buffer; + for (i = c >> 2; i--;) { + *dst = fb_readl(src++); + *dst = + (*dst & 0xff00ff00 >> 8) | + (*dst & 0x00ff00ff << 8); + dst++; + } + if (c & 3) { + u8 *dst8 = (u8 *) dst; + u8 __iomem *src8 = (u8 __iomem *) src; + + for (i = c & 3; i--;) { + if (i & 1) { + *dst8++ = fb_readb(++src8); + } else { + *dst8++ = fb_readb(--src8); + src8 += 2; + } + } + src = (u32 __iomem *) src8; + } + + if (copy_to_user(buf, buffer, c)) { + err = -EFAULT; + break; + } + *ppos += c; + buf += c; + cnt += c; + count -= c; + } + + kfree(buffer); + + return (err) ? err : cnt; +} + +static ssize_t +smtcfb_write(struct fb_info *info, const char __user *buf, size_t count, + loff_t *ppos) +{ + unsigned long p = *ppos; + + u32 *buffer, *src; + u32 __iomem *dst; + int c, i, cnt = 0, err = 0; + unsigned long total_size; + + if (!info || !info->screen_base) + return -ENODEV; + + if (info->state != FBINFO_STATE_RUNNING) + return -EPERM; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p > total_size) + return -EFBIG; + + if (count > total_size) { + err = -EFBIG; + count = total_size; + } + + if (count + p > total_size) { + if (!err) + err = -ENOSPC; + + count = total_size - p; + } + + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + dst = (u32 __iomem *) (info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + while (count) { + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; + src = buffer; + + if (copy_from_user(src, buf, c)) { + err = -EFAULT; + break; + } + + for (i = c >> 2; i--;) { + fb_writel((*src & 0xff00ff00 >> 8) | + (*src & 0x00ff00ff << 8), dst++); + src++; + } + if (c & 3) { + u8 *src8 = (u8 *) src; + u8 __iomem *dst8 = (u8 __iomem *) dst; + + for (i = c & 3; i--;) { + if (i & 1) { + fb_writeb(*src8++, ++dst8); + } else { + fb_writeb(*src8++, --dst8); + dst8 += 2; + } + } + dst = (u32 __iomem *) dst8; + } + + *ppos += c; + buf += c; + cnt += c; + count -= c; + } + + kfree(buffer); + + return (cnt) ? cnt : err; +} +#endif /* ! __BIG_ENDIAN */ + +static void sm7xx_set_timing(struct smtcfb_info *sfb) +{ + int i = 0, j = 0; + u32 m_nScreenStride; + + dev_dbg(&sfb->pdev->dev, + "sfb->width=%d sfb->height=%d sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n", + sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz); + + for (j = 0; j < numVGAModes; j++) { + if (VGAMode[j].mmSizeX == sfb->width && + VGAMode[j].mmSizeY == sfb->height && + VGAMode[j].bpp == sfb->fb.var.bits_per_pixel && + VGAMode[j].hz == sfb->hz) { + + dev_dbg(&sfb->pdev->dev, + "VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d VGAMode[j].bpp=%d VGAMode[j].hz=%d\n", + VGAMode[j].mmSizeX, VGAMode[j].mmSizeY, + VGAMode[j].bpp, VGAMode[j].hz); + + dev_dbg(&sfb->pdev->dev, "VGAMode index=%d\n", j); + + smtc_mmiowb(0x0, 0x3c6); + + smtc_seqw(0, 0x1); + + smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2); + + /* init SEQ register SR00 - SR04 */ + for (i = 0; i < SIZE_SR00_SR04; i++) + smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]); + + /* init SEQ register SR10 - SR24 */ + for (i = 0; i < SIZE_SR10_SR24; i++) + smtc_seqw(i + 0x10, + VGAMode[j].Init_SR10_SR24[i]); + + /* init SEQ register SR30 - SR75 */ + for (i = 0; i < SIZE_SR30_SR75; i++) + if ((i + 0x30) != 0x62 && + (i + 0x30) != 0x6a && + (i + 0x30) != 0x6b) + smtc_seqw(i + 0x30, + VGAMode[j].Init_SR30_SR75[i]); + + /* init SEQ register SR80 - SR93 */ + for (i = 0; i < SIZE_SR80_SR93; i++) + smtc_seqw(i + 0x80, + VGAMode[j].Init_SR80_SR93[i]); + + /* init SEQ register SRA0 - SRAF */ + for (i = 0; i < SIZE_SRA0_SRAF; i++) + smtc_seqw(i + 0xa0, + VGAMode[j].Init_SRA0_SRAF[i]); + + /* init Graphic register GR00 - GR08 */ + for (i = 0; i < SIZE_GR00_GR08; i++) + smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]); + + /* init Attribute register AR00 - AR14 */ + for (i = 0; i < SIZE_AR00_AR14; i++) + smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]); + + /* init CRTC register CR00 - CR18 */ + for (i = 0; i < SIZE_CR00_CR18; i++) + smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]); + + /* init CRTC register CR30 - CR4D */ + for (i = 0; i < SIZE_CR30_CR4D; i++) + smtc_crtcw(i + 0x30, + VGAMode[j].Init_CR30_CR4D[i]); + + /* init CRTC register CR90 - CRA7 */ + for (i = 0; i < SIZE_CR90_CRA7; i++) + smtc_crtcw(i + 0x90, + VGAMode[j].Init_CR90_CRA7[i]); + } + } + smtc_mmiowb(0x67, 0x3c2); + + /* set VPR registers */ + writel(0x0, sfb->vp_regs + 0x0C); + writel(0x0, sfb->vp_regs + 0x40); + + /* set data width */ + m_nScreenStride = + (sfb->width * sfb->fb.var.bits_per_pixel) / 64; + switch (sfb->fb.var.bits_per_pixel) { + case 8: + writel(0x0, sfb->vp_regs + 0x0); + break; + case 16: + writel(0x00020000, sfb->vp_regs + 0x0); + break; + case 24: + writel(0x00040000, sfb->vp_regs + 0x0); + break; + case 32: + writel(0x00030000, sfb->vp_regs + 0x0); + break; + } + writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride), + sfb->vp_regs + 0x10); + +} + +static void smtc_set_timing(struct smtcfb_info *sfb) +{ + switch (sfb->chip_id) { + case 0x710: + case 0x712: + case 0x720: + sm7xx_set_timing(sfb); + break; + } +} + +static void smtcfb_setmode(struct smtcfb_info *sfb) +{ + switch (sfb->fb.var.bits_per_pixel) { + case 32: + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres * 4; + sfb->fb.var.red.length = 8; + sfb->fb.var.green.length = 8; + sfb->fb.var.blue.length = 8; + sfb->fb.var.red.offset = 16; + sfb->fb.var.green.offset = 8; + sfb->fb.var.blue.offset = 0; + break; + case 24: + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres * 3; + sfb->fb.var.red.length = 8; + sfb->fb.var.green.length = 8; + sfb->fb.var.blue.length = 8; + sfb->fb.var.red.offset = 16; + sfb->fb.var.green.offset = 8; + sfb->fb.var.blue.offset = 0; + break; + case 8: + sfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres; + sfb->fb.var.red.length = 3; + sfb->fb.var.green.length = 3; + sfb->fb.var.blue.length = 2; + sfb->fb.var.red.offset = 5; + sfb->fb.var.green.offset = 2; + sfb->fb.var.blue.offset = 0; + break; + case 16: + default: + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres * 2; + sfb->fb.var.red.length = 5; + sfb->fb.var.green.length = 6; + sfb->fb.var.blue.length = 5; + sfb->fb.var.red.offset = 11; + sfb->fb.var.green.offset = 5; + sfb->fb.var.blue.offset = 0; + break; + } + + sfb->width = sfb->fb.var.xres; + sfb->height = sfb->fb.var.yres; + sfb->hz = 60; + smtc_set_timing(sfb); +} + +static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + /* sanity checks */ + if (var->xres_virtual < var->xres) + var->xres_virtual = var->xres; + + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + + /* set valid default bpp */ + if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16) && + (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32)) + var->bits_per_pixel = 16; + + return 0; +} + +static int smtc_set_par(struct fb_info *info) +{ + smtcfb_setmode(info->par); + + return 0; +} + +static struct fb_ops smtcfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = smtc_check_var, + .fb_set_par = smtc_set_par, + .fb_setcolreg = smtc_setcolreg, + .fb_blank = smtc_blank, + .fb_fillrect = cfb_fillrect, + .fb_imageblit = cfb_imageblit, + .fb_copyarea = cfb_copyarea, +#ifdef __BIG_ENDIAN + .fb_read = smtcfb_read, + .fb_write = smtcfb_write, +#endif +}; + +/* + * alloc struct smtcfb_info and assign default values + */ +static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev) +{ + struct smtcfb_info *sfb; + + sfb = kzalloc(sizeof(*sfb), GFP_KERNEL); + + if (!sfb) + return NULL; + + sfb->pdev = pdev; + + sfb->fb.flags = FBINFO_FLAG_DEFAULT; + sfb->fb.fbops = &smtcfb_ops; + sfb->fb.fix = smtcfb_fix; + sfb->fb.var = smtcfb_var; + sfb->fb.pseudo_palette = sfb->colreg; + sfb->fb.par = sfb; + + return sfb; +} + +/* + * free struct smtcfb_info + */ +static void smtc_free_fb_info(struct smtcfb_info *sfb) +{ + kfree(sfb); +} + +/* + * Unmap in the memory mapped IO registers + */ + +static void smtc_unmap_mmio(struct smtcfb_info *sfb) +{ + if (sfb && smtc_RegBaseAddress) + smtc_RegBaseAddress = NULL; +} + +/* + * Map in the screen memory + */ + +static int smtc_map_smem(struct smtcfb_info *sfb, + struct pci_dev *pdev, u_long smem_len) +{ + + sfb->fb.fix.smem_start = pci_resource_start(pdev, 0); + +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 32) + sfb->fb.fix.smem_start += 0x800000; +#endif + + sfb->fb.fix.smem_len = smem_len; + + sfb->fb.screen_base = sfb->lfb; + + if (!sfb->fb.screen_base) { + dev_err(&pdev->dev, + "%s: unable to map screen memory\n", sfb->fb.fix.id); + return -ENOMEM; + } + + return 0; +} + +/* + * Unmap in the screen memory + * + */ +static void smtc_unmap_smem(struct smtcfb_info *sfb) +{ + if (sfb && sfb->fb.screen_base) { + iounmap(sfb->fb.screen_base); + sfb->fb.screen_base = NULL; + } +} + +/* + * We need to wake up the device and make sure its in linear memory mode. + */ +static inline void sm7xx_init_hw(void) +{ + outb_p(0x18, 0x3c4); + outb_p(0x11, 0x3c5); +} + +static int smtcfb_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct smtcfb_info *sfb; + u_long smem_size = 0x00800000; /* default 8MB */ + int err; + unsigned long mmio_base; + + dev_info(&pdev->dev, "Silicon Motion display driver."); + + err = pci_enable_device(pdev); /* enable SMTC chip */ + if (err) + return err; + + sprintf(smtcfb_fix.id, "sm%Xfb", ent->device); + + sfb = smtc_alloc_fb_info(pdev); + + if (!sfb) { + err = -ENOMEM; + goto failed_free; + } + + sfb->chip_id = ent->device; + + pci_set_drvdata(pdev, sfb); + + sm7xx_init_hw(); + + /* get mode parameter from smtc_scr_info */ + if (smtc_scr_info.lfb_width != 0) { + sfb->fb.var.xres = smtc_scr_info.lfb_width; + sfb->fb.var.yres = smtc_scr_info.lfb_height; + sfb->fb.var.bits_per_pixel = smtc_scr_info.lfb_depth; + } else { + /* default resolution 1024x600 16bit mode */ + sfb->fb.var.xres = SCREEN_X_RES; + sfb->fb.var.yres = SCREEN_Y_RES; + sfb->fb.var.bits_per_pixel = SCREEN_BPP; + } + +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 24) + sfb->fb.var.bits_per_pixel = (smtc_scr_info.lfb_depth = 32); +#endif + /* Map address and memory detection */ + mmio_base = pci_resource_start(pdev, 0); + pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id); + + switch (sfb->chip_id) { + case 0x710: + case 0x712: + sfb->fb.fix.mmio_start = mmio_base + 0x00400000; + sfb->fb.fix.mmio_len = 0x00400000; + smem_size = SM712_VIDEOMEMORYSIZE; +#ifdef __BIG_ENDIAN + sfb->lfb = ioremap(mmio_base, 0x00c00000); +#else + sfb->lfb = ioremap(mmio_base, 0x00800000); +#endif + sfb->mmio = (smtc_RegBaseAddress = + sfb->lfb + 0x00700000); + sfb->dp_regs = sfb->lfb + 0x00408000; + sfb->vp_regs = sfb->lfb + 0x0040c000; +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 32) { + sfb->lfb += 0x800000; + dev_info(&pdev->dev, "sfb->lfb=%p", sfb->lfb); + } +#endif + if (!smtc_RegBaseAddress) { + dev_err(&pdev->dev, + "%s: unable to map memory mapped IO!", + sfb->fb.fix.id); + err = -ENOMEM; + goto failed_fb; + } + + /* set MCLK = 14.31818 * (0x16 / 0x2) */ + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x62, 0x3e); + /* enable PCI burst */ + smtc_seqw(0x17, 0x20); + /* enable word swap */ +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 32) + smtc_seqw(0x17, 0x30); +#endif + break; + case 0x720: + sfb->fb.fix.mmio_start = mmio_base; + sfb->fb.fix.mmio_len = 0x00200000; + smem_size = SM722_VIDEOMEMORYSIZE; + sfb->dp_regs = ioremap(mmio_base, 0x00a00000); + sfb->lfb = sfb->dp_regs + 0x00200000; + sfb->mmio = (smtc_RegBaseAddress = + sfb->dp_regs + 0x000c0000); + sfb->vp_regs = sfb->dp_regs + 0x800; + + smtc_seqw(0x62, 0xff); + smtc_seqw(0x6a, 0x0d); + smtc_seqw(0x6b, 0x02); + break; + default: + dev_err(&pdev->dev, + "No valid Silicon Motion display chip was detected!"); + + goto failed_fb; + } + + /* can support 32 bpp */ + if (15 == sfb->fb.var.bits_per_pixel) + sfb->fb.var.bits_per_pixel = 16; + + sfb->fb.var.xres_virtual = sfb->fb.var.xres; + sfb->fb.var.yres_virtual = sfb->fb.var.yres; + err = smtc_map_smem(sfb, pdev, smem_size); + if (err) + goto failed; + + smtcfb_setmode(sfb); + + err = register_framebuffer(&sfb->fb); + if (err < 0) + goto failed; + + dev_info(&pdev->dev, + "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.", + sfb->chip_id, sfb->chip_rev_id, sfb->fb.var.xres, + sfb->fb.var.yres, sfb->fb.var.bits_per_pixel); + + return 0; + +failed: + dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail."); + + smtc_unmap_smem(sfb); + smtc_unmap_mmio(sfb); +failed_fb: + smtc_free_fb_info(sfb); + +failed_free: + pci_disable_device(pdev); + + return err; +} + +/* + * 0x710 (LynxEM) + * 0x712 (LynxEM+) + * 0x720 (Lynx3DM, Lynx3DM+) + */ +static const struct pci_device_id smtcfb_pci_table[] = { + { PCI_DEVICE(0x126f, 0x710), }, + { PCI_DEVICE(0x126f, 0x712), }, + { PCI_DEVICE(0x126f, 0x720), }, + {0,} +}; + +static void smtcfb_pci_remove(struct pci_dev *pdev) +{ + struct smtcfb_info *sfb; + + sfb = pci_get_drvdata(pdev); + smtc_unmap_smem(sfb); + smtc_unmap_mmio(sfb); + unregister_framebuffer(&sfb->fb); + smtc_free_fb_info(sfb); +} + +#ifdef CONFIG_PM +static int smtcfb_pci_suspend(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct smtcfb_info *sfb; + + sfb = pci_get_drvdata(pdev); + + /* set the hw in sleep mode use external clock and self memory refresh + * so that we can turn off internal PLLs later on + */ + smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0)); + smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7)); + + console_lock(); + fb_set_suspend(&sfb->fb, 1); + console_unlock(); + + /* additionally turn off all function blocks including internal PLLs */ + smtc_seqw(0x21, 0xff); + + return 0; +} + +static int smtcfb_pci_resume(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct smtcfb_info *sfb; + + sfb = pci_get_drvdata(pdev); + + /* reinit hardware */ + sm7xx_init_hw(); + switch (sfb->chip_id) { + case 0x710: + case 0x712: + /* set MCLK = 14.31818 * (0x16 / 0x2) */ + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x62, 0x3e); + /* enable PCI burst */ + smtc_seqw(0x17, 0x20); +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 32) + smtc_seqw(0x17, 0x30); +#endif + break; + case 0x720: + smtc_seqw(0x62, 0xff); + smtc_seqw(0x6a, 0x0d); + smtc_seqw(0x6b, 0x02); + break; + } + + smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0)); + smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb)); + + smtcfb_setmode(sfb); + + console_lock(); + fb_set_suspend(&sfb->fb, 0); + console_unlock(); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume); +#define SM7XX_PM_OPS (&sm7xx_pm_ops) + +#else /* !CONFIG_PM */ + +#define SM7XX_PM_OPS NULL + +#endif /* !CONFIG_PM */ + +static struct pci_driver smtcfb_driver = { + .name = "smtcfb", + .id_table = smtcfb_pci_table, + .probe = smtcfb_pci_probe, + .remove = smtcfb_pci_remove, + .driver.pm = SM7XX_PM_OPS, +}; + +module_pci_driver(smtcfb_driver); + +MODULE_AUTHOR("Siliconmotion "); +MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From d14d0dade5e48c294bf02c08d1c65a1333288c20 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 19 Jan 2015 13:41:01 +0530 Subject: staging: sm7xxfb: update TODO file update the email addresses in the TODO file, also update the final destination of this driver. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sm7xxfb/TODO b/drivers/staging/sm7xxfb/TODO index 1fcead5..7cb0b24 100644 --- a/drivers/staging/sm7xxfb/TODO +++ b/drivers/staging/sm7xxfb/TODO @@ -3,7 +3,10 @@ TODO: - 2D acceleration support - use kernel coding style - refine the code and remove unused code -- move it to drivers/video/sm7xxfb.c +- move it to drivers/video/fbdev/sm7xxfb.c -Please send any patches to Greg Kroah-Hartman and -Teddy Wang . +Please send any patches to + Greg Kroah-Hartman + Sudip Mukherjee + Teddy Wang + Sudip Mukherjee -- cgit v0.10.2 From 13e4e9b84ba98dd448b3807467e8a1b1cf3bebf6 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 19 Jan 2015 13:41:02 +0530 Subject: MAINTAINERS: update for SM7XX driver add myself and Teddy Wang as the Maintainer of the SM7XX FRAME BUFFER DRIVER. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/MAINTAINERS b/MAINTAINERS index 0dbe230..9cff717 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9179,6 +9179,14 @@ L: linux-wireless@vger.kernel.org S: Maintained F: drivers/staging/rtl8723au/ +STAGING - SILICON MOTION SM7XX FRAME BUFFER DRIVER +M: Sudip Mukherjee +M: Teddy Wang +M: Sudip Mukherjee +L: linux-fbdev@vger.kernel.org +S: Maintained +F: drivers/staging/sm7xxfb/ + STAGING - SLICOSS M: Lior Dotan M: Christopher Harrer -- cgit v0.10.2 From a1f6da67beeb1a9225231a66242282e4fee86d5a Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 19 Jan 2015 13:41:03 +0530 Subject: staging: sm7xxfb: add missing blank line checkpatch cleanup to add missing blank line after declaration Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index c550b71..6bce9f1 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -259,6 +259,7 @@ static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green, if (regno < 16) { if (sfb->fb.var.bits_per_pixel == 16) { u32 *pal = sfb->fb.pseudo_palette; + val = chan_to_field(red, &sfb->fb.var.red); val |= chan_to_field(green, &sfb->fb.var.green); val |= chan_to_field(blue, &sfb->fb.var.blue); @@ -273,6 +274,7 @@ static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green, #endif } else { u32 *pal = sfb->fb.pseudo_palette; + val = chan_to_field(red, &sfb->fb.var.red); val |= chan_to_field(green, &sfb->fb.var.green); val |= chan_to_field(blue, &sfb->fb.var.blue); -- cgit v0.10.2 From 53f54a48acfd37ee5b660d3b5332826d3aaf2f79 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 19 Jan 2015 13:41:04 +0530 Subject: staging: sm7xxfb: no space is necessary after a cast checkpatch cleanup: space is not necessary after cast Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index 6bce9f1..6f0469a 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -352,8 +352,8 @@ static ssize_t smtcfb_read(struct fb_info *info, char __user *buf, size_t dst++; } if (c & 3) { - u8 *dst8 = (u8 *) dst; - u8 __iomem *src8 = (u8 __iomem *) src; + u8 *dst8 = (u8 *)dst; + u8 __iomem *src8 = (u8 __iomem *)src; for (i = c & 3; i--;) { if (i & 1) { @@ -363,7 +363,7 @@ static ssize_t smtcfb_read(struct fb_info *info, char __user *buf, size_t src8 += 2; } } - src = (u32 __iomem *) src8; + src = (u32 __iomem *)src8; } if (copy_to_user(buf, buffer, c)) { @@ -442,8 +442,8 @@ smtcfb_write(struct fb_info *info, const char __user *buf, size_t count, src++; } if (c & 3) { - u8 *src8 = (u8 *) src; - u8 __iomem *dst8 = (u8 __iomem *) dst; + u8 *src8 = (u8 *)src; + u8 __iomem *dst8 = (u8 __iomem *)dst; for (i = c & 3; i--;) { if (i & 1) { @@ -453,7 +453,7 @@ smtcfb_write(struct fb_info *info, const char __user *buf, size_t count, dst8 += 2; } } - dst = (u32 __iomem *) dst8; + dst = (u32 __iomem *)dst8; } *ppos += c; -- cgit v0.10.2 From f64ac7deba5cf9f930c5379c49dc668302e9c3e1 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 19 Jan 2015 13:41:05 +0530 Subject: staging: sm7xxfb: remove unnecessary blank lines checkpatch cleanup: blank lines are not necessary before closing brace and after opening brace. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index 6f0469a..097747c 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -298,7 +298,6 @@ static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green, } return 0; - } #ifdef __BIG_ENDIAN @@ -482,7 +481,6 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb) VGAMode[j].mmSizeY == sfb->height && VGAMode[j].bpp == sfb->fb.var.bits_per_pixel && VGAMode[j].hz == sfb->hz) { - dev_dbg(&sfb->pdev->dev, "VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d VGAMode[j].bpp=%d VGAMode[j].hz=%d\n", VGAMode[j].mmSizeX, VGAMode[j].mmSizeY, @@ -571,7 +569,6 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb) } writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride), sfb->vp_regs + 0x10); - } static void smtc_set_timing(struct smtcfb_info *sfb) @@ -725,7 +722,6 @@ static void smtc_unmap_mmio(struct smtcfb_info *sfb) static int smtc_map_smem(struct smtcfb_info *sfb, struct pci_dev *pdev, u_long smem_len) { - sfb->fb.fix.smem_start = pci_resource_start(pdev, 0); #ifdef __BIG_ENDIAN -- cgit v0.10.2 From f049a526ad3dc46241b7f7a1115fc2c421518d43 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 19 Jan 2015 13:41:06 +0530 Subject: staging: sm7xxfb: fix alignment checkpatch cleanup: alignment should match open parenthesis Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index 097747c..2ae9fd0 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -509,7 +509,7 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb) (i + 0x30) != 0x6a && (i + 0x30) != 0x6b) smtc_seqw(i + 0x30, - VGAMode[j].Init_SR30_SR75[i]); + VGAMode[j].Init_SR30_SR75[i]); /* init SEQ register SR80 - SR93 */ for (i = 0; i < SIZE_SR80_SR93; i++) @@ -720,7 +720,7 @@ static void smtc_unmap_mmio(struct smtcfb_info *sfb) */ static int smtc_map_smem(struct smtcfb_info *sfb, - struct pci_dev *pdev, u_long smem_len) + struct pci_dev *pdev, u_long smem_len) { sfb->fb.fix.smem_start = pci_resource_start(pdev, 0); @@ -764,7 +764,7 @@ static inline void sm7xx_init_hw(void) } static int smtcfb_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { struct smtcfb_info *sfb; u_long smem_size = 0x00800000; /* default 8MB */ -- cgit v0.10.2 From ab80496a813aefafd0e33619b8b6c061a4d5c3f4 Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Thu, 8 Jan 2015 17:40:27 +0100 Subject: iio: Deselect IIO_TRIGGER for IIO_KFIFO_BUF iio kfifo can be used without trigger support so there is no need to build it. Signed-off-by: Karol Wrona Reviewed-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 345395e..4132935 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -27,7 +27,6 @@ boolean "IIO callback buffer used for push in-kernel interfaces" usage. That is, those where the data is pushed to the consumer. config IIO_KFIFO_BUF - select IIO_TRIGGER tristate "Industrial I/O buffering based on kfifo" help A simple fifo based on kfifo. Note that this currently provides -- cgit v0.10.2 From 03af03ad7c6723e0f87568e4ffe66ceb9608bfe7 Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Wed, 7 Jan 2015 19:36:11 +0100 Subject: iio: Add new operating mode for non triggered sw buffers There was a need for non triggered software buffer type. It can be used when triggered model does not fit and INDIO_BUFFER_HARDWARE causes confusion because the data stream can be obtained not directly form hardware backend. Suggested-by: Jonathan Cameron Signed-off-by: Karol Wrona Reviewed-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 403b728..7133314 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -639,6 +639,8 @@ static int __iio_update_buffers(struct iio_dev *indio_dev, indio_dev->currentmode = INDIO_BUFFER_TRIGGERED; } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) { indio_dev->currentmode = INDIO_BUFFER_HARDWARE; + } else if (indio_dev->modes & INDIO_BUFFER_SOFTWARE) { + indio_dev->currentmode = INDIO_BUFFER_SOFTWARE; } else { /* Should never be reached */ ret = -EINVAL; goto error_run_postdisable; diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 878d861..5902020 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -286,10 +286,11 @@ static inline s64 iio_get_time_ns(void) /* Device operating modes */ #define INDIO_DIRECT_MODE 0x01 #define INDIO_BUFFER_TRIGGERED 0x02 +#define INDIO_BUFFER_SOFTWARE 0x04 #define INDIO_BUFFER_HARDWARE 0x08 #define INDIO_ALL_BUFFER_MODES \ - (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE) + (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE | INDIO_BUFFER_SOFTWARE) #define INDIO_MAX_RAW_ELEMENTS 4 @@ -593,7 +594,8 @@ void devm_iio_trigger_free(struct device *dev, struct iio_trigger *iio_trig); static inline bool iio_buffer_enabled(struct iio_dev *indio_dev) { return indio_dev->currentmode - & (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE); + & (INDIO_BUFFER_TRIGGERED | INDIO_BUFFER_HARDWARE | + INDIO_BUFFER_SOFTWARE); } /** -- cgit v0.10.2 From 2179aabe0122b476a3bd9f5e0716d86829f71638 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Fri, 16 Jan 2015 00:24:14 +0200 Subject: iio: industrialio-event: Fix typo 's/dynically/dynamically/' Signed-off-by: Roberta Dobrescu Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 3f5cee0..78cf115 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -411,7 +411,7 @@ static inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev) { int j, ret, attrcount = 0; - /* Dynically created from the channels array */ + /* Dynamically created from the channels array */ for (j = 0; j < indio_dev->num_channels; j++) { ret = iio_device_add_event_sysfs(indio_dev, &indio_dev->channels[j]); -- cgit v0.10.2 From 2cdc560abe4c1a4eaf7c62c4542e562aa1f6e8f7 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Fri, 16 Jan 2015 00:25:02 +0200 Subject: iio: light: tcs3414: Fix misindented lines Signed-off-by: Roberta Dobrescu Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c index a9e449b..71c2bde 100644 --- a/drivers/iio/light/tcs3414.c +++ b/drivers/iio/light/tcs3414.c @@ -149,8 +149,8 @@ static int tcs3414_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - i = (data->gain & TCS3414_GAIN_MASK) >> TCS3414_GAIN_SHIFT; - *val = tcs3414_scales[i][0]; + i = (data->gain & TCS3414_GAIN_MASK) >> TCS3414_GAIN_SHIFT; + *val = tcs3414_scales[i][0]; *val2 = tcs3414_scales[i][1]; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_INT_TIME: -- cgit v0.10.2 From a86ea55790b397d7b389af0466c316b5a9984e86 Mon Sep 17 00:00:00 2001 From: Roberta Dobrescu Date: Fri, 16 Jan 2015 00:24:41 +0200 Subject: iio: light: cm32181: Fix typo 's/claibscale/calibscale/' Signed-off-by: Roberta Dobrescu Reviewed-by: Daniel Baluta Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c index ad36b29..5d12ae54 100644 --- a/drivers/iio/light/cm32181.c +++ b/drivers/iio/light/cm32181.c @@ -169,7 +169,7 @@ static int cm32181_write_als_it(struct cm32181_chip *cm32181, int val) * @cm32181: pointer of struct cm32181. * * Convert sensor raw data to lux. It depends on integration - * time and claibscale variable. + * time and calibscale variable. * * Return: Positive value is lux, otherwise is error code. */ -- cgit v0.10.2 From 9bd9c20279827caeef91be5ec5e182b483e4de00 Mon Sep 17 00:00:00 2001 From: Phani Movva Date: Tue, 6 Jan 2015 17:47:36 -0300 Subject: DT: iio: adc: Add CC_10001 binding documentation Add the devicetree binding document for Cosmic Circuits 10001 ADC device. Reviewed-by: Andrew Bresticker Acked-by: Rob Herring Signed-off-by: Phani Movva Signed-off-by: Naidu Tellapati Signed-off-by: Ezequiel Garcia Signed-off-by: Jonathan Cameron diff --git a/Documentation/devicetree/bindings/iio/adc/cc10001_adc.txt b/Documentation/devicetree/bindings/iio/adc/cc10001_adc.txt new file mode 100644 index 0000000..904f76d --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/cc10001_adc.txt @@ -0,0 +1,22 @@ +* Cosmic Circuits - Analog to Digital Converter (CC-10001-ADC) + +Required properties: + - compatible: Should be "cosmic,10001-adc" + - reg: Should contain adc registers location and length. + - clock-names: Should contain "adc". + - clocks: Should contain a clock specifier for each entry in clock-names + - vref-supply: The regulator supply ADC reference voltage. + +Optional properties: + - adc-reserved-channels: Bitmask of reserved channels, + i.e. channels that cannot be used by the OS. + +Example: +adc: adc@18101600 { + compatible = "cosmic,10001-adc"; + reg = <0x18101600 0x24>; + adc-reserved-channels = <0x2>; + clocks = <&adc_clk>; + clock-names = "adc"; + vref-supply = <®_1v8>; +}; -- cgit v0.10.2 From efce73f7121d2ca19878cac9c99b6394589e9850 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Tue, 6 Jan 2015 17:47:37 -0300 Subject: DT: Add a vendor prefix for Cosmic Circuits Reviewed-by: Andrew Bresticker Acked-by: Rob Herring Signed-off-by: Ezequiel Garcia Signed-off-by: Jonathan Cameron diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index b1df0ad..014770f 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -36,6 +36,7 @@ chunghwa Chunghwa Picture Tubes Ltd. cirrus Cirrus Logic, Inc. cnm Chips&Media, Inc. cortina Cortina Systems, Inc. +cosmic Cosmic Circuits crystalfontz Crystalfontz America, Inc. dallas Maxim Integrated Products (formerly Dallas Semiconductor) davicom DAVICOM Semiconductor, Inc. -- cgit v0.10.2 From 3a70eb878585b43895232141c70162643ac2f89b Mon Sep 17 00:00:00 2001 From: Asaf Vertz Date: Tue, 20 Jan 2015 12:43:38 +0200 Subject: staging: iio: tsl2583: fix format string warnings Fixed the following warnings (reported by cppcheck): [drivers/staging/iio/light/tsl2583.c:695]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [drivers/staging/iio/light/tsl2583.c:695]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned int'. [drivers/staging/iio/light/tsl2583.c:695]: (warning) %d in format string (no. 3) requires 'int' but the argument type is 'unsigned int'. Signed-off-by: Asaf Vertz Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/light/tsl2583.c b/drivers/staging/iio/light/tsl2583.c index cc4ddcc..8afae8e 100644 --- a/drivers/staging/iio/light/tsl2583.c +++ b/drivers/staging/iio/light/tsl2583.c @@ -692,7 +692,7 @@ static ssize_t taos_luxtable_show(struct device *dev, int offset = 0; for (i = 0; i < ARRAY_SIZE(taos_device_lux); i++) { - offset += sprintf(buf + offset, "%d,%d,%d,", + offset += sprintf(buf + offset, "%u,%u,%u,", taos_device_lux[i].ratio, taos_device_lux[i].ch0, taos_device_lux[i].ch1); -- cgit v0.10.2 From f0002b3bd97b8de5a9e6ecf359821e85f1f22ed3 Mon Sep 17 00:00:00 2001 From: Asaf Vertz Date: Tue, 20 Jan 2015 09:25:22 +0200 Subject: staging: iio: ad5933: fix format string warnings Fixed the following warnings (reported by cppcheck): [drivers/staging/iio/impedance-analyzer/ad5933.c:363]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [drivers/staging/iio/impedance-analyzer/ad5933.c:367]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [drivers/staging/iio/impedance-analyzer/ad5933.c:367]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned int'. [drivers/staging/iio/impedance-analyzer/ad5933.c:367]: (warning) %d in format string (no. 3) requires 'int' but the argument type is 'unsigned int'. [drivers/staging/iio/impedance-analyzer/ad5933.c:367]: (warning) %d in format string (no. 4) requires 'int' but the argument type is 'unsigned int'. Signed-off-by: Asaf Vertz Acked-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index e90653f..7919439 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -360,11 +360,11 @@ static ssize_t ad5933_show(struct device *dev, mutex_lock(&indio_dev->mlock); switch ((u32) this_attr->address) { case AD5933_OUT_RANGE: - len = sprintf(buf, "%d\n", + len = sprintf(buf, "%u\n", st->range_avail[(st->ctrl_hb >> 1) & 0x3]); break; case AD5933_OUT_RANGE_AVAIL: - len = sprintf(buf, "%d %d %d %d\n", st->range_avail[0], + len = sprintf(buf, "%u %u %u %u\n", st->range_avail[0], st->range_avail[3], st->range_avail[2], st->range_avail[1]); break; -- cgit v0.10.2 From 3e5976dcd13f2d385f0742b02b1071230ce17f15 Mon Sep 17 00:00:00 2001 From: Asaf Vertz Date: Tue, 20 Jan 2015 11:27:58 +0200 Subject: staging: iio: tsl2x7x_core: fix format string warnings Fixed the following warnings (reported by cppcheck): [drivers/staging/iio/light/tsl2x7x_core.c:1150]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [drivers/staging/iio/light/tsl2x7x_core.c:1150]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned int'. [drivers/staging/iio/light/tsl2x7x_core.c:1150]: (warning) %d in format string (no. 3) requires 'int' but the argument type is 'unsigned int'. Signed-off-by: Asaf Vertz Signed-off-by: Jonathan Cameron diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c index 423f96b..4a5dc26 100644 --- a/drivers/staging/iio/light/tsl2x7x_core.c +++ b/drivers/staging/iio/light/tsl2x7x_core.c @@ -1147,7 +1147,7 @@ static ssize_t tsl2x7x_luxtable_show(struct device *dev, int offset = 0; while (i < (TSL2X7X_MAX_LUX_TABLE_SIZE * 3)) { - offset += snprintf(buf + offset, PAGE_SIZE, "%d,%d,%d,", + offset += snprintf(buf + offset, PAGE_SIZE, "%u,%u,%u,", chip->tsl2x7x_device_lux[i].ratio, chip->tsl2x7x_device_lux[i].ch0, chip->tsl2x7x_device_lux[i].ch1); -- cgit v0.10.2 From 2b89635e9a9e7cae5d137384842c3da7726ed197 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 7 Jan 2015 10:55:53 -0800 Subject: iio: hid_sensor_hub: Common PM functions To improvement power and performance, both regular and run time callbacks are introduced. Because of auto suspend delay, two consecutive read don't have to go through full power on/off procedure. The auto suspend time can be adjusted using regular power attributes of PM sysfs. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c index 92068cd..2f1d535b 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c @@ -22,16 +22,18 @@ #include #include #include +#include #include #include #include #include #include "hid-sensor-trigger.h" -int hid_sensor_power_state(struct hid_sensor_common *st, bool state) +static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state) { int state_val; int report_val; + s32 poll_value = 0; if (state) { if (sensor_hub_device_open(st->hsdev)) @@ -47,6 +49,8 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) st->report_state.report_id, st->report_state.index, HID_USAGE_SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM); + + poll_value = hid_sensor_read_poll_value(st); } else { if (!atomic_dec_and_test(&st->data_ready)) return 0; @@ -78,10 +82,36 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state) sensor_hub_get_feature(st->hsdev, st->power_state.report_id, st->power_state.index, &state_val); + if (state && poll_value) + msleep_interruptible(poll_value * 2); + return 0; } EXPORT_SYMBOL(hid_sensor_power_state); +int hid_sensor_power_state(struct hid_sensor_common *st, bool state) +{ +#ifdef CONFIG_PM + int ret; + + if (state) + ret = pm_runtime_get_sync(&st->pdev->dev); + else { + pm_runtime_mark_last_busy(&st->pdev->dev); + ret = pm_runtime_put_autosuspend(&st->pdev->dev); + } + if (ret < 0) { + if (state) + pm_runtime_put_noidle(&st->pdev->dev); + return ret; + } + + return 0; +#else + return _hid_sensor_power_state(st, state); +#endif +} + static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) { @@ -125,8 +155,21 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, attrb->trigger = trig; indio_dev->trig = iio_trigger_get(trig); - return ret; + ret = pm_runtime_set_active(&indio_dev->dev); + if (ret) + goto error_unreg_trigger; + iio_device_set_drvdata(indio_dev, attrb); + pm_suspend_ignore_children(&attrb->pdev->dev, true); + pm_runtime_enable(&attrb->pdev->dev); + /* Default to 3 seconds, but can be changed from sysfs */ + pm_runtime_set_autosuspend_delay(&attrb->pdev->dev, + 3000); + pm_runtime_use_autosuspend(&attrb->pdev->dev); + + return ret; +error_unreg_trigger: + iio_trigger_unregister(trig); error_free_trig: iio_trigger_free(trig); error_ret: @@ -134,6 +177,34 @@ error_ret: } EXPORT_SYMBOL(hid_sensor_setup_trigger); +#ifdef CONFIG_PM +static int hid_sensor_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); + + return _hid_sensor_power_state(attrb, false); +} + +static int hid_sensor_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct hid_sensor_common *attrb = iio_device_get_drvdata(indio_dev); + + return _hid_sensor_power_state(attrb, true); +} + +#endif + +const struct dev_pm_ops hid_sensor_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(hid_sensor_suspend, hid_sensor_resume) + SET_RUNTIME_PM_OPS(hid_sensor_suspend, + hid_sensor_resume, NULL) +}; +EXPORT_SYMBOL(hid_sensor_pm_ops); + MODULE_AUTHOR("Srinivas Pandruvada "); MODULE_DESCRIPTION("HID Sensor trigger processing"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h index 0f8e78c..9f4713f 100644 --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h @@ -19,6 +19,11 @@ #ifndef _HID_SENSOR_TRIGGER_H #define _HID_SENSOR_TRIGGER_H +#include +#include + +extern const struct dev_pm_ops hid_sensor_pm_ops; + int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name, struct hid_sensor_common *attrb); void hid_sensor_remove_trigger(struct hid_sensor_common *attrb); -- cgit v0.10.2 From cbbcc937090b0d3137eac58759480b13d73f159d Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 7 Jan 2015 10:55:54 -0800 Subject: iio: hid-sensor-accel-3d: Introduce PM Use common hid sensor iio pm functions. Also the poll time read and wait is part of power up function of hid sensor iio pm function, so remove from the client drivers. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index d5d95317..df6a593 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -111,19 +111,12 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev, int report_id = -1; u32 address; int ret_type; - s32 poll_value; *val = 0; *val2 = 0; switch (mask) { case 0: - poll_value = hid_sensor_read_poll_value( - &accel_state->common_attributes); - if (poll_value < 0) - return -EINVAL; - hid_sensor_power_state(&accel_state->common_attributes, true); - msleep_interruptible(poll_value * 2); report_id = accel_state->accel[chan->scan_index].report_id; address = accel_3d_addresses[chan->scan_index]; if (report_id >= 0) @@ -419,6 +412,7 @@ static struct platform_driver hid_accel_3d_platform_driver = { .id_table = hid_accel_3d_ids, .driver = { .name = KBUILD_MODNAME, + .pm = &hid_sensor_pm_ops, }, .probe = hid_accel_3d_probe, .remove = hid_accel_3d_remove, -- cgit v0.10.2 From 27ce4239367793f1f008d2f3dac10e3987b9ecd4 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 7 Jan 2015 10:55:55 -0800 Subject: iio: hid-sensor-gyro-3d: Introduce PM Use common hid sensor iio pm functions. Also the poll time read and wait is part of power up function of hid sensor iio pm function, so remove from the client drivers. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c index a3ea1e8..a3c3e19 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c @@ -111,19 +111,12 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev, int report_id = -1; u32 address; int ret_type; - s32 poll_value; *val = 0; *val2 = 0; switch (mask) { case 0: - poll_value = hid_sensor_read_poll_value( - &gyro_state->common_attributes); - if (poll_value < 0) - return -EINVAL; - hid_sensor_power_state(&gyro_state->common_attributes, true); - msleep_interruptible(poll_value * 2); report_id = gyro_state->gyro[chan->scan_index].report_id; address = gyro_3d_addresses[chan->scan_index]; if (report_id >= 0) @@ -416,6 +409,7 @@ static struct platform_driver hid_gyro_3d_platform_driver = { .id_table = hid_gyro_3d_ids, .driver = { .name = KBUILD_MODNAME, + .pm = &hid_sensor_pm_ops, }, .probe = hid_gyro_3d_probe, .remove = hid_gyro_3d_remove, -- cgit v0.10.2 From 2c615aff1a8d3264610f1b4825452d49fcfc5cfb Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 7 Jan 2015 10:55:56 -0800 Subject: iio: hid-sensor-als: Introduce PM Use common hid sensor iio pm functions. Also the poll time read and wait is part of power up function of hid sensor iio pm function, so remove from the client drivers. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index a5283d7..948acfc 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -80,7 +80,6 @@ static int als_read_raw(struct iio_dev *indio_dev, int report_id = -1; u32 address; int ret_type; - s32 poll_value; *val = 0; *val2 = 0; @@ -97,15 +96,8 @@ static int als_read_raw(struct iio_dev *indio_dev, break; } if (report_id >= 0) { - poll_value = hid_sensor_read_poll_value( - &als_state->common_attributes); - if (poll_value < 0) - return -EINVAL; - hid_sensor_power_state(&als_state->common_attributes, true); - msleep_interruptible(poll_value * 2); - *val = sensor_hub_input_attr_get_raw_value( als_state->common_attributes.hsdev, HID_USAGE_SENSOR_ALS, address, @@ -381,6 +373,7 @@ static struct platform_driver hid_als_platform_driver = { .id_table = hid_als_ids, .driver = { .name = KBUILD_MODNAME, + .pm = &hid_sensor_pm_ops, }, .probe = hid_als_probe, .remove = hid_als_remove, -- cgit v0.10.2 From a357b9b0c5e7ac8276aebd366297d6441e697a27 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 7 Jan 2015 10:55:57 -0800 Subject: iio: hid-sensor-prox: Introduce PM Use common hid sensor iio pm functions. Also the poll time read and wait is part of power up function of hid sensor iio pm function, so remove from the client drivers. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index f5a5146..3ecf79e 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -75,7 +75,6 @@ static int prox_read_raw(struct iio_dev *indio_dev, int report_id = -1; u32 address; int ret_type; - s32 poll_value; *val = 0; *val2 = 0; @@ -92,16 +91,8 @@ static int prox_read_raw(struct iio_dev *indio_dev, break; } if (report_id >= 0) { - poll_value = hid_sensor_read_poll_value( - &prox_state->common_attributes); - if (poll_value < 0) - return -EINVAL; - hid_sensor_power_state(&prox_state->common_attributes, true); - - msleep_interruptible(poll_value * 2); - *val = sensor_hub_input_attr_get_raw_value( prox_state->common_attributes.hsdev, HID_USAGE_SENSOR_PROX, address, @@ -373,6 +364,7 @@ static struct platform_driver hid_prox_platform_driver = { .id_table = hid_prox_ids, .driver = { .name = KBUILD_MODNAME, + .pm = &hid_sensor_pm_ops, }, .probe = hid_prox_probe, .remove = hid_prox_remove, -- cgit v0.10.2 From 0ef809cf9956c156220155203b0df934f2b2fc14 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 7 Jan 2015 10:55:58 -0800 Subject: iio: hid-sensor-magn-3d: Introduce PM Use common hid sensor iio pm functions. Also the poll time read and wait is part of power up function of hid sensor iio pm function, so remove from the client drivers. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index 6294575..d22993b 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c @@ -157,20 +157,12 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev, int report_id = -1; u32 address; int ret_type; - s32 poll_value; *val = 0; *val2 = 0; switch (mask) { case 0: - poll_value = hid_sensor_read_poll_value( - &magn_state->common_attributes); - if (poll_value < 0) - return -EINVAL; - hid_sensor_power_state(&magn_state->common_attributes, true); - msleep_interruptible(poll_value * 2); - report_id = magn_state->magn[chan->address].report_id; address = magn_3d_addresses[chan->address]; @@ -530,6 +522,7 @@ static struct platform_driver hid_magn_3d_platform_driver = { .id_table = hid_magn_3d_ids, .driver = { .name = KBUILD_MODNAME, + .pm = &hid_sensor_pm_ops, }, .probe = hid_magn_3d_probe, .remove = hid_magn_3d_remove, -- cgit v0.10.2 From feb2b06d630922c62ee72ebe207d4cde2f1cfa22 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 7 Jan 2015 10:55:59 -0800 Subject: iio: hid-sensor-incl-3d: Introduce PM Use common hid sensor iio pm functions. Also the poll time read and wait is part of power up function of hid sensor iio pm function, so remove from the client drivers. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c index 1ff181b..7385446 100644 --- a/drivers/iio/orientation/hid-sensor-incl-3d.c +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c @@ -111,20 +111,12 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev, int report_id = -1; u32 address; int ret_type; - s32 poll_value; *val = 0; *val2 = 0; switch (mask) { case IIO_CHAN_INFO_RAW: - poll_value = hid_sensor_read_poll_value( - &incl_state->common_attributes); - if (poll_value < 0) - return -EINVAL; - hid_sensor_power_state(&incl_state->common_attributes, true); - msleep_interruptible(poll_value * 2); - report_id = incl_state->incl[chan->scan_index].report_id; address = incl_3d_addresses[chan->scan_index]; @@ -437,6 +429,7 @@ static struct platform_driver hid_incl_3d_platform_driver = { .id_table = hid_incl_3d_ids, .driver = { .name = KBUILD_MODNAME, + .pm = &hid_sensor_pm_ops, }, .probe = hid_incl_3d_probe, .remove = hid_incl_3d_remove, -- cgit v0.10.2 From a77945fd4f9af5298196345d89905d604d1fa884 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Wed, 7 Jan 2015 10:56:00 -0800 Subject: iio: hid-sensor-press: Introduce PM Use common hid sensor iio pm functions. Also the poll time read and wait is part of power up function of hid sensor iio pm function, so remove from the client drivers. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c index 7649286..1af3149 100644 --- a/drivers/iio/pressure/hid-sensor-press.c +++ b/drivers/iio/pressure/hid-sensor-press.c @@ -79,7 +79,6 @@ static int press_read_raw(struct iio_dev *indio_dev, int report_id = -1; u32 address; int ret_type; - s32 poll_value; *val = 0; *val2 = 0; @@ -96,15 +95,8 @@ static int press_read_raw(struct iio_dev *indio_dev, break; } if (report_id >= 0) { - poll_value = hid_sensor_read_poll_value( - &press_state->common_attributes); - if (poll_value < 0) - return -EINVAL; hid_sensor_power_state(&press_state->common_attributes, true); - - msleep_interruptible(poll_value * 2); - *val = sensor_hub_input_attr_get_raw_value( press_state->common_attributes.hsdev, HID_USAGE_SENSOR_PRESSURE, address, @@ -382,6 +374,7 @@ static struct platform_driver hid_press_platform_driver = { .id_table = hid_press_ids, .driver = { .name = KBUILD_MODNAME, + .pm = &hid_sensor_pm_ops, }, .probe = hid_press_probe, .remove = hid_press_remove, -- cgit v0.10.2 From b84894c7f088ed83d05292e35d3235ebf38a4465 Mon Sep 17 00:00:00 2001 From: Kevin Tsai Date: Thu, 15 Jan 2015 17:41:04 -0800 Subject: iio: Added Capella cm3232 ambient light sensor driver. CM3232 is an advanced ambient light sensor with I2C protocol interface. The I2C slave address is internally hardwired as 0x10 (7-bit). Writing to configure register is byte mode, but reading ALS register requests to use word mode for 16-bit resolution. Signed-off-by: Kevin Tsai Signed-off-by: Jonathan Cameron diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 9f4e382..572a7c4 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -34,6 +34,7 @@ atmel,24c512 i2c serial eeprom (24cxx) atmel,24c1024 i2c serial eeprom (24cxx) atmel,at97sc3204t i2c trusted platform module (TPM) capella,cm32181 CM32181: Ambient Light Sensor +capella,cm3232 CM3232: Ambient Light Sensor catalyst,24c32 i2c serial eeprom cirrus,cs42l51 Cirrus Logic CS42L51 audio codec dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock diff --git a/MAINTAINERS b/MAINTAINERS index 2fa3853..8d2d9a2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2379,6 +2379,12 @@ F: security/capability.c F: security/commoncap.c F: kernel/capability.c +CAPELLA MICROSYSTEMS LIGHT SENSOR DRIVER +M: Kevin Tsai +S: Maintained +F: drivers/iio/light/cm* +F: Documentation/devicetree/bindings/i2c/trivial-devices.txt + CC2520 IEEE-802.15.4 RADIO DRIVER M: Varka Bhadram L: linux-wpan@vger.kernel.org diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 5a3237b..ae68c64 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig @@ -48,6 +48,17 @@ config CM32181 To compile this driver as a module, choose M here: the module will be called cm32181. +config CM3232 + depends on I2C + tristate "CM3232 ambient light sensor" + help + Say Y here if you use cm3232. + This option enables ambient light sensor using + Capella Microsystems cm3232 device driver. + + To compile this driver as a module, choose M here: + the module will be called cm3232. + config CM36651 depends on I2C tristate "CM36651 driver" diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 74656c1..b12a516 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_ADJD_S311) += adjd_s311.o obj-$(CONFIG_AL3320A) += al3320a.o obj-$(CONFIG_APDS9300) += apds9300.o obj-$(CONFIG_CM32181) += cm32181.o +obj-$(CONFIG_CM3232) += cm3232.o obj-$(CONFIG_CM36651) += cm36651.o obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o diff --git a/drivers/iio/light/cm3232.c b/drivers/iio/light/cm3232.c new file mode 100644 index 0000000..90e3519 --- /dev/null +++ b/drivers/iio/light/cm3232.c @@ -0,0 +1,403 @@ +/* + * CM3232 Ambient Light Sensor + * + * Copyright (C) 2014-2015 Capella Microsystems Inc. + * Author: Kevin Tsai + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2, as published + * by the Free Software Foundation. + * + * IIO driver for CM3232 (7-bit I2C slave address 0x10). + */ + +#include +#include +#include +#include +#include + +/* Registers Address */ +#define CM3232_REG_ADDR_CMD 0x00 +#define CM3232_REG_ADDR_ALS 0x50 +#define CM3232_REG_ADDR_ID 0x53 + +#define CM3232_CMD_ALS_DISABLE BIT(0) + +#define CM3232_CMD_ALS_IT_SHIFT 2 +#define CM3232_CMD_ALS_IT_MASK (BIT(2) | BIT(3) | BIT(4)) +#define CM3232_CMD_ALS_IT_DEFAULT (0x01 << CM3232_CMD_ALS_IT_SHIFT) + +#define CM3232_CMD_ALS_RESET BIT(6) + +#define CM3232_CMD_DEFAULT CM3232_CMD_ALS_IT_DEFAULT + +#define CM3232_HW_ID 0x32 +#define CM3232_CALIBSCALE_DEFAULT 100000 +#define CM3232_CALIBSCALE_RESOLUTION 100000 +#define CM3232_MLUX_PER_LUX 1000 + +#define CM3232_MLUX_PER_BIT_DEFAULT 64 +#define CM3232_MLUX_PER_BIT_BASE_IT 100000 + +static const struct { + int val; + int val2; + u8 it; +} cm3232_als_it_scales[] = { + {0, 100000, 0}, /* 0.100000 */ + {0, 200000, 1}, /* 0.200000 */ + {0, 400000, 2}, /* 0.400000 */ + {0, 800000, 3}, /* 0.800000 */ + {1, 600000, 4}, /* 1.600000 */ + {3, 200000, 5}, /* 3.200000 */ +}; + +struct cm3232_als_info { + u8 regs_cmd_default; + u8 hw_id; + int calibscale; + int mlux_per_bit; + int mlux_per_bit_base_it; +}; + +static struct cm3232_als_info cm3232_als_info_default = { + .regs_cmd_default = CM3232_CMD_DEFAULT, + .hw_id = CM3232_HW_ID, + .calibscale = CM3232_CALIBSCALE_DEFAULT, + .mlux_per_bit = CM3232_MLUX_PER_BIT_DEFAULT, + .mlux_per_bit_base_it = CM3232_MLUX_PER_BIT_BASE_IT, +}; + +struct cm3232_chip { + struct i2c_client *client; + struct cm3232_als_info *als_info; + u8 regs_cmd; + u16 regs_als; +}; + +/** + * cm3232_reg_init() - Initialize CM3232 + * @chip: pointer of struct cm3232_chip. + * + * Check and initialize CM3232 ambient light sensor. + * + * Return: 0 for success; otherwise for error code. + */ +static int cm3232_reg_init(struct cm3232_chip *chip) +{ + struct i2c_client *client = chip->client; + s32 ret; + + chip->als_info = &cm3232_als_info_default; + + /* Identify device */ + ret = i2c_smbus_read_word_data(client, CM3232_REG_ADDR_ID); + if (ret < 0) { + dev_err(&chip->client->dev, "Error reading addr_id\n"); + return ret; + } + + if ((ret & 0xFF) != chip->als_info->hw_id) + return -ENODEV; + + /* Disable and reset device */ + chip->regs_cmd = CM3232_CMD_ALS_DISABLE | CM3232_CMD_ALS_RESET; + ret = i2c_smbus_write_byte_data(client, CM3232_REG_ADDR_CMD, + chip->regs_cmd); + if (ret < 0) { + dev_err(&chip->client->dev, "Error writing reg_cmd\n"); + return ret; + } + + /* Register default value */ + chip->regs_cmd = chip->als_info->regs_cmd_default; + + /* Configure register */ + ret = i2c_smbus_write_byte_data(client, CM3232_REG_ADDR_CMD, + chip->regs_cmd); + if (ret < 0) + dev_err(&chip->client->dev, "Error writing reg_cmd\n"); + + return 0; +} + +/** + * cm3232_read_als_it() - Get sensor integration time + * @chip: pointer of struct cm3232_chip + * @val: pointer of int to load the integration (sec). + * @val2: pointer of int to load the integration time (microsecond). + * + * Report the current integration time. + * + * Return: IIO_VAL_INT_PLUS_MICRO for success, otherwise -EINVAL. + */ +static int cm3232_read_als_it(struct cm3232_chip *chip, int *val, int *val2) +{ + u16 als_it; + int i; + + als_it = chip->regs_cmd; + als_it &= CM3232_CMD_ALS_IT_MASK; + als_it >>= CM3232_CMD_ALS_IT_SHIFT; + for (i = 0; i < ARRAY_SIZE(cm3232_als_it_scales); i++) { + if (als_it == cm3232_als_it_scales[i].it) { + *val = cm3232_als_it_scales[i].val; + *val2 = cm3232_als_it_scales[i].val2; + return IIO_VAL_INT_PLUS_MICRO; + } + } + + return -EINVAL; +} + +/** + * cm3232_write_als_it() - Write sensor integration time + * @chip: pointer of struct cm3232_chip. + * @val: integration time in second. + * @val2: integration time in microsecond. + * + * Convert integration time to sensor value. + * + * Return: i2c_smbus_write_byte_data command return value. + */ +static int cm3232_write_als_it(struct cm3232_chip *chip, int val, int val2) +{ + struct i2c_client *client = chip->client; + u16 als_it, cmd; + int i; + s32 ret; + + for (i = 0; i < ARRAY_SIZE(cm3232_als_it_scales); i++) { + if (val == cm3232_als_it_scales[i].val && + val2 == cm3232_als_it_scales[i].val2) { + + als_it = cm3232_als_it_scales[i].it; + als_it <<= CM3232_CMD_ALS_IT_SHIFT; + + cmd = chip->regs_cmd & ~CM3232_CMD_ALS_IT_MASK; + cmd |= als_it; + ret = i2c_smbus_write_byte_data(client, + CM3232_REG_ADDR_CMD, + cmd); + if (ret < 0) + return ret; + chip->regs_cmd = cmd; + return 0; + } + } + return -EINVAL; +} + +/** + * cm3232_get_lux() - report current lux value + * @chip: pointer of struct cm3232_chip. + * + * Convert sensor data to lux. It depends on integration + * time and calibscale variable. + * + * Return: Zero or positive value is lux, otherwise error code. + */ +static int cm3232_get_lux(struct cm3232_chip *chip) +{ + struct i2c_client *client = chip->client; + struct cm3232_als_info *als_info = chip->als_info; + int ret; + int val, val2; + int als_it; + u64 lux; + + /* Calculate mlux per bit based on als_it */ + ret = cm3232_read_als_it(chip, &val, &val2); + if (ret < 0) + return -EINVAL; + als_it = val * 1000000 + val2; + lux = (__force u64)als_info->mlux_per_bit; + lux *= als_info->mlux_per_bit_base_it; + lux = div_u64(lux, als_it); + + ret = i2c_smbus_read_word_data(client, CM3232_REG_ADDR_ALS); + if (ret < 0) { + dev_err(&client->dev, "Error reading reg_addr_als\n"); + return ret; + } + + chip->regs_als = (u16)ret; + lux *= chip->regs_als; + lux *= als_info->calibscale; + lux = div_u64(lux, CM3232_CALIBSCALE_RESOLUTION); + lux = div_u64(lux, CM3232_MLUX_PER_LUX); + + if (lux > 0xFFFF) + lux = 0xFFFF; + + return (int)lux; +} + +static int cm3232_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct cm3232_chip *chip = iio_priv(indio_dev); + struct cm3232_als_info *als_info = chip->als_info; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + ret = cm3232_get_lux(chip); + if (ret < 0) + return ret; + *val = ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBSCALE: + *val = als_info->calibscale; + return IIO_VAL_INT; + case IIO_CHAN_INFO_INT_TIME: + return cm3232_read_als_it(chip, val, val2); + } + + return -EINVAL; +} + +static int cm3232_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct cm3232_chip *chip = iio_priv(indio_dev); + struct cm3232_als_info *als_info = chip->als_info; + + switch (mask) { + case IIO_CHAN_INFO_CALIBSCALE: + als_info->calibscale = val; + return 0; + case IIO_CHAN_INFO_INT_TIME: + return cm3232_write_als_it(chip, val, val2); + } + + return -EINVAL; +} + +/** + * cm3232_get_it_available() - Get available ALS IT value + * @dev: pointer of struct device. + * @attr: pointer of struct device_attribute. + * @buf: pointer of return string buffer. + * + * Display the available integration time in second. + * + * Return: string length. + */ +static ssize_t cm3232_get_it_available(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i, len; + + for (i = 0, len = 0; i < ARRAY_SIZE(cm3232_als_it_scales); i++) + len += scnprintf(buf + len, PAGE_SIZE - len, "%u.%06u ", + cm3232_als_it_scales[i].val, + cm3232_als_it_scales[i].val2); + return len + scnprintf(buf + len, PAGE_SIZE - len, "\n"); +} + +static const struct iio_chan_spec cm3232_channels[] = { + { + .type = IIO_LIGHT, + .info_mask_separate = + BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | + BIT(IIO_CHAN_INFO_INT_TIME), + } +}; + +static IIO_DEVICE_ATTR(in_illuminance_integration_time_available, + S_IRUGO, cm3232_get_it_available, NULL, 0); + +static struct attribute *cm3232_attributes[] = { + &iio_dev_attr_in_illuminance_integration_time_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group cm3232_attribute_group = { + .attrs = cm3232_attributes +}; + +static const struct iio_info cm3232_info = { + .driver_module = THIS_MODULE, + .read_raw = &cm3232_read_raw, + .write_raw = &cm3232_write_raw, + .attrs = &cm3232_attribute_group, +}; + +static int cm3232_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct cm3232_chip *chip; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; + + chip = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + chip->client = client; + + indio_dev->dev.parent = &client->dev; + indio_dev->channels = cm3232_channels; + indio_dev->num_channels = ARRAY_SIZE(cm3232_channels); + indio_dev->info = &cm3232_info; + indio_dev->name = id->name; + indio_dev->modes = INDIO_DIRECT_MODE; + + ret = cm3232_reg_init(chip); + if (ret) { + dev_err(&client->dev, + "%s: register init failed\n", + __func__); + return ret; + } + + return iio_device_register(indio_dev); +} + +static int cm3232_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + + i2c_smbus_write_byte_data(client, CM3232_REG_ADDR_CMD, + CM3232_CMD_ALS_DISABLE); + + iio_device_unregister(indio_dev); + + return 0; +} + +static const struct i2c_device_id cm3232_id[] = { + {"cm3232", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, cm3232_id); + +static const struct of_device_id cm3232_of_match[] = { + {.compatible = "capella,cm3232"}, + {} +}; + +static struct i2c_driver cm3232_driver = { + .driver = { + .name = "cm3232", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(cm3232_of_match), + }, + .id_table = cm3232_id, + .probe = cm3232_probe, + .remove = cm3232_remove, +}; + +module_i2c_driver(cm3232_driver); + +MODULE_AUTHOR("Kevin Tsai "); +MODULE_DESCRIPTION("CM3232 ambient light sensor driver"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 9d9f780000e0a2c2582843ee83612530a16920c8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 11 Jan 2015 15:37:04 +0100 Subject: iio: as3935: Switch to PM ops Switch from the legacy suspend/resume callbacks to device pm ops. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index 466aa43..bc0d68e 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -273,9 +273,9 @@ static void calibrate_as3935(struct as3935_state *st) } #ifdef CONFIG_PM_SLEEP -static int as3935_suspend(struct spi_device *spi, pm_message_t msg) +static int as3935_suspend(struct device *dev) { - struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct as3935_state *st = iio_priv(indio_dev); int val, ret; @@ -293,9 +293,9 @@ err_suspend: return ret; } -static int as3935_resume(struct spi_device *spi) +static int as3935_resume(struct device *dev) { - struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct iio_dev *indio_dev = dev_get_drvdata(dev); struct as3935_state *st = iio_priv(indio_dev); int val, ret; @@ -311,9 +311,12 @@ err_resume: return ret; } + +static SIMPLE_DEV_PM_OPS(as3935_pm_ops, as3935_suspend, as3935_resume); +#define AS3935_PM_OPS (&as3935_pm_ops) + #else -#define as3935_suspend NULL -#define as3935_resume NULL +#define AS3935_PM_OPS NULL #endif static int as3935_probe(struct spi_device *spi) @@ -441,12 +444,11 @@ static struct spi_driver as3935_driver = { .driver = { .name = "as3935", .owner = THIS_MODULE, + .pm = AS3935_PM_OPS, }, .probe = as3935_probe, .remove = as3935_remove, .id_table = as3935_id, - .suspend = as3935_suspend, - .resume = as3935_resume, }; module_spi_driver(as3935_driver); -- cgit v0.10.2 From 72c66644673a61ad85d293de7a61e54b9bdc9682 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sun, 11 Jan 2015 21:10:07 +0200 Subject: iio: core: Introduce ENERGY channel type Human activity sensors report the energy burnt by the user. One of this devices is Freescale's MMA9553L (http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf) that computes the number of calories based on weight and step rate. Introduce a new channel type ENERGY to export these values. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 831db86..3311886 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -282,6 +282,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_current_scale What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale What: /sys/bus/iio/devices/iio:deviceX/in_accel_peak_scale What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_scale +What: /sys/bus/iio/devices/iio:deviceX/in_energy_scale What: /sys/bus/iio/devices/iio:deviceX/in_magn_scale What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_scale What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_scale @@ -1049,6 +1050,15 @@ Description: For a list of available output power modes read in_accel_power_mode_available. +What: /sys/.../iio:deviceX/in_energy_input +What: /sys/.../iio:deviceX/in_energy_raw +KernelVersion: 3.20 +Contact: linux-iio@vger.kernel.org +Description: + This attribute is used to read the energy value reported by the + device (e.g.: human activity sensors report energy burnt by the + user). Units after application of scale are Joules. + What: /sys/bus/iio/devices/iio:deviceX/store_eeprom KernelVersion: 3.4.0 Contact: linux-iio@vger.kernel.org diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 69feb91..8d2c9ba 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -72,6 +72,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_HUMIDITYRELATIVE] = "humidityrelative", [IIO_ACTIVITY] = "activity", [IIO_STEPS] = "steps", + [IIO_ENERGY] = "energy", }; static const char * const iio_modifier_names[] = { diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 904dcbb..26b8a1c 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -32,6 +32,7 @@ enum iio_chan_type { IIO_HUMIDITYRELATIVE, IIO_ACTIVITY, IIO_STEPS, + IIO_ENERGY, }; enum iio_modifier { -- cgit v0.10.2 From cc3c9eecaed65b26ee0661e9e9491fd8d48e3907 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sun, 11 Jan 2015 21:10:08 +0200 Subject: iio: core: Introduce DISTANCE channel type Some devices export an estimation of the distance the user has covered since the last reset. One of this devices is Freescale's MMA9553L (http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf) that computes the distance based on the stride length and step rate. Introduce a new channel type DISTANCE to export these values. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 3311886..c627a9a 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -283,6 +283,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale What: /sys/bus/iio/devices/iio:deviceX/in_accel_peak_scale What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_scale What: /sys/bus/iio/devices/iio:deviceX/in_energy_scale +What: /sys/bus/iio/devices/iio:deviceX/in_distance_scale What: /sys/bus/iio/devices/iio:deviceX/in_magn_scale What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_scale What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_scale @@ -1059,6 +1060,15 @@ Description: device (e.g.: human activity sensors report energy burnt by the user). Units after application of scale are Joules. +What: /sys/.../iio:deviceX/in_distance_input +What: /sys/.../iio:deviceX/in_distance_raw +KernelVersion: 3.20 +Contact: linux-iio@vger.kernel.org +Description: + This attribute is used to read the distance covered by the user + since the last reboot while activated. Units after application + of scale are meters. + What: /sys/bus/iio/devices/iio:deviceX/store_eeprom KernelVersion: 3.4.0 Contact: linux-iio@vger.kernel.org diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 8d2c9ba..655755b 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -73,6 +73,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_ACTIVITY] = "activity", [IIO_STEPS] = "steps", [IIO_ENERGY] = "energy", + [IIO_DISTANCE] = "distance", }; static const char * const iio_modifier_names[] = { diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 26b8a1c..a7de445 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -33,6 +33,7 @@ enum iio_chan_type { IIO_ACTIVITY, IIO_STEPS, IIO_ENERGY, + IIO_DISTANCE, }; enum iio_modifier { -- cgit v0.10.2 From 5a1a932981415661827f7edd9e99943a2a3b7b67 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sun, 11 Jan 2015 21:10:09 +0200 Subject: iio: core: Introduce IIO_VELOCITY and IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z Some devices export the current speed value of the user. One of this devices is Freescale's MMA9553L (http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf) that computes the speed of the user based on the number of steps and stride length. Introduce a new channel type VELOCITY and a modifier for the magniture or norm of the velocity vector, IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index c627a9a..80b5efb1 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -295,6 +295,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_rot_from_north_true_tilt_comp_scale What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_scale What: /sys/bus/iio/devices/iio:deviceX/in_pressure_scale What: /sys/bus/iio/devices/iio:deviceX/in_humidityrelative_scale +What: /sys/bus/iio/devices/iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_scale KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org Description: @@ -1164,3 +1165,12 @@ Contact: linux-iio@vger.kernel.org Description: This attribute is used to read the number of steps taken by the user since the last reboot while activated. + +What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_input +What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_raw +KernelVersion: 3.19 +Contact: linux-iio@vger.kernel.org +Description: + This attribute is used to read the current speed value of the + user (which is the norm or magnitude of the velocity vector). + Units after application of scale are m/s. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 655755b..18a8ab9 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -74,6 +74,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_STEPS] = "steps", [IIO_ENERGY] = "energy", [IIO_DISTANCE] = "distance", + [IIO_VELOCITY] = "velocity", }; static const char * const iio_modifier_names[] = { @@ -99,6 +100,7 @@ static const char * const iio_modifier_names[] = { [IIO_MOD_JOGGING] = "jogging", [IIO_MOD_WALKING] = "walking", [IIO_MOD_STILL] = "still", + [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)", }; /* relies on pairs of these shared then separate */ diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index a7de445..c3601c2 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -34,6 +34,7 @@ enum iio_chan_type { IIO_STEPS, IIO_ENERGY, IIO_DISTANCE, + IIO_VELOCITY, }; enum iio_modifier { @@ -68,6 +69,7 @@ enum iio_modifier { IIO_MOD_JOGGING, IIO_MOD_WALKING, IIO_MOD_STILL, + IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z, }; enum iio_event_type { -- cgit v0.10.2 From d37f6836fa285882450e28d1cbc5a9b624911e7e Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sun, 11 Jan 2015 21:10:10 +0200 Subject: iio: core: Introduce IIO_CHAN_INFO_CALIBWEIGHT Some devices need the weight of the user to compute other parameters. One of this devices is Freescale's MMA9553L (http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf) that needs the weight of the user to compute the number of calories burnt. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 80b5efb1..71dc8db 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -351,6 +351,13 @@ Description: to compute the stride length, distance, speed and activity type. +What: /sys/bus/iio/devices/iio:deviceX/in_energy_calibweight +KernelVersion: 3.20 +Contact: linux-iio@vger.kernel.org +Description: + Weight of the user (in kg). It is needed by some pedometers + to compute the calories burnt by the user. + What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale_available What: /sys/.../iio:deviceX/in_voltageX_scale_available What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 18a8ab9..4ee6fdf 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -125,6 +125,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_INT_TIME] = "integration_time", [IIO_CHAN_INFO_ENABLE] = "en", [IIO_CHAN_INFO_CALIBHEIGHT] = "calibheight", + [IIO_CHAN_INFO_CALIBWEIGHT] = "calibweight", }; /** diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 5902020..51f1643 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -40,6 +40,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_INT_TIME, IIO_CHAN_INFO_ENABLE, IIO_CHAN_INFO_CALIBHEIGHT, + IIO_CHAN_INFO_CALIBWEIGHT, }; enum iio_shared_by { -- cgit v0.10.2 From 27be84236d75c13a83c45d850390f40b58401d97 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sun, 11 Jan 2015 21:10:11 +0200 Subject: iio: core: Introduce CHANGE event type A step detector will generate an interrupt each time N step are detected. A device that has such pedometer functionality is Freescale's MMA9553L: http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf. Introduce IIO_EV_TYPE_CHANGE event type for events that are generated when the channel passes a threshold on the absolute change in value. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 71dc8db..c03a140 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -891,12 +891,24 @@ Description: number or direction is not specified, applies to all channels of this type. -What: /sys/.../events/in_steps_instance_en -KernelVersion: 3.19 +What: /sys/.../events/in_steps_change_en +KernelVersion: 3.20 Contact: linux-iio@vger.kernel.org Description: - Enables or disables step detection. Each time the user takes a step an - event of this type will be generated. + Event generated when channel passes a threshold on the absolute + change in value. E.g. for steps: a step change event is + generated each time the user takes N steps, where N is set using + in_steps_change_value. + +What: /sys/.../events/in_steps_change_value +KernelVersion: 3.20 +Contact: linux-iio@vger.kernel.org +Description: + Specifies the value of change threshold that the + device is comparing against for the events enabled by + [Y][_name]_roc[_rising|falling|]_en. E.g. for steps: + if set to 3, a step change event will be generated every 3 + steps. What: /sys/bus/iio/devices/iio:deviceX/trigger/current_trigger KernelVersion: 2.6.35 diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index 78cf115..b33ce55 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -198,6 +198,7 @@ static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", [IIO_EV_TYPE_INSTANCE] = "instance", + [IIO_EV_TYPE_CHANGE] = "change", }; static const char * const iio_ev_dir_text[] = { diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c index def236a..2e78d58 100644 --- a/drivers/staging/iio/Documentation/iio_event_monitor.c +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -60,6 +60,7 @@ static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", [IIO_EV_TYPE_INSTANCE] = "instance", + [IIO_EV_TYPE_CHANGE] = "change", }; static const char * const iio_ev_dir_text[] = { @@ -179,6 +180,7 @@ static bool event_is_known(struct iio_event_data *event) case IIO_EV_TYPE_THRESH_ADAPTIVE: case IIO_EV_TYPE_MAG_ADAPTIVE: case IIO_EV_TYPE_INSTANCE: + case IIO_EV_TYPE_CHANGE: break; default: return false; diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index c3601c2..3ba3d66 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -79,6 +79,7 @@ enum iio_event_type { IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_TYPE_INSTANCE, + IIO_EV_TYPE_CHANGE, }; enum iio_event_info { -- cgit v0.10.2 From 17a2cbc27981b85a09a48425c2614ae0cb7be8cd Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sun, 11 Jan 2015 21:10:12 +0200 Subject: iio: core: Remove IIO_EV_TYPE_INSTANCE By introducing IIO_EV_TYPE_CHANGE, IIO_EV_TYPE_INSTANCE becomes redundant. The effect of IIO_EV_TYPE_INSTANCE can be obtained by using IIO_EV_TYPE_CHANGE with IIO_EV_INFO_VALUE set to 1. Remove all instances of IIO_EV_TYPE_INSTANCE and replace them with IIO_EV_TYPE_CHANGE where needed. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c index b33ce55..a4b3970 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -197,7 +197,6 @@ static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_ROC] = "roc", [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", - [IIO_EV_TYPE_INSTANCE] = "instance", [IIO_EV_TYPE_CHANGE] = "change", }; diff --git a/drivers/staging/iio/Documentation/iio_event_monitor.c b/drivers/staging/iio/Documentation/iio_event_monitor.c index 2e78d58..72c96aa 100644 --- a/drivers/staging/iio/Documentation/iio_event_monitor.c +++ b/drivers/staging/iio/Documentation/iio_event_monitor.c @@ -59,7 +59,6 @@ static const char * const iio_ev_type_text[] = { [IIO_EV_TYPE_ROC] = "roc", [IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive", - [IIO_EV_TYPE_INSTANCE] = "instance", [IIO_EV_TYPE_CHANGE] = "change", }; @@ -179,7 +178,6 @@ static bool event_is_known(struct iio_event_data *event) case IIO_EV_TYPE_ROC: case IIO_EV_TYPE_THRESH_ADAPTIVE: case IIO_EV_TYPE_MAG_ADAPTIVE: - case IIO_EV_TYPE_INSTANCE: case IIO_EV_TYPE_CHANGE: break; default: diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c index 0b8611a..e452021 100644 --- a/drivers/staging/iio/iio_simple_dummy.c +++ b/drivers/staging/iio/iio_simple_dummy.c @@ -73,7 +73,7 @@ static const struct iio_event_spec iio_dummy_event = { * simple step detect event - triggered when a step is detected */ static const struct iio_event_spec step_detect_event = { - .type = IIO_EV_TYPE_INSTANCE, + .type = IIO_EV_TYPE_CHANGE, .dir = IIO_EV_DIR_NONE, .mask_separate = BIT(IIO_EV_INFO_ENABLE), }; diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c index ac15a44..a5cd3bb 100644 --- a/drivers/staging/iio/iio_simple_dummy_events.c +++ b/drivers/staging/iio/iio_simple_dummy_events.c @@ -86,7 +86,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, } case IIO_STEPS: switch (type) { - case IIO_EV_TYPE_INSTANCE: + case IIO_EV_TYPE_CHANGE: st->event_en = state; break; default: @@ -201,7 +201,7 @@ static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private) iio_push_event(indio_dev, IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, IIO_EV_DIR_NONE, - IIO_EV_TYPE_INSTANCE, 0, 0, 0), + IIO_EV_TYPE_CHANGE, 0, 0, 0), iio_get_time_ns()); break; default: diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index 3ba3d66..580ed5b 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -78,7 +78,6 @@ enum iio_event_type { IIO_EV_TYPE_ROC, IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_TYPE_MAG_ADAPTIVE, - IIO_EV_TYPE_INSTANCE, IIO_EV_TYPE_CHANGE, }; -- cgit v0.10.2 From 6da93a6710a3b1eb3d15b88bf96efaac322c893f Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sun, 11 Jan 2015 21:10:14 +0200 Subject: iio: accel: mma9551: Add runtime pm support Add support for runtime pm to reduce the power consumed by the device when not used. If CONFIG_PM is not enabled, the device will be powered on at init and only powered off on system suspend. If CONFIG_PM is enabled, runtime pm autosuspend is used: - for raw reads will keep the device on for a specified time - for events it will keep the device on as long as we have at least one event active Signed-off-by: Irina Tirdea Reviewed-by: Vlad Dogaru Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index 6563e26..f1a5a06 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -22,6 +22,7 @@ #include #include #include +#include #define MMA9551_DRV_NAME "mma9551" #define MMA9551_IRQ_NAME "mma9551_event" @@ -71,6 +72,7 @@ enum mma9551_gpio_pin { /* Sleep/Wake application */ #define MMA9551_SLEEP_CFG 0x06 #define MMA9551_SLEEP_CFG_SNCEN BIT(0) +#define MMA9551_SLEEP_CFG_FLEEN BIT(1) #define MMA9551_SLEEP_CFG_SCHEN BIT(2) /* AFE application */ @@ -114,6 +116,9 @@ enum mma9551_tilt_axis { #define MMA9551_I2C_READ_RETRIES 5 #define MMA9551_I2C_READ_DELAY 50 /* us */ +#define MMA9551_DEFAULT_SAMPLE_RATE 122 /* Hz */ +#define MMA9551_AUTO_SUSPEND_DELAY_MS 2000 + struct mma9551_mbox_request { u8 start_mbox; /* Always 0. */ u8 app_id; @@ -387,16 +392,55 @@ static int mma9551_read_version(struct i2c_client *client) } /* + * Power on chip and enable doze mode. * Use 'false' as the second parameter to cause the device to enter * sleep. */ -static int mma9551_set_device_state(struct i2c_client *client, - bool enable) +static int mma9551_set_device_state(struct i2c_client *client, bool enable) { return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE, MMA9551_SLEEP_CFG, - MMA9551_SLEEP_CFG_SNCEN, - enable ? 0 : MMA9551_SLEEP_CFG_SNCEN); + MMA9551_SLEEP_CFG_SNCEN | + MMA9551_SLEEP_CFG_FLEEN | + MMA9551_SLEEP_CFG_SCHEN, + enable ? MMA9551_SLEEP_CFG_SCHEN | + MMA9551_SLEEP_CFG_FLEEN : + MMA9551_SLEEP_CFG_SNCEN); +} + +static int mma9551_set_power_state(struct i2c_client *client, bool on) +{ +#ifdef CONFIG_PM + int ret; + + if (on) + ret = pm_runtime_get_sync(&client->dev); + else { + pm_runtime_mark_last_busy(&client->dev); + ret = pm_runtime_put_autosuspend(&client->dev); + } + + if (ret < 0) { + dev_err(&client->dev, + "failed to change power state to %d\n", on); + if (on) + pm_runtime_put_noidle(&client->dev); + + return ret; + } +#endif + + return 0; +} + +static void mma9551_sleep(int freq) +{ + int sleep_val = 1000 / freq; + + if (sleep_val < 20) + usleep_range(sleep_val * 1000, 20000); + else + msleep_interruptible(sleep_val); } static int mma9551_read_incli_chan(struct i2c_client *client, @@ -424,15 +468,19 @@ static int mma9551_read_incli_chan(struct i2c_client *client, return -EINVAL; } + ret = mma9551_set_power_state(client, true); + if (ret < 0) + return ret; + ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, reg_addr, &angle); if (ret < 0) - return ret; + goto out_poweroff; ret = mma9551_read_status_byte(client, MMA9551_APPID_TILT, MMA9551_TILT_QUAD_REG, &quadrant); if (ret < 0) - return ret; + goto out_poweroff; angle &= ~MMA9551_TILT_ANGFLG; quadrant = (quadrant >> quad_shift) & 0x03; @@ -442,7 +490,11 @@ static int mma9551_read_incli_chan(struct i2c_client *client, else *val = angle + 90 * quadrant; - return IIO_VAL_INT; + ret = IIO_VAL_INT; + +out_poweroff: + mma9551_set_power_state(client, false); + return ret; } static int mma9551_read_accel_chan(struct i2c_client *client, @@ -467,14 +519,22 @@ static int mma9551_read_accel_chan(struct i2c_client *client, return -EINVAL; } + ret = mma9551_set_power_state(client, true); + if (ret < 0) + return ret; + ret = mma9551_read_status_word(client, MMA9551_APPID_AFE, reg_addr, &raw_accel); if (ret < 0) - return ret; + goto out_poweroff; *val = raw_accel; - return IIO_VAL_INT; + ret = IIO_VAL_INT; + +out_poweroff: + mma9551_set_power_state(client, false); + return ret; } static int mma9551_read_raw(struct iio_dev *indio_dev, @@ -556,6 +616,10 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev, MMA9551_APPID_NONE, 0, 0); if (ret < 0) return ret; + + ret = mma9551_set_power_state(data->client, false); + if (ret < 0) + return ret; } else { int bitnum; @@ -574,11 +638,18 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev, return -EINVAL; } + + ret = mma9551_set_power_state(data->client, true); + if (ret < 0) + return ret; + ret = mma9551_gpio_config(data->client, (enum mma9551_gpio_pin)mma_axis, MMA9551_APPID_TILT, bitnum, 0); - if (ret < 0) + if (ret < 0) { + mma9551_set_power_state(data->client, false); return ret; + } } data->event_enabled[mma_axis] = state; @@ -771,12 +842,7 @@ static int mma9551_init(struct mma9551_data *data) if (ret) return ret; - /* Power on chip and enable doze mode. */ - return mma9551_update_config_bits(data->client, - MMA9551_APPID_SLEEP_WAKE, - MMA9551_SLEEP_CFG, - MMA9551_SLEEP_CFG_SCHEN | MMA9551_SLEEP_CFG_SNCEN, - MMA9551_SLEEP_CFG_SCHEN); + return mma9551_set_device_state(data->client, true); } static int mma9551_gpio_probe(struct iio_dev *indio_dev) @@ -869,8 +935,19 @@ static int mma9551_probe(struct i2c_client *client, goto out_poweroff; } + ret = pm_runtime_set_active(&client->dev); + if (ret < 0) + goto out_iio_unregister; + + pm_runtime_enable(&client->dev); + pm_runtime_set_autosuspend_delay(&client->dev, + MMA9551_AUTO_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&client->dev); + return 0; +out_iio_unregister: + iio_device_unregister(indio_dev); out_poweroff: mma9551_set_device_state(client, false); @@ -882,6 +959,10 @@ static int mma9551_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); struct mma9551_data *data = iio_priv(indio_dev); + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + iio_device_unregister(indio_dev); mutex_lock(&data->mutex); mma9551_set_device_state(data->client, false); @@ -890,37 +971,72 @@ static int mma9551_remove(struct i2c_client *client) return 0; } +#ifdef CONFIG_PM +static int mma9551_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma9551_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + ret = mma9551_set_device_state(data->client, false); + mutex_unlock(&data->mutex); + if (ret < 0) { + dev_err(&data->client->dev, "powering off device failed\n"); + return -EAGAIN; + } + + return 0; +} + +static int mma9551_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma9551_data *data = iio_priv(indio_dev); + int ret; + + ret = mma9551_set_device_state(data->client, true); + if (ret < 0) + return ret; + + mma9551_sleep(MMA9551_DEFAULT_SAMPLE_RATE); + + return 0; +} +#endif + #ifdef CONFIG_PM_SLEEP static int mma9551_suspend(struct device *dev) { struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct mma9551_data *data = iio_priv(indio_dev); + int ret; mutex_lock(&data->mutex); - mma9551_set_device_state(data->client, false); + ret = mma9551_set_device_state(data->client, false); mutex_unlock(&data->mutex); - return 0; + return ret; } static int mma9551_resume(struct device *dev) { struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); struct mma9551_data *data = iio_priv(indio_dev); + int ret; mutex_lock(&data->mutex); - mma9551_set_device_state(data->client, true); + ret = mma9551_set_device_state(data->client, true); mutex_unlock(&data->mutex); - return 0; + return ret; } -#else -#define mma9551_suspend NULL -#define mma9551_resume NULL #endif static const struct dev_pm_ops mma9551_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(mma9551_suspend, mma9551_resume) + SET_RUNTIME_PM_OPS(mma9551_runtime_suspend, + mma9551_runtime_resume, NULL) }; static const struct acpi_device_id mma9551_acpi_match[] = { -- cgit v0.10.2 From d5b97f5c7dfcad98927fb4f3b2e99d4c3beeec9a Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Sun, 11 Jan 2015 21:10:15 +0200 Subject: iio: accel: mma9551: split driver to expose mma955x api Freescale has the MMA955xL family of devices that use the same communication protocol (based on i2c messages): http://www.freescale.com/files/sensors/doc/data_sheet/MMA955xL.pdf. To support more devices from this family, we need to split the mma9551 driver so we can export the common functions that will be used by other mma955x drivers. Signed-off-by: Irina Tirdea Reviewed-by: Vlad Dogaru Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 9f67c10..c53047d 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -111,9 +111,14 @@ config KXCJK1013 To compile this driver as a module, choose M here: the module will be called kxcjk-1013. +config MMA9551_CORE + tristate + config MMA9551 tristate "Freescale MMA9551L Intelligent Motion-Sensing Platform Driver" depends on I2C + select MMA9551_CORE + help Say yes here to build support for the Freescale MMA9551L Intelligent Motion-Sensing Platform Driver. diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index de5b9cb..8105316 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -9,7 +9,9 @@ obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o obj-$(CONFIG_KXSD9) += kxsd9.o obj-$(CONFIG_MMA8452) += mma8452.o -obj-$(CONFIG_MMA9551) += mma9551.o + +obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o +obj-$(CONFIG_MMA9551) += mma9551.o obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o st_accel-y := st_accel_core.o diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c index f1a5a06..46c3835 100644 --- a/drivers/iio/accel/mma9551.c +++ b/drivers/iio/accel/mma9551.c @@ -23,63 +23,13 @@ #include #include #include +#include "mma9551_core.h" #define MMA9551_DRV_NAME "mma9551" #define MMA9551_IRQ_NAME "mma9551_event" #define MMA9551_GPIO_NAME "mma9551_int" #define MMA9551_GPIO_COUNT 4 -/* Applications IDs */ -#define MMA9551_APPID_VERSION 0x00 -#define MMA9551_APPID_GPIO 0x03 -#define MMA9551_APPID_AFE 0x06 -#define MMA9551_APPID_TILT 0x0B -#define MMA9551_APPID_SLEEP_WAKE 0x12 -#define MMA9551_APPID_RESET 0x17 -#define MMA9551_APPID_NONE 0xff - -/* Command masks for mailbox write command */ -#define MMA9551_CMD_READ_VERSION_INFO 0x00 -#define MMA9551_CMD_READ_CONFIG 0x10 -#define MMA9551_CMD_WRITE_CONFIG 0x20 -#define MMA9551_CMD_READ_STATUS 0x30 - -enum mma9551_gpio_pin { - mma9551_gpio6 = 0, - mma9551_gpio7, - mma9551_gpio8, - mma9551_gpio9, - mma9551_gpio_max = mma9551_gpio9, -}; - -/* Mailbox read command */ -#define MMA9551_RESPONSE_COCO BIT(7) - -/* Error-Status codes returned in mailbox read command */ -#define MMA9551_MCI_ERROR_NONE 0x00 -#define MMA9551_MCI_ERROR_PARAM 0x04 -#define MMA9551_MCI_INVALID_COUNT 0x19 -#define MMA9551_MCI_ERROR_COMMAND 0x1C -#define MMA9551_MCI_ERROR_INVALID_LENGTH 0x21 -#define MMA9551_MCI_ERROR_FIFO_BUSY 0x22 -#define MMA9551_MCI_ERROR_FIFO_ALLOCATED 0x23 -#define MMA9551_MCI_ERROR_FIFO_OVERSIZE 0x24 - -/* GPIO Application */ -#define MMA9551_GPIO_POL_MSB 0x08 -#define MMA9551_GPIO_POL_LSB 0x09 - -/* Sleep/Wake application */ -#define MMA9551_SLEEP_CFG 0x06 -#define MMA9551_SLEEP_CFG_SNCEN BIT(0) -#define MMA9551_SLEEP_CFG_FLEEN BIT(1) -#define MMA9551_SLEEP_CFG_SCHEN BIT(2) - -/* AFE application */ -#define MMA9551_AFE_X_ACCEL_REG 0x00 -#define MMA9551_AFE_Y_ACCEL_REG 0x02 -#define MMA9551_AFE_Z_ACCEL_REG 0x04 - /* Tilt application (inclination in IIO terms). */ #define MMA9551_TILT_XZ_ANG_REG 0x00 #define MMA9551_TILT_YZ_ANG_REG 0x01 @@ -92,6 +42,8 @@ enum mma9551_gpio_pin { #define MMA9551_TILT_CFG_REG 0x01 #define MMA9551_TILT_ANG_THRESH_MASK GENMASK(3, 0) +#define MMA9551_DEFAULT_SAMPLE_RATE 122 /* Hz */ + /* Tilt events are mapped to the first three GPIO pins. */ enum mma9551_tilt_axis { mma9551_x = 0, @@ -99,64 +51,6 @@ enum mma9551_tilt_axis { mma9551_z, }; -/* - * A response is composed of: - * - control registers: MB0-3 - * - data registers: MB4-31 - * - * A request is composed of: - * - mbox to write to (always 0) - * - control registers: MB1-4 - * - data registers: MB5-31 - */ -#define MMA9551_MAILBOX_CTRL_REGS 4 -#define MMA9551_MAX_MAILBOX_DATA_REGS 28 -#define MMA9551_MAILBOX_REGS 32 - -#define MMA9551_I2C_READ_RETRIES 5 -#define MMA9551_I2C_READ_DELAY 50 /* us */ - -#define MMA9551_DEFAULT_SAMPLE_RATE 122 /* Hz */ -#define MMA9551_AUTO_SUSPEND_DELAY_MS 2000 - -struct mma9551_mbox_request { - u8 start_mbox; /* Always 0. */ - u8 app_id; - /* - * See Section 5.3.1 of the MMA955xL Software Reference Manual. - * - * Bit 7: reserved, always 0 - * Bits 6-4: command - * Bits 3-0: upper bits of register offset - */ - u8 cmd_off; - u8 lower_off; - u8 nbytes; - u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS - 1]; -} __packed; - -struct mma9551_mbox_response { - u8 app_id; - /* - * See Section 5.3.3 of the MMA955xL Software Reference Manual. - * - * Bit 7: COCO - * Bits 6-0: Error code. - */ - u8 coco_err; - u8 nbytes; - u8 req_bytes; - u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS]; -} __packed; - -struct mma9551_version_info { - __be32 device_id; - u8 rom_version[2]; - u8 fw_version[2]; - u8 hw_version[2]; - u8 fw_build[2]; -}; - struct mma9551_data { struct i2c_client *client; struct mutex mutex; @@ -164,285 +58,6 @@ struct mma9551_data { int irqs[MMA9551_GPIO_COUNT]; }; -static int mma9551_transfer(struct i2c_client *client, - u8 app_id, u8 command, u16 offset, - u8 *inbytes, int num_inbytes, - u8 *outbytes, int num_outbytes) -{ - struct mma9551_mbox_request req; - struct mma9551_mbox_response rsp; - struct i2c_msg in, out; - u8 req_len, err_code; - int ret, retries; - - if (offset >= 1 << 12) { - dev_err(&client->dev, "register offset too large\n"); - return -EINVAL; - } - - req_len = 1 + MMA9551_MAILBOX_CTRL_REGS + num_inbytes; - req.start_mbox = 0; - req.app_id = app_id; - req.cmd_off = command | (offset >> 8); - req.lower_off = offset; - - if (command == MMA9551_CMD_WRITE_CONFIG) - req.nbytes = num_inbytes; - else - req.nbytes = num_outbytes; - if (num_inbytes) - memcpy(req.buf, inbytes, num_inbytes); - - out.addr = client->addr; - out.flags = 0; - out.len = req_len; - out.buf = (u8 *)&req; - - ret = i2c_transfer(client->adapter, &out, 1); - if (ret < 0) { - dev_err(&client->dev, "i2c write failed\n"); - return ret; - } - - retries = MMA9551_I2C_READ_RETRIES; - do { - udelay(MMA9551_I2C_READ_DELAY); - - in.addr = client->addr; - in.flags = I2C_M_RD; - in.len = sizeof(rsp); - in.buf = (u8 *)&rsp; - - ret = i2c_transfer(client->adapter, &in, 1); - if (ret < 0) { - dev_err(&client->dev, "i2c read failed\n"); - return ret; - } - - if (rsp.coco_err & MMA9551_RESPONSE_COCO) - break; - } while (--retries > 0); - - if (retries == 0) { - dev_err(&client->dev, - "timed out while waiting for command response\n"); - return -ETIMEDOUT; - } - - if (rsp.app_id != app_id) { - dev_err(&client->dev, - "app_id mismatch in response got %02x expected %02x\n", - rsp.app_id, app_id); - return -EINVAL; - } - - err_code = rsp.coco_err & ~MMA9551_RESPONSE_COCO; - if (err_code != MMA9551_MCI_ERROR_NONE) { - dev_err(&client->dev, "read returned error %x\n", err_code); - return -EINVAL; - } - - if (rsp.nbytes != rsp.req_bytes) { - dev_err(&client->dev, - "output length mismatch got %d expected %d\n", - rsp.nbytes, rsp.req_bytes); - return -EINVAL; - } - - if (num_outbytes) - memcpy(outbytes, rsp.buf, num_outbytes); - - return 0; -} - -static int mma9551_read_config_byte(struct i2c_client *client, u8 app_id, - u16 reg, u8 *val) -{ - return mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, - reg, NULL, 0, val, 1); -} - -static int mma9551_write_config_byte(struct i2c_client *client, u8 app_id, - u16 reg, u8 val) -{ - return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg, - &val, 1, NULL, 0); -} - -static int mma9551_read_status_byte(struct i2c_client *client, u8 app_id, - u16 reg, u8 *val) -{ - return mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, - reg, NULL, 0, val, 1); -} - -static int mma9551_read_status_word(struct i2c_client *client, u8 app_id, - u16 reg, u16 *val) -{ - int ret; - __be16 v; - - ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, - reg, NULL, 0, (u8 *)&v, 2); - *val = be16_to_cpu(v); - - return ret; -} - -static int mma9551_update_config_bits(struct i2c_client *client, u8 app_id, - u16 reg, u8 mask, u8 val) -{ - int ret; - u8 tmp, orig; - - ret = mma9551_read_config_byte(client, app_id, reg, &orig); - if (ret < 0) - return ret; - - tmp = orig & ~mask; - tmp |= val & mask; - - if (tmp == orig) - return 0; - - return mma9551_write_config_byte(client, app_id, reg, tmp); -} - -/* - * The polarity parameter is described in section 6.2.2, page 66, of the - * Software Reference Manual. Basically, polarity=0 means the interrupt - * line has the same value as the selected bit, while polarity=1 means - * the line is inverted. - */ -static int mma9551_gpio_config(struct i2c_client *client, - enum mma9551_gpio_pin pin, - u8 app_id, u8 bitnum, int polarity) -{ - u8 reg, pol_mask, pol_val; - int ret; - - if (pin > mma9551_gpio_max) { - dev_err(&client->dev, "bad GPIO pin\n"); - return -EINVAL; - } - - /* - * Pin 6 is configured by regs 0x00 and 0x01, pin 7 by 0x02 and - * 0x03, and so on. - */ - reg = pin * 2; - - ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, - reg, app_id); - if (ret < 0) { - dev_err(&client->dev, "error setting GPIO app_id\n"); - return ret; - } - - ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, - reg + 1, bitnum); - if (ret < 0) { - dev_err(&client->dev, "error setting GPIO bit number\n"); - return ret; - } - - switch (pin) { - case mma9551_gpio6: - reg = MMA9551_GPIO_POL_LSB; - pol_mask = 1 << 6; - break; - case mma9551_gpio7: - reg = MMA9551_GPIO_POL_LSB; - pol_mask = 1 << 7; - break; - case mma9551_gpio8: - reg = MMA9551_GPIO_POL_MSB; - pol_mask = 1 << 0; - break; - case mma9551_gpio9: - reg = MMA9551_GPIO_POL_MSB; - pol_mask = 1 << 1; - break; - } - pol_val = polarity ? pol_mask : 0; - - ret = mma9551_update_config_bits(client, MMA9551_APPID_GPIO, reg, - pol_mask, pol_val); - if (ret < 0) - dev_err(&client->dev, "error setting GPIO polarity\n"); - - return ret; -} - -static int mma9551_read_version(struct i2c_client *client) -{ - struct mma9551_version_info info; - int ret; - - ret = mma9551_transfer(client, MMA9551_APPID_VERSION, 0x00, 0x00, - NULL, 0, (u8 *)&info, sizeof(info)); - if (ret < 0) - return ret; - - dev_info(&client->dev, "Device ID 0x%x, firmware version %02x.%02x\n", - be32_to_cpu(info.device_id), info.fw_version[0], - info.fw_version[1]); - - return 0; -} - -/* - * Power on chip and enable doze mode. - * Use 'false' as the second parameter to cause the device to enter - * sleep. - */ -static int mma9551_set_device_state(struct i2c_client *client, bool enable) -{ - return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE, - MMA9551_SLEEP_CFG, - MMA9551_SLEEP_CFG_SNCEN | - MMA9551_SLEEP_CFG_FLEEN | - MMA9551_SLEEP_CFG_SCHEN, - enable ? MMA9551_SLEEP_CFG_SCHEN | - MMA9551_SLEEP_CFG_FLEEN : - MMA9551_SLEEP_CFG_SNCEN); -} - -static int mma9551_set_power_state(struct i2c_client *client, bool on) -{ -#ifdef CONFIG_PM - int ret; - - if (on) - ret = pm_runtime_get_sync(&client->dev); - else { - pm_runtime_mark_last_busy(&client->dev); - ret = pm_runtime_put_autosuspend(&client->dev); - } - - if (ret < 0) { - dev_err(&client->dev, - "failed to change power state to %d\n", on); - if (on) - pm_runtime_put_noidle(&client->dev); - - return ret; - } -#endif - - return 0; -} - -static void mma9551_sleep(int freq) -{ - int sleep_val = 1000 / freq; - - if (sleep_val < 20) - usleep_range(sleep_val * 1000, 20000); - else - msleep_interruptible(sleep_val); -} - static int mma9551_read_incli_chan(struct i2c_client *client, const struct iio_chan_spec *chan, int *val) @@ -497,46 +112,6 @@ out_poweroff: return ret; } -static int mma9551_read_accel_chan(struct i2c_client *client, - const struct iio_chan_spec *chan, - int *val, int *val2) -{ - u16 reg_addr; - s16 raw_accel; - int ret; - - switch (chan->channel2) { - case IIO_MOD_X: - reg_addr = MMA9551_AFE_X_ACCEL_REG; - break; - case IIO_MOD_Y: - reg_addr = MMA9551_AFE_Y_ACCEL_REG; - break; - case IIO_MOD_Z: - reg_addr = MMA9551_AFE_Z_ACCEL_REG; - break; - default: - return -EINVAL; - } - - ret = mma9551_set_power_state(client, true); - if (ret < 0) - return ret; - - ret = mma9551_read_status_word(client, MMA9551_APPID_AFE, - reg_addr, &raw_accel); - if (ret < 0) - goto out_poweroff; - - *val = raw_accel; - - ret = IIO_VAL_INT; - -out_poweroff: - mma9551_set_power_state(client, false); - return ret; -} - static int mma9551_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -569,9 +144,7 @@ static int mma9551_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_ACCEL: - *val = 0; - *val2 = 2440; - return IIO_VAL_INT_PLUS_MICRO; + return mma9551_read_accel_scale(val, val2); default: return -EINVAL; } @@ -740,14 +313,6 @@ static const struct iio_event_spec mma9551_incli_event = { .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), }; -#define MMA9551_ACCEL_CHANNEL(axis) { \ - .type = IIO_ACCEL, \ - .modified = 1, \ - .channel2 = axis, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ -} - #define MMA9551_INCLI_CHANNEL(axis) { \ .type = IIO_INCLI, \ .modified = 1, \ diff --git a/drivers/iio/accel/mma9551_core.c b/drivers/iio/accel/mma9551_core.c new file mode 100644 index 0000000..7f1a73e --- /dev/null +++ b/drivers/iio/accel/mma9551_core.c @@ -0,0 +1,615 @@ +/* + * Common code for Freescale MMA955x Intelligent Sensor Platform drivers + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include "mma9551_core.h" + +/* Command masks for mailbox write command */ +#define MMA9551_CMD_READ_VERSION_INFO 0x00 +#define MMA9551_CMD_READ_CONFIG 0x10 +#define MMA9551_CMD_WRITE_CONFIG 0x20 +#define MMA9551_CMD_READ_STATUS 0x30 + +/* Mailbox read command */ +#define MMA9551_RESPONSE_COCO BIT(7) + +/* Error-Status codes returned in mailbox read command */ +#define MMA9551_MCI_ERROR_NONE 0x00 +#define MMA9551_MCI_ERROR_PARAM 0x04 +#define MMA9551_MCI_INVALID_COUNT 0x19 +#define MMA9551_MCI_ERROR_COMMAND 0x1C +#define MMA9551_MCI_ERROR_INVALID_LENGTH 0x21 +#define MMA9551_MCI_ERROR_FIFO_BUSY 0x22 +#define MMA9551_MCI_ERROR_FIFO_ALLOCATED 0x23 +#define MMA9551_MCI_ERROR_FIFO_OVERSIZE 0x24 + +/* GPIO Application */ +#define MMA9551_GPIO_POL_MSB 0x08 +#define MMA9551_GPIO_POL_LSB 0x09 + +/* Sleep/Wake application */ +#define MMA9551_SLEEP_CFG 0x06 +#define MMA9551_SLEEP_CFG_SNCEN BIT(0) +#define MMA9551_SLEEP_CFG_FLEEN BIT(1) +#define MMA9551_SLEEP_CFG_SCHEN BIT(2) + +/* AFE application */ +#define MMA9551_AFE_X_ACCEL_REG 0x00 +#define MMA9551_AFE_Y_ACCEL_REG 0x02 +#define MMA9551_AFE_Z_ACCEL_REG 0x04 + +/* + * A response is composed of: + * - control registers: MB0-3 + * - data registers: MB4-31 + * + * A request is composed of: + * - mbox to write to (always 0) + * - control registers: MB1-4 + * - data registers: MB5-31 + */ +#define MMA9551_MAILBOX_CTRL_REGS 4 +#define MMA9551_MAX_MAILBOX_DATA_REGS 28 +#define MMA9551_MAILBOX_REGS 32 + +#define MMA9551_I2C_READ_RETRIES 5 +#define MMA9551_I2C_READ_DELAY 50 /* us */ + +struct mma9551_mbox_request { + u8 start_mbox; /* Always 0. */ + u8 app_id; + /* + * See Section 5.3.1 of the MMA955xL Software Reference Manual. + * + * Bit 7: reserved, always 0 + * Bits 6-4: command + * Bits 3-0: upper bits of register offset + */ + u8 cmd_off; + u8 lower_off; + u8 nbytes; + u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS - 1]; +} __packed; + +struct mma9551_mbox_response { + u8 app_id; + /* + * See Section 5.3.3 of the MMA955xL Software Reference Manual. + * + * Bit 7: COCO + * Bits 6-0: Error code. + */ + u8 coco_err; + u8 nbytes; + u8 req_bytes; + u8 buf[MMA9551_MAX_MAILBOX_DATA_REGS]; +} __packed; + +struct mma9551_version_info { + __be32 device_id; + u8 rom_version[2]; + u8 fw_version[2]; + u8 hw_version[2]; + u8 fw_build[2]; +}; + +static int mma9551_transfer(struct i2c_client *client, + u8 app_id, u8 command, u16 offset, + u8 *inbytes, int num_inbytes, + u8 *outbytes, int num_outbytes) +{ + struct mma9551_mbox_request req; + struct mma9551_mbox_response rsp; + struct i2c_msg in, out; + u8 req_len, err_code; + int ret, retries; + + if (offset >= 1 << 12) { + dev_err(&client->dev, "register offset too large\n"); + return -EINVAL; + } + + req_len = 1 + MMA9551_MAILBOX_CTRL_REGS + num_inbytes; + req.start_mbox = 0; + req.app_id = app_id; + req.cmd_off = command | (offset >> 8); + req.lower_off = offset; + + if (command == MMA9551_CMD_WRITE_CONFIG) + req.nbytes = num_inbytes; + else + req.nbytes = num_outbytes; + if (num_inbytes) + memcpy(req.buf, inbytes, num_inbytes); + + out.addr = client->addr; + out.flags = 0; + out.len = req_len; + out.buf = (u8 *)&req; + + ret = i2c_transfer(client->adapter, &out, 1); + if (ret < 0) { + dev_err(&client->dev, "i2c write failed\n"); + return ret; + } + + retries = MMA9551_I2C_READ_RETRIES; + do { + udelay(MMA9551_I2C_READ_DELAY); + + in.addr = client->addr; + in.flags = I2C_M_RD; + in.len = sizeof(rsp); + in.buf = (u8 *)&rsp; + + ret = i2c_transfer(client->adapter, &in, 1); + if (ret < 0) { + dev_err(&client->dev, "i2c read failed\n"); + return ret; + } + + if (rsp.coco_err & MMA9551_RESPONSE_COCO) + break; + } while (--retries > 0); + + if (retries == 0) { + dev_err(&client->dev, + "timed out while waiting for command response\n"); + return -ETIMEDOUT; + } + + if (rsp.app_id != app_id) { + dev_err(&client->dev, + "app_id mismatch in response got %02x expected %02x\n", + rsp.app_id, app_id); + return -EINVAL; + } + + err_code = rsp.coco_err & ~MMA9551_RESPONSE_COCO; + if (err_code != MMA9551_MCI_ERROR_NONE) { + dev_err(&client->dev, "read returned error %x\n", err_code); + return -EINVAL; + } + + if (rsp.nbytes != rsp.req_bytes) { + dev_err(&client->dev, + "output length mismatch got %d expected %d\n", + rsp.nbytes, rsp.req_bytes); + return -EINVAL; + } + + if (num_outbytes) + memcpy(outbytes, rsp.buf, num_outbytes); + + return 0; +} + +/** + * mma9551_read_config_byte() - read 1 configuration byte + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @val: Pointer to store value read + * + * Read one configuration byte from the device using MMA955xL command format. + * Commands to the MMA955xL platform consist of a write followed + * by one or more reads. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_read_config_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 *val) +{ + return mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, + reg, NULL, 0, val, 1); +} +EXPORT_SYMBOL(mma9551_read_config_byte); + +/** + * mma9551_write_config_byte() - write 1 configuration byte + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @val: Value to write + * + * Write one configuration byte from the device using MMA955xL command format. + * Commands to the MMA955xL platform consist of a write followed by one or + * more reads. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_write_config_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 val) +{ + return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg, + &val, 1, NULL, 0); +} +EXPORT_SYMBOL(mma9551_write_config_byte); + +/** + * mma9551_read_status_byte() - read 1 status byte + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @val: Pointer to store value read + * + * Read one status byte from the device using MMA955xL command format. + * Commands to the MMA955xL platform consist of a write followed by one or + * more reads. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_read_status_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 *val) +{ + return mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, + reg, NULL, 0, val, 1); +} +EXPORT_SYMBOL(mma9551_read_status_byte); + +/** + * mma9551_read_status_word() - read 1 status word + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @val: Pointer to store value read + * + * Read one status word from the device using MMA955xL command format. + * Commands to the MMA955xL platform consist of a write followed by one or + * more reads. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_read_status_word(struct i2c_client *client, u8 app_id, + u16 reg, u16 *val) +{ + int ret; + __be16 v; + + ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, + reg, NULL, 0, (u8 *)&v, 2); + *val = be16_to_cpu(v); + + return ret; +} +EXPORT_SYMBOL(mma9551_read_status_word); + +/** + * mma9551_update_config_bits() - update bits in register + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @mask: Mask for the bits to update + * @val: Value of the bits to update + * + * Update bits in the given register using a bit mask. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_update_config_bits(struct i2c_client *client, u8 app_id, + u16 reg, u8 mask, u8 val) +{ + int ret; + u8 tmp, orig; + + ret = mma9551_read_config_byte(client, app_id, reg, &orig); + if (ret < 0) + return ret; + + tmp = orig & ~mask; + tmp |= val & mask; + + if (tmp == orig) + return 0; + + return mma9551_write_config_byte(client, app_id, reg, tmp); +} +EXPORT_SYMBOL(mma9551_update_config_bits); + +/** + * mma9551_gpio_config() - configure gpio + * @client: I2C client + * @pin: GPIO pin to configure + * @app_id: Application ID + * @bitnum: Bit number of status register being assigned to the GPIO pin. + * @polarity: The polarity parameter is described in section 6.2.2, page 66, + * of the Software Reference Manual. Basically, polarity=0 means + * the interrupt line has the same value as the selected bit, + * while polarity=1 means the line is inverted. + * + * Assign a bit from an application’s status register to a specific GPIO pin. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_gpio_config(struct i2c_client *client, enum mma9551_gpio_pin pin, + u8 app_id, u8 bitnum, int polarity) +{ + u8 reg, pol_mask, pol_val; + int ret; + + if (pin > mma9551_gpio_max) { + dev_err(&client->dev, "bad GPIO pin\n"); + return -EINVAL; + } + + /* + * Pin 6 is configured by regs 0x00 and 0x01, pin 7 by 0x02 and + * 0x03, and so on. + */ + reg = pin * 2; + + ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, + reg, app_id); + if (ret < 0) { + dev_err(&client->dev, "error setting GPIO app_id\n"); + return ret; + } + + ret = mma9551_write_config_byte(client, MMA9551_APPID_GPIO, + reg + 1, bitnum); + if (ret < 0) { + dev_err(&client->dev, "error setting GPIO bit number\n"); + return ret; + } + + switch (pin) { + case mma9551_gpio6: + reg = MMA9551_GPIO_POL_LSB; + pol_mask = 1 << 6; + break; + case mma9551_gpio7: + reg = MMA9551_GPIO_POL_LSB; + pol_mask = 1 << 7; + break; + case mma9551_gpio8: + reg = MMA9551_GPIO_POL_MSB; + pol_mask = 1 << 0; + break; + case mma9551_gpio9: + reg = MMA9551_GPIO_POL_MSB; + pol_mask = 1 << 1; + break; + } + pol_val = polarity ? pol_mask : 0; + + ret = mma9551_update_config_bits(client, MMA9551_APPID_GPIO, reg, + pol_mask, pol_val); + if (ret < 0) + dev_err(&client->dev, "error setting GPIO polarity\n"); + + return ret; +} +EXPORT_SYMBOL(mma9551_gpio_config); + +/** + * mma9551_read_version() - read device version information + * @client: I2C client + * + * Read version information and print device id and firmware version. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_read_version(struct i2c_client *client) +{ + struct mma9551_version_info info; + int ret; + + ret = mma9551_transfer(client, MMA9551_APPID_VERSION, 0x00, 0x00, + NULL, 0, (u8 *)&info, sizeof(info)); + if (ret < 0) + return ret; + + dev_info(&client->dev, "device ID 0x%x, firmware version %02x.%02x\n", + be32_to_cpu(info.device_id), info.fw_version[0], + info.fw_version[1]); + + return 0; +} +EXPORT_SYMBOL(mma9551_read_version); + +/** + * mma9551_set_device_state() - sets HW power mode + * @client: I2C client + * @enable: Use true to power on device, false to cause the device + * to enter sleep. + * + * Set power on/off for device using the Sleep/Wake Application. + * When enable is true, power on chip and enable doze mode. + * When enable is false, enter sleep mode (device remains in the + * lowest-power mode). + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_set_device_state(struct i2c_client *client, bool enable) +{ + return mma9551_update_config_bits(client, MMA9551_APPID_SLEEP_WAKE, + MMA9551_SLEEP_CFG, + MMA9551_SLEEP_CFG_SNCEN | + MMA9551_SLEEP_CFG_FLEEN | + MMA9551_SLEEP_CFG_SCHEN, + enable ? MMA9551_SLEEP_CFG_SCHEN | + MMA9551_SLEEP_CFG_FLEEN : + MMA9551_SLEEP_CFG_SNCEN); +} +EXPORT_SYMBOL(mma9551_set_device_state); + +/** + * mma9551_set_power_state() - sets runtime PM state + * @client: I2C client + * @on: Use true to power on device, false to power off + * + * Resume or suspend the device using Runtime PM. + * The device will suspend after the autosuspend delay. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_set_power_state(struct i2c_client *client, bool on) +{ +#ifdef CONFIG_PM + int ret; + + if (on) + ret = pm_runtime_get_sync(&client->dev); + else { + pm_runtime_mark_last_busy(&client->dev); + ret = pm_runtime_put_autosuspend(&client->dev); + } + + if (ret < 0) { + dev_err(&client->dev, + "failed to change power state to %d\n", on); + if (on) + pm_runtime_put_noidle(&client->dev); + + return ret; + } +#endif + + return 0; +} +EXPORT_SYMBOL(mma9551_set_power_state); + +/** + * mma9551_sleep() - sleep + * @freq: Application frequency + * + * Firmware applications run at a certain frequency on the + * device. Sleep for one application cycle to make sure the + * application had time to run once and initialize set values. + */ +void mma9551_sleep(int freq) +{ + int sleep_val = 1000 / freq; + + if (sleep_val < 20) + usleep_range(sleep_val * 1000, 20000); + else + msleep_interruptible(sleep_val); +} +EXPORT_SYMBOL(mma9551_sleep); + +/** + * mma9551_read_accel_chan() - read accelerometer channel + * @client: I2C client + * @chan: IIO channel + * @val: Pointer to the accelerometer value read + * @val2: Unused + * + * Read accelerometer value for the specified channel. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: IIO_VAL_INT on success, negative value on failure. + */ +int mma9551_read_accel_chan(struct i2c_client *client, + const struct iio_chan_spec *chan, + int *val, int *val2) +{ + u16 reg_addr; + s16 raw_accel; + int ret; + + switch (chan->channel2) { + case IIO_MOD_X: + reg_addr = MMA9551_AFE_X_ACCEL_REG; + break; + case IIO_MOD_Y: + reg_addr = MMA9551_AFE_Y_ACCEL_REG; + break; + case IIO_MOD_Z: + reg_addr = MMA9551_AFE_Z_ACCEL_REG; + break; + default: + return -EINVAL; + } + + ret = mma9551_set_power_state(client, true); + if (ret < 0) + return ret; + + ret = mma9551_read_status_word(client, MMA9551_APPID_AFE, + reg_addr, &raw_accel); + if (ret < 0) + goto out_poweroff; + + *val = raw_accel; + + ret = IIO_VAL_INT; + +out_poweroff: + mma9551_set_power_state(client, false); + return ret; +} +EXPORT_SYMBOL(mma9551_read_accel_chan); + +/** + * mma9551_read_accel_scale() - read accelerometer scale + * @val: Pointer to the accelerometer scale (int value) + * @val2: Pointer to the accelerometer scale (micro value) + * + * Read accelerometer scale. + * + * Returns: IIO_VAL_INT_PLUS_MICRO. + */ +int mma9551_read_accel_scale(int *val, int *val2) +{ + *val = 0; + *val2 = 2440; + + return IIO_VAL_INT_PLUS_MICRO; +} +EXPORT_SYMBOL(mma9551_read_accel_scale); + +MODULE_AUTHOR("Irina Tirdea "); +MODULE_AUTHOR("Vlad Dogaru "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MMA955xL sensors core"); diff --git a/drivers/iio/accel/mma9551_core.h b/drivers/iio/accel/mma9551_core.h new file mode 100644 index 0000000..e6efd027 --- /dev/null +++ b/drivers/iio/accel/mma9551_core.h @@ -0,0 +1,66 @@ +/* + * Common code for Freescale MMA955x Intelligent Sensor Platform drivers + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _MMA9551_CORE_H_ +#define _MMA9551_CORE_H_ + +/* Applications IDs */ +#define MMA9551_APPID_VERSION 0x00 +#define MMA9551_APPID_GPIO 0x03 +#define MMA9551_APPID_AFE 0x06 +#define MMA9551_APPID_TILT 0x0B +#define MMA9551_APPID_SLEEP_WAKE 0x12 +#define MMA9551_APPID_RESET 0x17 +#define MMA9551_APPID_NONE 0xff + +#define MMA9551_AUTO_SUSPEND_DELAY_MS 2000 + +enum mma9551_gpio_pin { + mma9551_gpio6 = 0, + mma9551_gpio7, + mma9551_gpio8, + mma9551_gpio9, + mma9551_gpio_max = mma9551_gpio9, +}; + +#define MMA9551_ACCEL_CHANNEL(axis) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +int mma9551_read_config_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 *val); +int mma9551_write_config_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 val); +int mma9551_read_status_byte(struct i2c_client *client, u8 app_id, + u16 reg, u8 *val); +int mma9551_read_status_word(struct i2c_client *client, u8 app_id, + u16 reg, u16 *val); +int mma9551_update_config_bits(struct i2c_client *client, u8 app_id, + u16 reg, u8 mask, u8 val); +int mma9551_gpio_config(struct i2c_client *client, enum mma9551_gpio_pin pin, + u8 app_id, u8 bitnum, int polarity); +int mma9551_read_version(struct i2c_client *client); +int mma9551_set_device_state(struct i2c_client *client, bool enable); +int mma9551_set_power_state(struct i2c_client *client, bool on); +void mma9551_sleep(int freq); +int mma9551_read_accel_chan(struct i2c_client *client, + const struct iio_chan_spec *chan, + int *val, int *val2); +int mma9551_read_accel_scale(int *val, int *val2); + +#endif /* _MMA9551_CORE_H_ */ -- cgit v0.10.2 From b3e9ad703bef139fbcbb6423f4bafe3f89c97b00 Mon Sep 17 00:00:00 2001 From: Varka Bhadram Date: Thu, 22 Jan 2015 09:08:02 +0530 Subject: imu: inv_mpu6050: use devm_iio_trigger_alloc Signed-off-by: Varka Bhadram Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index 926fcce..c827d21 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -116,9 +116,10 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) int ret; struct inv_mpu6050_state *st = iio_priv(indio_dev); - st->trig = iio_trigger_alloc("%s-dev%d", - indio_dev->name, - indio_dev->id); + st->trig = devm_iio_trigger_alloc(&indio_dev->dev, + "%s-dev%d", + indio_dev->name, + indio_dev->id); if (st->trig == NULL) { ret = -ENOMEM; goto error_ret; @@ -128,7 +129,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) "inv_mpu", st->trig); if (ret) - goto error_free_trig; + goto error_ret; st->trig->dev.parent = &st->client->dev; st->trig->ops = &inv_mpu_trigger_ops; iio_trigger_set_drvdata(st->trig, indio_dev); @@ -141,8 +142,6 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) error_free_irq: free_irq(st->client->irq, st->trig); -error_free_trig: - iio_trigger_free(st->trig); error_ret: return ret; } @@ -151,5 +150,4 @@ void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st) { iio_trigger_unregister(st->trig); free_irq(st->client->irq, st->trig); - iio_trigger_free(st->trig); } -- cgit v0.10.2 From eec06b8c532588fb114fcbd9724f3c9fbdfe10c9 Mon Sep 17 00:00:00 2001 From: Varka Bhadram Date: Thu, 22 Jan 2015 09:08:03 +0530 Subject: imu: inv_mpu6050: use devm_request_irq This patch use the devres API for requesting an IRQ. Signed-off-by: Varka Bhadram Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index c827d21..ab8c85a 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -124,10 +124,11 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_ret; } - ret = request_irq(st->client->irq, &iio_trigger_generic_data_rdy_poll, - IRQF_TRIGGER_RISING, - "inv_mpu", - st->trig); + ret = devm_request_irq(&indio_dev->dev, st->client->irq, + &iio_trigger_generic_data_rdy_poll, + IRQF_TRIGGER_RISING, + "inv_mpu", + st->trig); if (ret) goto error_ret; st->trig->dev.parent = &st->client->dev; @@ -135,13 +136,11 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) iio_trigger_set_drvdata(st->trig, indio_dev); ret = iio_trigger_register(st->trig); if (ret) - goto error_free_irq; + goto error_ret; indio_dev->trig = iio_trigger_get(st->trig); return 0; -error_free_irq: - free_irq(st->client->irq, st->trig); error_ret: return ret; } @@ -149,5 +148,4 @@ error_ret: void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st) { iio_trigger_unregister(st->trig); - free_irq(st->client->irq, st->trig); } -- cgit v0.10.2 From 76cd2e71780b5b5dfd6d0cffef8301b664d4fcf0 Mon Sep 17 00:00:00 2001 From: Varka Bhadram Date: Thu, 22 Jan 2015 09:08:04 +0530 Subject: imu: inv_mpu6050: cleanup on error check Signed-off-by: Varka Bhadram Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index ab8c85a..844610c 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -120,29 +120,28 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) "%s-dev%d", indio_dev->name, indio_dev->id); - if (st->trig == NULL) { - ret = -ENOMEM; - goto error_ret; - } + if (!st->trig) + return -ENOMEM; + ret = devm_request_irq(&indio_dev->dev, st->client->irq, &iio_trigger_generic_data_rdy_poll, IRQF_TRIGGER_RISING, "inv_mpu", st->trig); if (ret) - goto error_ret; + return ret; + st->trig->dev.parent = &st->client->dev; st->trig->ops = &inv_mpu_trigger_ops; iio_trigger_set_drvdata(st->trig, indio_dev); + ret = iio_trigger_register(st->trig); if (ret) - goto error_ret; + return ret; + indio_dev->trig = iio_trigger_get(st->trig); return 0; - -error_ret: - return ret; } void inv_mpu6050_remove_trigger(struct inv_mpu6050_state *st) -- cgit v0.10.2 From 2d8339d0ec7986d4654003f4da88e17ea14c1779 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 9 Jan 2015 15:30:38 -0800 Subject: iio: magnetometer: ak8975: Add AK8963 Added AK8963 in the id table. Unfortunately some commercial devices using caps version ak8963. Signed-off-by: Srinivas Pandruvada Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index 0d10a4b..b13936d 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -813,6 +813,7 @@ static int ak8975_probe(struct i2c_client *client, static const struct i2c_device_id ak8975_id[] = { {"ak8975", AK8975}, {"ak8963", AK8963}, + {"AK8963", AK8963}, {"ak09911", AK09911}, {"ak09912", AK09912}, {} -- cgit v0.10.2 From d3ba5586facfc038110333b5ce17f8bfccbcaddf Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Tue, 20 Jan 2015 12:15:21 +0200 Subject: DT: iio: vadc: document dt binding Document DT binding for Qualcomm SPMI PMIC voltage ADC driver. Signed-off-by: Stanimir Varbanov Signed-off-by: Ivan T. Ivanov Signed-off-by: Jonathan Cameron diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.txt b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.txt new file mode 100644 index 0000000..0fb4613 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.txt @@ -0,0 +1,129 @@ +Qualcomm's SPMI PMIC voltage ADC + +SPMI PMIC voltage ADC (VADC) provides interface to clients to read +voltage. The VADC is a 15-bit sigma-delta ADC. + +VADC node: + +- compatible: + Usage: required + Value type: + Definition: Should contain "qcom,spmi-vadc". + +- reg: + Usage: required + Value type: + Definition: VADC base address and length in the SPMI PMIC register map. + +- #address-cells: + Usage: required + Value type: + Definition: Must be one. Child node 'reg' property should define ADC + channel number. + +- #size-cells: + Usage: required + Value type: + Definition: Must be zero. + +- #io-channel-cells: + Usage: required + Value type: + Definition: Must be one. For details about IIO bindings see: + Documentation/devicetree/bindings/iio/iio-bindings.txt + +- interrupts: + Usage: optional + Value type: + Definition: End of conversion interrupt. + +Channel node properties: + +- reg: + Usage: required + Value type: + Definition: ADC channel number. + See include/dt-bindings/iio/qcom,spmi-vadc.h + +- qcom,decimation: + Usage: optional + Value type: + Definition: This parameter is used to decrease ADC sampling rate. + Quicker measurements can be made by reducing decimation ratio. + Valid values are 512, 1024, 2048, 4096. + If property is not found, default value of 512 will be used. + +- qcom,pre-scaling: + Usage: optional + Value type: + Definition: Used for scaling the channel input signal before the signal is + fed to VADC. The configuration for this node is to know the + pre-determined ratio and use it for post scaling. Select one from + the following options. + <1 1>, <1 3>, <1 4>, <1 6>, <1 20>, <1 8>, <10 81>, <1 10> + If property is not found default value depending on chip will be used. + +- qcom,ratiometric: + Usage: optional + Value type: + Definition: Channel calibration type. If this property is specified + VADC will use the VDD reference (1.8V) and GND for channel + calibration. If property is not found, channel will be + calibrated with 0.625V and 1.25V reference channels, also + known as absolute calibration. + +- qcom,hw-settle-time: + Usage: optional + Value type: + Definition: Time between AMUX getting configured and the ADC starting + conversion. Delay = 100us * (value) for value < 11, and + 2ms * (value - 10) otherwise. + Valid values are: 0, 100, 200, 300, 400, 500, 600, 700, 800, + 900 us and 1, 2, 4, 6, 8, 10 ms + If property is not found, channel will use 0us. + +- qcom,avg-samples: + Usage: optional + Value type: + Definition: Number of samples to be used for measurement. + Averaging provides the option to obtain a single measurement + from the ADC that is an average of multiple samples. The value + selected is 2^(value). + Valid values are: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 + If property is not found, 1 sample will be used. + +NOTE: + +Following channels, also known as reference point channels, are used for +result calibration and their channel configuration nodes should be defined: +VADC_REF_625MV and/or VADC_SPARE1(based on PMIC version) VADC_REF_1250MV, +VADC_GND_REF and VADC_VDD_VADC. + +Example: + + /* VADC node */ + pmic_vadc: vadc@3100 { + compatible = "qcom,spmi-vadc"; + reg = <0x3100 0x100>; + interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>; + #address-cells = <1>; + #size-cells = <0>; + #io-channel-cells = <1>; + io-channel-ranges; + + /* Channel node */ + usb_id_nopull { + reg = ; + qcom,decimation = <512>; + qcom,ratiometric; + qcom,hw-settle-time = <200>; + qcom,avg-samples = <1>; + qcom,pre-scaling = <1 3>; + }; + }; + + /* IIO client node */ + usb { + io-channels = <&pmic_vadc VADC_LR_MUX10_USB_ID>; + io-channel-names = "vadc"; + }; diff --git a/include/dt-bindings/iio/qcom,spmi-vadc.h b/include/dt-bindings/iio/qcom,spmi-vadc.h new file mode 100644 index 0000000..42121fa --- /dev/null +++ b/include/dt-bindings/iio/qcom,spmi-vadc.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_QCOM_SPMI_VADC_H +#define _DT_BINDINGS_QCOM_SPMI_VADC_H + +/* Voltage ADC channels */ +#define VADC_USBIN 0x00 +#define VADC_DCIN 0x01 +#define VADC_VCHG_SNS 0x02 +#define VADC_SPARE1_03 0x03 +#define VADC_USB_ID_MV 0x04 +#define VADC_VCOIN 0x05 +#define VADC_VBAT_SNS 0x06 +#define VADC_VSYS 0x07 +#define VADC_DIE_TEMP 0x08 +#define VADC_REF_625MV 0x09 +#define VADC_REF_1250MV 0x0a +#define VADC_CHG_TEMP 0x0b +#define VADC_SPARE1 0x0c +#define VADC_SPARE2 0x0d +#define VADC_GND_REF 0x0e +#define VADC_VDD_VADC 0x0f + +#define VADC_P_MUX1_1_1 0x10 +#define VADC_P_MUX2_1_1 0x11 +#define VADC_P_MUX3_1_1 0x12 +#define VADC_P_MUX4_1_1 0x13 +#define VADC_P_MUX5_1_1 0x14 +#define VADC_P_MUX6_1_1 0x15 +#define VADC_P_MUX7_1_1 0x16 +#define VADC_P_MUX8_1_1 0x17 +#define VADC_P_MUX9_1_1 0x18 +#define VADC_P_MUX10_1_1 0x19 +#define VADC_P_MUX11_1_1 0x1a +#define VADC_P_MUX12_1_1 0x1b +#define VADC_P_MUX13_1_1 0x1c +#define VADC_P_MUX14_1_1 0x1d +#define VADC_P_MUX15_1_1 0x1e +#define VADC_P_MUX16_1_1 0x1f + +#define VADC_P_MUX1_1_3 0x20 +#define VADC_P_MUX2_1_3 0x21 +#define VADC_P_MUX3_1_3 0x22 +#define VADC_P_MUX4_1_3 0x23 +#define VADC_P_MUX5_1_3 0x24 +#define VADC_P_MUX6_1_3 0x25 +#define VADC_P_MUX7_1_3 0x26 +#define VADC_P_MUX8_1_3 0x27 +#define VADC_P_MUX9_1_3 0x28 +#define VADC_P_MUX10_1_3 0x29 +#define VADC_P_MUX11_1_3 0x2a +#define VADC_P_MUX12_1_3 0x2b +#define VADC_P_MUX13_1_3 0x2c +#define VADC_P_MUX14_1_3 0x2d +#define VADC_P_MUX15_1_3 0x2e +#define VADC_P_MUX16_1_3 0x2f + +#define VADC_LR_MUX1_BAT_THERM 0x30 +#define VADC_LR_MUX2_BAT_ID 0x31 +#define VADC_LR_MUX3_XO_THERM 0x32 +#define VADC_LR_MUX4_AMUX_THM1 0x33 +#define VADC_LR_MUX5_AMUX_THM2 0x34 +#define VADC_LR_MUX6_AMUX_THM3 0x35 +#define VADC_LR_MUX7_HW_ID 0x36 +#define VADC_LR_MUX8_AMUX_THM4 0x37 +#define VADC_LR_MUX9_AMUX_THM5 0x38 +#define VADC_LR_MUX10_USB_ID 0x39 +#define VADC_AMUX_PU1 0x3a +#define VADC_AMUX_PU2 0x3b +#define VADC_LR_MUX3_BUF_XO_THERM 0x3c + +#define VADC_LR_MUX1_PU1_BAT_THERM 0x70 +#define VADC_LR_MUX2_PU1_BAT_ID 0x71 +#define VADC_LR_MUX3_PU1_XO_THERM 0x72 +#define VADC_LR_MUX4_PU1_AMUX_THM1 0x73 +#define VADC_LR_MUX5_PU1_AMUX_THM2 0x74 +#define VADC_LR_MUX6_PU1_AMUX_THM3 0x75 +#define VADC_LR_MUX7_PU1_AMUX_HW_ID 0x76 +#define VADC_LR_MUX8_PU1_AMUX_THM4 0x77 +#define VADC_LR_MUX9_PU1_AMUX_THM5 0x78 +#define VADC_LR_MUX10_PU1_AMUX_USB_ID 0x79 +#define VADC_LR_MUX3_BUF_PU1_XO_THERM 0x7c + +#define VADC_LR_MUX1_PU2_BAT_THERM 0xb0 +#define VADC_LR_MUX2_PU2_BAT_ID 0xb1 +#define VADC_LR_MUX3_PU2_XO_THERM 0xb2 +#define VADC_LR_MUX4_PU2_AMUX_THM1 0xb3 +#define VADC_LR_MUX5_PU2_AMUX_THM2 0xb4 +#define VADC_LR_MUX6_PU2_AMUX_THM3 0xb5 +#define VADC_LR_MUX7_PU2_AMUX_HW_ID 0xb6 +#define VADC_LR_MUX8_PU2_AMUX_THM4 0xb7 +#define VADC_LR_MUX9_PU2_AMUX_THM5 0xb8 +#define VADC_LR_MUX10_PU2_AMUX_USB_ID 0xb9 +#define VADC_LR_MUX3_BUF_PU2_XO_THERM 0xbc + +#define VADC_LR_MUX1_PU1_PU2_BAT_THERM 0xf0 +#define VADC_LR_MUX2_PU1_PU2_BAT_ID 0xf1 +#define VADC_LR_MUX3_PU1_PU2_XO_THERM 0xf2 +#define VADC_LR_MUX4_PU1_PU2_AMUX_THM1 0xf3 +#define VADC_LR_MUX5_PU1_PU2_AMUX_THM2 0xf4 +#define VADC_LR_MUX6_PU1_PU2_AMUX_THM3 0xf5 +#define VADC_LR_MUX7_PU1_PU2_AMUX_HW_ID 0xf6 +#define VADC_LR_MUX8_PU1_PU2_AMUX_THM4 0xf7 +#define VADC_LR_MUX9_PU1_PU2_AMUX_THM5 0xf8 +#define VADC_LR_MUX10_PU1_PU2_AMUX_USB_ID 0xf9 +#define VADC_LR_MUX3_BUF_PU1_PU2_XO_THERM 0xfc + +#endif /* _DT_BINDINGS_QCOM_SPMI_VADC_H */ -- cgit v0.10.2 From 0917de94c02fd3fee68924b1e8e48cb32d090128 Mon Sep 17 00:00:00 2001 From: Stanimir Varbanov Date: Tue, 20 Jan 2015 12:15:22 +0200 Subject: iio: vadc: Qualcomm SPMI PMIC voltage ADC driver The voltage ADC is peripheral of Qualcomm SPMI PMIC chips. It has 15bits resolution and register space inside PMIC accessible across SPMI bus. The vadc driver registers itself through IIO interface. Signed-off-by: Stanimir Varbanov Signed-off-by: Ivan T. Ivanov Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 0f79e47..311829a 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -228,6 +228,20 @@ config QCOM_SPMI_IADC To compile this driver as a module, choose M here: the module will be called qcom-spmi-iadc. +config QCOM_SPMI_VADC + tristate "Qualcomm SPMI PMIC voltage ADC" + depends on SPMI + select REGMAP_SPMI + help + This is the IIO Voltage ADC driver for Qualcomm QPNP VADC Chip. + + The driver supports multiple channels read. The VADC is a 15-bit + sigma-delta ADC. Some of the channels are internally used for + calibration. + + To compile this driver as a module, choose M here: the module will + be called qcom-spmi-vadc. + config ROCKCHIP_SARADC tristate "Rockchip SARADC driver" depends on ARCH_ROCKCHIP || (ARM && COMPILE_TEST) diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 701fdb7..b0f62f7 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_MCP3422) += mcp3422.o obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o obj-$(CONFIG_NAU7802) += nau7802.o obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o +obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c new file mode 100644 index 0000000..3211729 --- /dev/null +++ b/drivers/iio/adc/qcom-spmi-vadc.c @@ -0,0 +1,1016 @@ +/* + * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* VADC register and bit definitions */ +#define VADC_REVISION2 0x1 +#define VADC_REVISION2_SUPPORTED_VADC 1 + +#define VADC_PERPH_TYPE 0x4 +#define VADC_PERPH_TYPE_ADC 8 + +#define VADC_PERPH_SUBTYPE 0x5 +#define VADC_PERPH_SUBTYPE_VADC 1 + +#define VADC_STATUS1 0x8 +#define VADC_STATUS1_OP_MODE 4 +#define VADC_STATUS1_REQ_STS BIT(1) +#define VADC_STATUS1_EOC BIT(0) +#define VADC_STATUS1_REQ_STS_EOC_MASK 0x3 + +#define VADC_MODE_CTL 0x40 +#define VADC_OP_MODE_SHIFT 3 +#define VADC_OP_MODE_NORMAL 0 +#define VADC_AMUX_TRIM_EN BIT(1) +#define VADC_ADC_TRIM_EN BIT(0) + +#define VADC_EN_CTL1 0x46 +#define VADC_EN_CTL1_SET BIT(7) + +#define VADC_ADC_CH_SEL_CTL 0x48 + +#define VADC_ADC_DIG_PARAM 0x50 +#define VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT 2 + +#define VADC_HW_SETTLE_DELAY 0x51 + +#define VADC_CONV_REQ 0x52 +#define VADC_CONV_REQ_SET BIT(7) + +#define VADC_FAST_AVG_CTL 0x5a +#define VADC_FAST_AVG_EN 0x5b +#define VADC_FAST_AVG_EN_SET BIT(7) + +#define VADC_ACCESS 0xd0 +#define VADC_ACCESS_DATA 0xa5 + +#define VADC_PERH_RESET_CTL3 0xda +#define VADC_FOLLOW_WARM_RB BIT(2) + +#define VADC_DATA 0x60 /* 16 bits */ + +#define VADC_CONV_TIME_MIN_US 2000 +#define VADC_CONV_TIME_MAX_US 2100 + +/* Min ADC code represents 0V */ +#define VADC_MIN_ADC_CODE 0x6000 +/* Max ADC code represents full-scale range of 1.8V */ +#define VADC_MAX_ADC_CODE 0xa800 + +#define VADC_ABSOLUTE_RANGE_UV 625000 +#define VADC_RATIOMETRIC_RANGE_UV 1800000 + +#define VADC_DEF_PRESCALING 0 /* 1:1 */ +#define VADC_DEF_DECIMATION 0 /* 512 */ +#define VADC_DEF_HW_SETTLE_TIME 0 /* 0 us */ +#define VADC_DEF_AVG_SAMPLES 0 /* 1 sample */ +#define VADC_DEF_CALIB_TYPE VADC_CALIB_ABSOLUTE + +#define VADC_DECIMATION_MIN 512 +#define VADC_DECIMATION_MAX 4096 + +#define VADC_HW_SETTLE_DELAY_MAX 10000 +#define VADC_AVG_SAMPLES_MAX 512 + +#define KELVINMIL_CELSIUSMIL 273150 + +#define VADC_CHAN_MIN VADC_USBIN +#define VADC_CHAN_MAX VADC_LR_MUX3_BUF_PU1_PU2_XO_THERM + +/* + * VADC_CALIB_ABSOLUTE: uses the 625mV and 1.25V as reference channels. + * VADC_CALIB_RATIOMETRIC: uses the reference voltage (1.8V) and GND for + * calibration. + */ +enum vadc_calibration { + VADC_CALIB_ABSOLUTE = 0, + VADC_CALIB_RATIOMETRIC +}; + +/** + * struct vadc_linear_graph - Represent ADC characteristics. + * @dy: numerator slope to calculate the gain. + * @dx: denominator slope to calculate the gain. + * @gnd: A/D word of the ground reference used for the channel. + * + * Each ADC device has different offset and gain parameters which are + * computed to calibrate the device. + */ +struct vadc_linear_graph { + s32 dy; + s32 dx; + s32 gnd; +}; + +/** + * struct vadc_prescale_ratio - Represent scaling ratio for ADC input. + * @num: the inverse numerator of the gain applied to the input channel. + * @den: the inverse denominator of the gain applied to the input channel. + */ +struct vadc_prescale_ratio { + u32 num; + u32 den; +}; + +/** + * struct vadc_channel_prop - VADC channel property. + * @channel: channel number, refer to the channel list. + * @calibration: calibration type. + * @decimation: sampling rate supported for the channel. + * @prescale: channel scaling performed on the input signal. + * @hw_settle_time: the time between AMUX being configured and the + * start of conversion. + * @avg_samples: ability to provide single result from the ADC + * that is an average of multiple measurements. + */ +struct vadc_channel_prop { + unsigned int channel; + enum vadc_calibration calibration; + unsigned int decimation; + unsigned int prescale; + unsigned int hw_settle_time; + unsigned int avg_samples; +}; + +/** + * struct vadc_priv - VADC private structure. + * @regmap: pointer to struct regmap. + * @dev: pointer to struct device. + * @base: base address for the ADC peripheral. + * @nchannels: number of VADC channels. + * @chan_props: array of VADC channel properties. + * @iio_chans: array of IIO channels specification. + * @are_ref_measured: are reference points measured. + * @poll_eoc: use polling instead of interrupt. + * @complete: VADC result notification after interrupt is received. + * @graph: store parameters for calibration. + * @lock: ADC lock for access to the peripheral. + */ +struct vadc_priv { + struct regmap *regmap; + struct device *dev; + u16 base; + unsigned int nchannels; + struct vadc_channel_prop *chan_props; + struct iio_chan_spec *iio_chans; + bool are_ref_measured; + bool poll_eoc; + struct completion complete; + struct vadc_linear_graph graph[2]; + struct mutex lock; +}; + +static const struct vadc_prescale_ratio vadc_prescale_ratios[] = { + {.num = 1, .den = 1}, + {.num = 1, .den = 3}, + {.num = 1, .den = 4}, + {.num = 1, .den = 6}, + {.num = 1, .den = 20}, + {.num = 1, .den = 8}, + {.num = 10, .den = 81}, + {.num = 1, .den = 10} +}; + +static int vadc_read(struct vadc_priv *vadc, u16 offset, u8 *data) +{ + return regmap_bulk_read(vadc->regmap, vadc->base + offset, data, 1); +} + +static int vadc_write(struct vadc_priv *vadc, u16 offset, u8 data) +{ + return regmap_write(vadc->regmap, vadc->base + offset, data); +} + +static int vadc_reset(struct vadc_priv *vadc) +{ + u8 data; + int ret; + + ret = vadc_write(vadc, VADC_ACCESS, VADC_ACCESS_DATA); + if (ret) + return ret; + + ret = vadc_read(vadc, VADC_PERH_RESET_CTL3, &data); + if (ret) + return ret; + + ret = vadc_write(vadc, VADC_ACCESS, VADC_ACCESS_DATA); + if (ret) + return ret; + + data |= VADC_FOLLOW_WARM_RB; + + return vadc_write(vadc, VADC_PERH_RESET_CTL3, data); +} + +static int vadc_set_state(struct vadc_priv *vadc, bool state) +{ + return vadc_write(vadc, VADC_EN_CTL1, state ? VADC_EN_CTL1_SET : 0); +} + +static void vadc_show_status(struct vadc_priv *vadc) +{ + u8 mode, sta1, chan, dig, en, req; + int ret; + + ret = vadc_read(vadc, VADC_MODE_CTL, &mode); + if (ret) + return; + + ret = vadc_read(vadc, VADC_ADC_DIG_PARAM, &dig); + if (ret) + return; + + ret = vadc_read(vadc, VADC_ADC_CH_SEL_CTL, &chan); + if (ret) + return; + + ret = vadc_read(vadc, VADC_CONV_REQ, &req); + if (ret) + return; + + ret = vadc_read(vadc, VADC_STATUS1, &sta1); + if (ret) + return; + + ret = vadc_read(vadc, VADC_EN_CTL1, &en); + if (ret) + return; + + dev_err(vadc->dev, + "mode:%02x en:%02x chan:%02x dig:%02x req:%02x sta1:%02x\n", + mode, en, chan, dig, req, sta1); +} + +static int vadc_configure(struct vadc_priv *vadc, + struct vadc_channel_prop *prop) +{ + u8 decimation, mode_ctrl; + int ret; + + /* Mode selection */ + mode_ctrl = (VADC_OP_MODE_NORMAL << VADC_OP_MODE_SHIFT) | + VADC_ADC_TRIM_EN | VADC_AMUX_TRIM_EN; + ret = vadc_write(vadc, VADC_MODE_CTL, mode_ctrl); + if (ret) + return ret; + + /* Channel selection */ + ret = vadc_write(vadc, VADC_ADC_CH_SEL_CTL, prop->channel); + if (ret) + return ret; + + /* Digital parameter setup */ + decimation = prop->decimation << VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT; + ret = vadc_write(vadc, VADC_ADC_DIG_PARAM, decimation); + if (ret) + return ret; + + /* HW settle time delay */ + ret = vadc_write(vadc, VADC_HW_SETTLE_DELAY, prop->hw_settle_time); + if (ret) + return ret; + + ret = vadc_write(vadc, VADC_FAST_AVG_CTL, prop->avg_samples); + if (ret) + return ret; + + if (prop->avg_samples) + ret = vadc_write(vadc, VADC_FAST_AVG_EN, VADC_FAST_AVG_EN_SET); + else + ret = vadc_write(vadc, VADC_FAST_AVG_EN, 0); + + return ret; +} + +static int vadc_poll_wait_eoc(struct vadc_priv *vadc, unsigned int interval_us) +{ + unsigned int count, retry; + u8 sta1; + int ret; + + retry = interval_us / VADC_CONV_TIME_MIN_US; + + for (count = 0; count < retry; count++) { + ret = vadc_read(vadc, VADC_STATUS1, &sta1); + if (ret) + return ret; + + sta1 &= VADC_STATUS1_REQ_STS_EOC_MASK; + if (sta1 == VADC_STATUS1_EOC) + return 0; + + usleep_range(VADC_CONV_TIME_MIN_US, VADC_CONV_TIME_MAX_US); + } + + vadc_show_status(vadc); + + return -ETIMEDOUT; +} + +static int vadc_read_result(struct vadc_priv *vadc, u16 *data) +{ + int ret; + + ret = regmap_bulk_read(vadc->regmap, vadc->base + VADC_DATA, data, 2); + if (ret) + return ret; + + *data = clamp_t(u16, *data, VADC_MIN_ADC_CODE, VADC_MAX_ADC_CODE); + + return 0; +} + +static struct vadc_channel_prop *vadc_get_channel(struct vadc_priv *vadc, + unsigned int num) +{ + unsigned int i; + + for (i = 0; i < vadc->nchannels; i++) + if (vadc->chan_props[i].channel == num) + return &vadc->chan_props[i]; + + dev_dbg(vadc->dev, "no such channel %02x\n", num); + + return NULL; +} + +static int vadc_do_conversion(struct vadc_priv *vadc, + struct vadc_channel_prop *prop, u16 *data) +{ + unsigned int timeout; + int ret; + + mutex_lock(&vadc->lock); + + ret = vadc_configure(vadc, prop); + if (ret) + goto unlock; + + if (!vadc->poll_eoc) + reinit_completion(&vadc->complete); + + ret = vadc_set_state(vadc, true); + if (ret) + goto unlock; + + ret = vadc_write(vadc, VADC_CONV_REQ, VADC_CONV_REQ_SET); + if (ret) + goto err_disable; + + timeout = BIT(prop->avg_samples) * VADC_CONV_TIME_MIN_US * 2; + + if (vadc->poll_eoc) { + ret = vadc_poll_wait_eoc(vadc, timeout); + } else { + ret = wait_for_completion_timeout(&vadc->complete, timeout); + if (!ret) { + ret = -ETIMEDOUT; + goto err_disable; + } + + /* Double check conversion status */ + ret = vadc_poll_wait_eoc(vadc, VADC_CONV_TIME_MIN_US); + if (ret) + goto err_disable; + } + + ret = vadc_read_result(vadc, data); + +err_disable: + vadc_set_state(vadc, false); + if (ret) + dev_err(vadc->dev, "conversion failed\n"); +unlock: + mutex_unlock(&vadc->lock); + return ret; +} + +static int vadc_measure_ref_points(struct vadc_priv *vadc) +{ + struct vadc_channel_prop *prop; + u16 read_1, read_2; + int ret; + + vadc->graph[VADC_CALIB_RATIOMETRIC].dx = VADC_RATIOMETRIC_RANGE_UV; + vadc->graph[VADC_CALIB_ABSOLUTE].dx = VADC_ABSOLUTE_RANGE_UV; + + prop = vadc_get_channel(vadc, VADC_REF_1250MV); + ret = vadc_do_conversion(vadc, prop, &read_1); + if (ret) + goto err; + + /* Try with buffered 625mV channel first */ + prop = vadc_get_channel(vadc, VADC_SPARE1); + if (!prop) + prop = vadc_get_channel(vadc, VADC_REF_625MV); + + ret = vadc_do_conversion(vadc, prop, &read_2); + if (ret) + goto err; + + if (read_1 == read_2) { + ret = -EINVAL; + goto err; + } + + vadc->graph[VADC_CALIB_ABSOLUTE].dy = read_1 - read_2; + vadc->graph[VADC_CALIB_ABSOLUTE].gnd = read_2; + + /* Ratiometric calibration */ + prop = vadc_get_channel(vadc, VADC_VDD_VADC); + ret = vadc_do_conversion(vadc, prop, &read_1); + if (ret) + goto err; + + prop = vadc_get_channel(vadc, VADC_GND_REF); + ret = vadc_do_conversion(vadc, prop, &read_2); + if (ret) + goto err; + + if (read_1 == read_2) { + ret = -EINVAL; + goto err; + } + + vadc->graph[VADC_CALIB_RATIOMETRIC].dy = read_1 - read_2; + vadc->graph[VADC_CALIB_RATIOMETRIC].gnd = read_2; +err: + if (ret) + dev_err(vadc->dev, "measure reference points failed\n"); + + return ret; +} + +static s32 vadc_calibrate(struct vadc_priv *vadc, + const struct vadc_channel_prop *prop, u16 adc_code) +{ + const struct vadc_prescale_ratio *prescale; + s32 voltage; + + voltage = adc_code - vadc->graph[prop->calibration].gnd; + voltage *= vadc->graph[prop->calibration].dx; + voltage = voltage / vadc->graph[prop->calibration].dy; + + if (prop->calibration == VADC_CALIB_ABSOLUTE) + voltage += vadc->graph[prop->calibration].dx; + + if (voltage < 0) + voltage = 0; + + prescale = &vadc_prescale_ratios[prop->prescale]; + + voltage = voltage * prescale->den; + + return voltage / prescale->num; +} + +static int vadc_decimation_from_dt(u32 value) +{ + if (!is_power_of_2(value) || value < VADC_DECIMATION_MIN || + value > VADC_DECIMATION_MAX) + return -EINVAL; + + return __ffs64(value / VADC_DECIMATION_MIN); +} + +static int vadc_prescaling_from_dt(u32 num, u32 den) +{ + unsigned int pre; + + for (pre = 0; pre < ARRAY_SIZE(vadc_prescale_ratios); pre++) + if (vadc_prescale_ratios[pre].num == num && + vadc_prescale_ratios[pre].den == den) + break; + + if (pre == ARRAY_SIZE(vadc_prescale_ratios)) + return -EINVAL; + + return pre; +} + +static int vadc_hw_settle_time_from_dt(u32 value) +{ + if ((value <= 1000 && value % 100) || (value > 1000 && value % 2000)) + return -EINVAL; + + if (value <= 1000) + value /= 100; + else + value = value / 2000 + 10; + + return value; +} + +static int vadc_avg_samples_from_dt(u32 value) +{ + if (!is_power_of_2(value) || value > VADC_AVG_SAMPLES_MAX) + return -EINVAL; + + return __ffs64(value); +} + +static int vadc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, + long mask) +{ + struct vadc_priv *vadc = iio_priv(indio_dev); + struct vadc_channel_prop *prop; + u16 adc_code; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + prop = &vadc->chan_props[chan->address]; + ret = vadc_do_conversion(vadc, prop, &adc_code); + if (ret) + break; + + *val = vadc_calibrate(vadc, prop, adc_code); + + /* 2mV/K, return milli Celsius */ + *val /= 2; + *val -= KELVINMIL_CELSIUSMIL; + return IIO_VAL_INT; + case IIO_CHAN_INFO_RAW: + prop = &vadc->chan_props[chan->address]; + ret = vadc_do_conversion(vadc, prop, &adc_code); + if (ret) + break; + + *val = vadc_calibrate(vadc, prop, adc_code); + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 1000; + return IIO_VAL_INT_PLUS_MICRO; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int vadc_of_xlate(struct iio_dev *indio_dev, + const struct of_phandle_args *iiospec) +{ + struct vadc_priv *vadc = iio_priv(indio_dev); + unsigned int i; + + for (i = 0; i < vadc->nchannels; i++) + if (vadc->iio_chans[i].channel == iiospec->args[0]) + return i; + + return -EINVAL; +} + +static const struct iio_info vadc_info = { + .read_raw = vadc_read_raw, + .of_xlate = vadc_of_xlate, + .driver_module = THIS_MODULE, +}; + +struct vadc_channels { + const char *datasheet_name; + unsigned int prescale_index; + enum iio_chan_type type; + long info_mask; +}; + +#define VADC_CHAN(_dname, _type, _mask, _pre) \ + [VADC_##_dname] = { \ + .datasheet_name = __stringify(_dname), \ + .prescale_index = _pre, \ + .type = _type, \ + .info_mask = _mask \ + }, \ + +#define VADC_CHAN_TEMP(_dname, _pre) \ + VADC_CHAN(_dname, IIO_TEMP, BIT(IIO_CHAN_INFO_PROCESSED), _pre) \ + +#define VADC_CHAN_VOLT(_dname, _pre) \ + VADC_CHAN(_dname, IIO_VOLTAGE, \ + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \ + _pre) \ + +/* + * The array represents all possible ADC channels found in the supported PMICs. + * Every index in the array is equal to the channel number per datasheet. The + * gaps in the array should be treated as reserved channels. + */ +static const struct vadc_channels vadc_chans[] = { + VADC_CHAN_VOLT(USBIN, 4) + VADC_CHAN_VOLT(DCIN, 4) + VADC_CHAN_VOLT(VCHG_SNS, 3) + VADC_CHAN_VOLT(SPARE1_03, 1) + VADC_CHAN_VOLT(USB_ID_MV, 1) + VADC_CHAN_VOLT(VCOIN, 1) + VADC_CHAN_VOLT(VBAT_SNS, 1) + VADC_CHAN_VOLT(VSYS, 1) + VADC_CHAN_TEMP(DIE_TEMP, 0) + VADC_CHAN_VOLT(REF_625MV, 0) + VADC_CHAN_VOLT(REF_1250MV, 0) + VADC_CHAN_VOLT(CHG_TEMP, 0) + VADC_CHAN_VOLT(SPARE1, 0) + VADC_CHAN_VOLT(SPARE2, 0) + VADC_CHAN_VOLT(GND_REF, 0) + VADC_CHAN_VOLT(VDD_VADC, 0) + + VADC_CHAN_VOLT(P_MUX1_1_1, 0) + VADC_CHAN_VOLT(P_MUX2_1_1, 0) + VADC_CHAN_VOLT(P_MUX3_1_1, 0) + VADC_CHAN_VOLT(P_MUX4_1_1, 0) + VADC_CHAN_VOLT(P_MUX5_1_1, 0) + VADC_CHAN_VOLT(P_MUX6_1_1, 0) + VADC_CHAN_VOLT(P_MUX7_1_1, 0) + VADC_CHAN_VOLT(P_MUX8_1_1, 0) + VADC_CHAN_VOLT(P_MUX9_1_1, 0) + VADC_CHAN_VOLT(P_MUX10_1_1, 0) + VADC_CHAN_VOLT(P_MUX11_1_1, 0) + VADC_CHAN_VOLT(P_MUX12_1_1, 0) + VADC_CHAN_VOLT(P_MUX13_1_1, 0) + VADC_CHAN_VOLT(P_MUX14_1_1, 0) + VADC_CHAN_VOLT(P_MUX15_1_1, 0) + VADC_CHAN_VOLT(P_MUX16_1_1, 0) + + VADC_CHAN_VOLT(P_MUX1_1_3, 1) + VADC_CHAN_VOLT(P_MUX2_1_3, 1) + VADC_CHAN_VOLT(P_MUX3_1_3, 1) + VADC_CHAN_VOLT(P_MUX4_1_3, 1) + VADC_CHAN_VOLT(P_MUX5_1_3, 1) + VADC_CHAN_VOLT(P_MUX6_1_3, 1) + VADC_CHAN_VOLT(P_MUX7_1_3, 1) + VADC_CHAN_VOLT(P_MUX8_1_3, 1) + VADC_CHAN_VOLT(P_MUX9_1_3, 1) + VADC_CHAN_VOLT(P_MUX10_1_3, 1) + VADC_CHAN_VOLT(P_MUX11_1_3, 1) + VADC_CHAN_VOLT(P_MUX12_1_3, 1) + VADC_CHAN_VOLT(P_MUX13_1_3, 1) + VADC_CHAN_VOLT(P_MUX14_1_3, 1) + VADC_CHAN_VOLT(P_MUX15_1_3, 1) + VADC_CHAN_VOLT(P_MUX16_1_3, 1) + + VADC_CHAN_VOLT(LR_MUX1_BAT_THERM, 0) + VADC_CHAN_VOLT(LR_MUX2_BAT_ID, 0) + VADC_CHAN_VOLT(LR_MUX3_XO_THERM, 0) + VADC_CHAN_VOLT(LR_MUX4_AMUX_THM1, 0) + VADC_CHAN_VOLT(LR_MUX5_AMUX_THM2, 0) + VADC_CHAN_VOLT(LR_MUX6_AMUX_THM3, 0) + VADC_CHAN_VOLT(LR_MUX7_HW_ID, 0) + VADC_CHAN_VOLT(LR_MUX8_AMUX_THM4, 0) + VADC_CHAN_VOLT(LR_MUX9_AMUX_THM5, 0) + VADC_CHAN_VOLT(LR_MUX10_USB_ID, 0) + VADC_CHAN_VOLT(AMUX_PU1, 0) + VADC_CHAN_VOLT(AMUX_PU2, 0) + VADC_CHAN_VOLT(LR_MUX3_BUF_XO_THERM, 0) + + VADC_CHAN_VOLT(LR_MUX1_PU1_BAT_THERM, 0) + VADC_CHAN_VOLT(LR_MUX2_PU1_BAT_ID, 0) + VADC_CHAN_VOLT(LR_MUX3_PU1_XO_THERM, 0) + VADC_CHAN_VOLT(LR_MUX4_PU1_AMUX_THM1, 0) + VADC_CHAN_VOLT(LR_MUX5_PU1_AMUX_THM2, 0) + VADC_CHAN_VOLT(LR_MUX6_PU1_AMUX_THM3, 0) + VADC_CHAN_VOLT(LR_MUX7_PU1_AMUX_HW_ID, 0) + VADC_CHAN_VOLT(LR_MUX8_PU1_AMUX_THM4, 0) + VADC_CHAN_VOLT(LR_MUX9_PU1_AMUX_THM5, 0) + VADC_CHAN_VOLT(LR_MUX10_PU1_AMUX_USB_ID, 0) + VADC_CHAN_VOLT(LR_MUX3_BUF_PU1_XO_THERM, 0) + + VADC_CHAN_VOLT(LR_MUX1_PU2_BAT_THERM, 0) + VADC_CHAN_VOLT(LR_MUX2_PU2_BAT_ID, 0) + VADC_CHAN_VOLT(LR_MUX3_PU2_XO_THERM, 0) + VADC_CHAN_VOLT(LR_MUX4_PU2_AMUX_THM1, 0) + VADC_CHAN_VOLT(LR_MUX5_PU2_AMUX_THM2, 0) + VADC_CHAN_VOLT(LR_MUX6_PU2_AMUX_THM3, 0) + VADC_CHAN_VOLT(LR_MUX7_PU2_AMUX_HW_ID, 0) + VADC_CHAN_VOLT(LR_MUX8_PU2_AMUX_THM4, 0) + VADC_CHAN_VOLT(LR_MUX9_PU2_AMUX_THM5, 0) + VADC_CHAN_VOLT(LR_MUX10_PU2_AMUX_USB_ID, 0) + VADC_CHAN_VOLT(LR_MUX3_BUF_PU2_XO_THERM, 0) + + VADC_CHAN_VOLT(LR_MUX1_PU1_PU2_BAT_THERM, 0) + VADC_CHAN_VOLT(LR_MUX2_PU1_PU2_BAT_ID, 0) + VADC_CHAN_VOLT(LR_MUX3_PU1_PU2_XO_THERM, 0) + VADC_CHAN_VOLT(LR_MUX4_PU1_PU2_AMUX_THM1, 0) + VADC_CHAN_VOLT(LR_MUX5_PU1_PU2_AMUX_THM2, 0) + VADC_CHAN_VOLT(LR_MUX6_PU1_PU2_AMUX_THM3, 0) + VADC_CHAN_VOLT(LR_MUX7_PU1_PU2_AMUX_HW_ID, 0) + VADC_CHAN_VOLT(LR_MUX8_PU1_PU2_AMUX_THM4, 0) + VADC_CHAN_VOLT(LR_MUX9_PU1_PU2_AMUX_THM5, 0) + VADC_CHAN_VOLT(LR_MUX10_PU1_PU2_AMUX_USB_ID, 0) + VADC_CHAN_VOLT(LR_MUX3_BUF_PU1_PU2_XO_THERM, 0) +}; + +static int vadc_get_dt_channel_data(struct device *dev, + struct vadc_channel_prop *prop, + struct device_node *node) +{ + const char *name = node->name; + u32 chan, value, varr[2]; + int ret; + + ret = of_property_read_u32(node, "reg", &chan); + if (ret) { + dev_err(dev, "invalid channel number %s\n", name); + return ret; + } + + if (chan > VADC_CHAN_MAX || chan < VADC_CHAN_MIN) { + dev_err(dev, "%s invalid channel number %d\n", name, chan); + return -EINVAL; + } + + /* the channel has DT description */ + prop->channel = chan; + + ret = of_property_read_u32(node, "qcom,decimation", &value); + if (!ret) { + ret = vadc_decimation_from_dt(value); + if (ret < 0) { + dev_err(dev, "%02x invalid decimation %d\n", + chan, value); + return ret; + } + prop->decimation = ret; + } else { + prop->decimation = VADC_DEF_DECIMATION; + } + + ret = of_property_read_u32_array(node, "qcom,pre-scaling", varr, 2); + if (!ret) { + ret = vadc_prescaling_from_dt(varr[0], varr[1]); + if (ret < 0) { + dev_err(dev, "%02x invalid pre-scaling <%d %d>\n", + chan, varr[0], varr[1]); + return ret; + } + prop->prescale = ret; + } else { + prop->prescale = vadc_chans[prop->channel].prescale_index; + } + + ret = of_property_read_u32(node, "qcom,hw-settle-time", &value); + if (!ret) { + ret = vadc_hw_settle_time_from_dt(value); + if (ret < 0) { + dev_err(dev, "%02x invalid hw-settle-time %d us\n", + chan, value); + return ret; + } + prop->hw_settle_time = ret; + } else { + prop->hw_settle_time = VADC_DEF_HW_SETTLE_TIME; + } + + ret = of_property_read_u32(node, "qcom,avg-samples", &value); + if (!ret) { + ret = vadc_avg_samples_from_dt(value); + if (ret < 0) { + dev_err(dev, "%02x invalid avg-samples %d\n", + chan, value); + return ret; + } + prop->avg_samples = ret; + } else { + prop->avg_samples = VADC_DEF_AVG_SAMPLES; + } + + if (of_property_read_bool(node, "qcom,ratiometric")) + prop->calibration = VADC_CALIB_RATIOMETRIC; + else + prop->calibration = VADC_CALIB_ABSOLUTE; + + dev_dbg(dev, "%02x name %s\n", chan, name); + + return 0; +} + +static int vadc_get_dt_data(struct vadc_priv *vadc, struct device_node *node) +{ + const struct vadc_channels *vadc_chan; + struct iio_chan_spec *iio_chan; + struct vadc_channel_prop prop; + struct device_node *child; + unsigned int index = 0; + int ret; + + vadc->nchannels = of_get_available_child_count(node); + if (!vadc->nchannels) + return -EINVAL; + + vadc->iio_chans = devm_kcalloc(vadc->dev, vadc->nchannels, + sizeof(*vadc->iio_chans), GFP_KERNEL); + if (!vadc->iio_chans) + return -ENOMEM; + + vadc->chan_props = devm_kcalloc(vadc->dev, vadc->nchannels, + sizeof(*vadc->chan_props), GFP_KERNEL); + if (!vadc->chan_props) + return -ENOMEM; + + iio_chan = vadc->iio_chans; + + for_each_available_child_of_node(node, child) { + ret = vadc_get_dt_channel_data(vadc->dev, &prop, child); + if (ret) + return ret; + + vadc->chan_props[index] = prop; + + vadc_chan = &vadc_chans[prop.channel]; + + iio_chan->channel = prop.channel; + iio_chan->datasheet_name = vadc_chan->datasheet_name; + iio_chan->info_mask_separate = vadc_chan->info_mask; + iio_chan->type = vadc_chan->type; + iio_chan->indexed = 1; + iio_chan->address = index++; + + iio_chan++; + } + + /* These channels are mandatory, they are used as reference points */ + if (!vadc_get_channel(vadc, VADC_REF_1250MV)) { + dev_err(vadc->dev, "Please define 1.25V channel\n"); + return -ENODEV; + } + + if (!vadc_get_channel(vadc, VADC_REF_625MV)) { + dev_err(vadc->dev, "Please define 0.625V channel\n"); + return -ENODEV; + } + + if (!vadc_get_channel(vadc, VADC_VDD_VADC)) { + dev_err(vadc->dev, "Please define VDD channel\n"); + return -ENODEV; + } + + if (!vadc_get_channel(vadc, VADC_GND_REF)) { + dev_err(vadc->dev, "Please define GND channel\n"); + return -ENODEV; + } + + return 0; +} + +static irqreturn_t vadc_isr(int irq, void *dev_id) +{ + struct vadc_priv *vadc = dev_id; + + complete(&vadc->complete); + + return IRQ_HANDLED; +} + +static int vadc_check_revision(struct vadc_priv *vadc) +{ + u8 val; + int ret; + + ret = vadc_read(vadc, VADC_PERPH_TYPE, &val); + if (ret) + return ret; + + if (val < VADC_PERPH_TYPE_ADC) { + dev_err(vadc->dev, "%d is not ADC\n", val); + return -ENODEV; + } + + ret = vadc_read(vadc, VADC_PERPH_SUBTYPE, &val); + if (ret) + return ret; + + if (val < VADC_PERPH_SUBTYPE_VADC) { + dev_err(vadc->dev, "%d is not VADC\n", val); + return -ENODEV; + } + + ret = vadc_read(vadc, VADC_REVISION2, &val); + if (ret) + return ret; + + if (val < VADC_REVISION2_SUPPORTED_VADC) { + dev_err(vadc->dev, "revision %d not supported\n", val); + return -ENODEV; + } + + return 0; +} + +static int vadc_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct iio_dev *indio_dev; + struct vadc_priv *vadc; + struct regmap *regmap; + int ret, irq_eoc; + u32 reg; + + regmap = dev_get_regmap(dev->parent, NULL); + if (!regmap) + return -ENODEV; + + ret = of_property_read_u32(node, "reg", ®); + if (ret < 0) + return ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*vadc)); + if (!indio_dev) + return -ENOMEM; + + vadc = iio_priv(indio_dev); + vadc->regmap = regmap; + vadc->dev = dev; + vadc->base = reg; + vadc->are_ref_measured = false; + init_completion(&vadc->complete); + mutex_init(&vadc->lock); + + ret = vadc_check_revision(vadc); + if (ret) + return ret; + + ret = vadc_get_dt_data(vadc, node); + if (ret) + return ret; + + irq_eoc = platform_get_irq(pdev, 0); + if (irq_eoc < 0) { + if (irq_eoc == -EPROBE_DEFER || irq_eoc == -EINVAL) + return irq_eoc; + vadc->poll_eoc = true; + } else { + ret = devm_request_irq(dev, irq_eoc, vadc_isr, 0, + "spmi-vadc", vadc); + if (ret) + return ret; + } + + ret = vadc_reset(vadc); + if (ret) { + dev_err(dev, "reset failed\n"); + return ret; + } + + ret = vadc_measure_ref_points(vadc); + if (ret) + return ret; + + indio_dev->dev.parent = dev; + indio_dev->dev.of_node = node; + indio_dev->name = pdev->name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &vadc_info; + indio_dev->channels = vadc->iio_chans; + indio_dev->num_channels = vadc->nchannels; + + return devm_iio_device_register(dev, indio_dev); +} + +static const struct of_device_id vadc_match_table[] = { + { .compatible = "qcom,spmi-vadc" }, + { } +}; +MODULE_DEVICE_TABLE(of, vadc_match_table); + +static struct platform_driver vadc_driver = { + .driver = { + .name = "qcom-spmi-vadc", + .of_match_table = vadc_match_table, + }, + .probe = vadc_probe, +}; +module_platform_driver(vadc_driver); + +MODULE_ALIAS("platform:qcom-spmi-vadc"); +MODULE_DESCRIPTION("Qualcomm SPMI PMIC voltage ADC driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Stanimir Varbanov "); +MODULE_AUTHOR("Ivan T. Ivanov "); -- cgit v0.10.2 From ef99fd59f122ace847636b9143f33197c51f18b5 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Tue, 27 Jan 2015 22:29:59 +0100 Subject: staging: lustre: libcfs: nidstrings: Change type in printf format string Wrong type in printf format string, requires 'unsigned int' but the argument type is 'int' This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/nidstrings.c b/drivers/staging/lustre/lustre/libcfs/nidstrings.c index c70da37..087449f 100644 --- a/drivers/staging/lustre/lustre/libcfs/nidstrings.c +++ b/drivers/staging/lustre/lustre/libcfs/nidstrings.c @@ -364,7 +364,7 @@ libcfs_lnd2str(int lnd) return nf->nf_name; str = libcfs_next_nidstring(); - snprintf(str, LNET_NIDSTR_SIZE, "?%u?", lnd); + snprintf(str, LNET_NIDSTR_SIZE, "?%d?", lnd); return str; } EXPORT_SYMBOL(libcfs_lnd2str); @@ -390,11 +390,11 @@ libcfs_net2str(__u32 net) char *str = libcfs_next_nidstring(); if (nf == NULL) - snprintf(str, LNET_NIDSTR_SIZE, "<%u:%u>", lnd, num); + snprintf(str, LNET_NIDSTR_SIZE, "<%d:%d>", lnd, num); else if (num == 0) snprintf(str, LNET_NIDSTR_SIZE, "%s", nf->nf_name); else - snprintf(str, LNET_NIDSTR_SIZE, "%s%u", nf->nf_name, num); + snprintf(str, LNET_NIDSTR_SIZE, "%s%d", nf->nf_name, num); return str; } @@ -418,7 +418,7 @@ libcfs_nid2str(lnet_nid_t nid) str = libcfs_next_nidstring(); if (nf == NULL) - snprintf(str, LNET_NIDSTR_SIZE, "%x@<%u:%u>", addr, lnd, nnum); + snprintf(str, LNET_NIDSTR_SIZE, "%x@<%d:%d>", addr, lnd, nnum); else { nf->nf_addr2str(addr, str); nob = strlen(str); @@ -426,7 +426,7 @@ libcfs_nid2str(lnet_nid_t nid) snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s", nf->nf_name); else - snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s%u", + snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s%d", nf->nf_name, nnum); } -- cgit v0.10.2 From 1e3e981ad576eeb47ca1ca1743ff3b3d39e576a4 Mon Sep 17 00:00:00 2001 From: Kumar Amit Mehta Date: Mon, 26 Jan 2015 17:52:22 +0100 Subject: staging: lustre: lustre: obdclass: obd_mount.c: Fix NULL dereference OBD_ALLOC_PTR(uuid) invokes kmalloc, which may return NULL. This fix adds a check before dereferencing such pointer. Signed-off-by: Kumar Amit Mehta Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 4f39cde..3c0c910 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -376,6 +376,11 @@ int lustre_start_mgc(struct super_block *sb) /* Random uuid for MGC allows easier reconnects */ OBD_ALLOC_PTR(uuid); + if (!uuid) { + rc = -ENOMEM; + goto out_free; + } + ll_generate_random_uuid(uuidc); class_uuid_unparse(uuidc, uuid); -- cgit v0.10.2 From c1f79c74e222000386f3950ed98d150e6009648b Mon Sep 17 00:00:00 2001 From: Kumar Amit Mehta Date: Mon, 26 Jan 2015 16:44:53 +0100 Subject: staging: lustre: lustre: mdc: lproc_mdc.c: Fix for potential NULL pointer dereference In mdc_kuc_write(), OBD_ALLOC(lh, len) may leave 'lh' to NULL as kmalloc may fail to allocate memory. This fix adds a check to avoid, dereferencing a NULL pointer. Signed-off-by: Kumar Amit Mehta Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index c420219..c791941 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -106,6 +106,8 @@ static ssize_t mdc_kuc_write(struct file *file, /* for mockup below */ 2 * cfs_size_round(sizeof(*hai)); OBD_ALLOC(lh, len); + if (!lh) + return -ENOMEM; lh->kuc_magic = KUC_MAGIC; lh->kuc_transport = KUC_TRANSPORT_HSM; -- cgit v0.10.2 From b12fdf7da28ff9709a72814e141646e20d97ed21 Mon Sep 17 00:00:00 2001 From: Zachary Warren Date: Sat, 17 Jan 2015 22:39:53 +1100 Subject: staging: unisys: rework signal remove/insert to avoid sparse lock warnings Avoids the following warnings from sparse: visorchannel_funcs.c:457:9: warning: context imbalance in 'visorchannel_signalremove' - different lock contexts for basic block visorchannel_funcs.c:512:9: warning: context imbalance in 'visorchannel_signalinsert' - different lock contexts for basic These warnings are false positives. Sparse can't track conditional contexts. The change puts the lock/unlock into the same context by splitting the insert/remove functions each into a wrapper function that does locking if necessary and an inner function that does the insert/remove operation. Signed-off-by: Zachary Warren Acked-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c index 6c48ba1..0188ef8 100644 --- a/drivers/staging/unisys/visorchannel/visorchannel_funcs.c +++ b/drivers/staging/unisys/visorchannel/visorchannel_funcs.c @@ -411,27 +411,21 @@ safe_sig_queue_validate(struct signal_queue_header *psafe_sqh, return 1; } /* end safe_sig_queue_validate */ -BOOL -visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) +static BOOL +signalremove_inner(struct visorchannel *channel, u32 queue, void *msg) { - BOOL rc = FALSE; struct signal_queue_header sig_hdr; - if (channel->needs_lock) - spin_lock(&channel->remove_lock); - if (!sig_read_header(channel, queue, &sig_hdr)) { - rc = FALSE; - goto cleanup; - } - if (sig_hdr.head == sig_hdr.tail) { - rc = FALSE; /* no signals to remove */ - goto cleanup; + return FALSE; } + if (sig_hdr.head == sig_hdr.tail) + return FALSE; /* no signals to remove */ + sig_hdr.tail = (sig_hdr.tail + 1) % sig_hdr.max_slots; if (!sig_read_data(channel, queue, &sig_hdr, sig_hdr.tail, msg)) { - ERRDRV("sig_read_data failed: (status=%d)\n", rc); - goto cleanup; + ERRDRV("sig_read_data failed\n"); + return FALSE; } sig_hdr.num_received++; @@ -440,53 +434,54 @@ visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) */ mb(); /* required for channel synch */ if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, tail)) { - ERRDRV("visor_memregion_write of Tail failed: (status=%d)\n", - rc); - goto cleanup; + ERRDRV("visor_memregion_write of Tail failed\n"); + return FALSE; } if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_received)) { - ERRDRV("visor_memregion_write of NumSignalsReceived failed: (status=%d)\n", - rc); - goto cleanup; + ERRDRV("visor_memregion_write of NumSignalsReceived failed\n"); + return FALSE; } - rc = TRUE; -cleanup: - if (channel->needs_lock) + return TRUE; +} + +BOOL +visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg) +{ + BOOL rc; + + if (channel->needs_lock) { + spin_lock(&channel->remove_lock); + rc = signalremove_inner(channel, queue, msg); spin_unlock(&channel->remove_lock); + } else { + rc = signalremove_inner(channel, queue, msg); + } return rc; } EXPORT_SYMBOL_GPL(visorchannel_signalremove); -BOOL -visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) +static BOOL +signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) { - BOOL rc = FALSE; struct signal_queue_header sig_hdr; - if (channel->needs_lock) - spin_lock(&channel->insert_lock); - if (!sig_read_header(channel, queue, &sig_hdr)) { - rc = FALSE; - goto cleanup; + return FALSE; } sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots); if (sig_hdr.head == sig_hdr.tail) { sig_hdr.num_overflows++; - if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows)) { - ERRDRV("visor_memregion_write of NumOverflows failed: (status=%d)\n", - rc); - goto cleanup; - } - rc = FALSE; - goto cleanup; + if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_overflows)) + ERRDRV("visor_memregion_write of NumOverflows failed\n"); + + return FALSE; } if (!sig_write_data(channel, queue, &sig_hdr, sig_hdr.head, msg)) { - ERRDRV("sig_write_data failed: (status=%d)\n", rc); - goto cleanup; + ERRDRV("sig_write_data failed\n"); + return FALSE; } sig_hdr.num_sent++; @@ -495,19 +490,29 @@ visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) */ mb(); /* required for channel synch */ if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, head)) { - ERRDRV("visor_memregion_write of Head failed: (status=%d)\n", - rc); - goto cleanup; + ERRDRV("visor_memregion_write of Head failed\n"); + return FALSE; } if (!SIG_WRITE_FIELD(channel, queue, &sig_hdr, num_sent)) { - ERRDRV("visor_memregion_write of NumSignalsSent failed: (status=%d)\n", - rc); - goto cleanup; + ERRDRV("visor_memregion_write of NumSignalsSent failed\n"); + return FALSE; } - rc = TRUE; -cleanup: - if (channel->needs_lock) + + return TRUE; +} + +BOOL +visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg) +{ + BOOL rc; + + if (channel->needs_lock) { + spin_lock(&channel->insert_lock); + rc = signalinsert_inner(channel, queue, msg); spin_unlock(&channel->insert_lock); + } else { + rc = signalinsert_inner(channel, queue, msg); + } return rc; } -- cgit v0.10.2 From 1007c692264536d80ad61c1584670583c687652c Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Wed, 28 Jan 2015 12:00:22 +0200 Subject: staging: rtl8712: remove useless printing line This patch removes an unneeded call to printk. Signed-off-by: Heba Aamer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 7d0d171..f1fd7e8 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -366,7 +366,6 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, struct net_device *pnetdev; struct usb_device *udev; - printk(KERN_INFO "r8712u: Staging version\n"); /* In this probe function, O.S. will provide the usb interface pointer * to driver. We have to increase the reference count of the usb device * structure by using the usb_get_dev function. -- cgit v0.10.2 From 0137f1a019952f955f4050495be6725a5f92eb5b Mon Sep 17 00:00:00 2001 From: Kumar Amit Mehta Date: Mon, 26 Jan 2015 16:39:14 +0100 Subject: staging: rtl8188eu: core: rtw_wlan_util.c: Fix for NULL dereference In rtw_check_bcn_info(), check the return value of kzalloc() before dereferencing it, to avoid NULL pointer dereference. Signed-off-by: Kumar Amit Mehta Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 3e9b6e9..a3ffc69 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -931,6 +931,8 @@ int rtw_check_bcn_info(struct adapter *Adapter, u8 *pframe, u32 packet_len) } bssid = kzalloc(sizeof(struct wlan_bssid_ex), GFP_ATOMIC); + if (!bssid) + return _FAIL; subtype = GetFrameSubType(pframe) >> 4; -- cgit v0.10.2 From e1da1d573f67d11c2f80ffaf38d3cdd3fee97d4b Mon Sep 17 00:00:00 2001 From: Lorenzo Stoakes Date: Sat, 24 Jan 2015 15:45:21 +0000 Subject: staging: rtl8192u: fix comments This patch fixes errors raised by checkpatch.pl relating to use of C99 comments in r8192U_dm.c, and cleans up existing ANSI C comments. Signed-off-by: Lorenzo Stoakes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index b3b508c..6112c7d 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -21,9 +21,7 @@ Major Change History: #include "r8190_rtl8256.h" #include "r819xU_cmdpkt.h" /*---------------------------Define Local Constant---------------------------*/ -// -// Indicate different AP vendor for IOT issue. -// +/* Indicate different AP vendor for IOT issue. */ static u32 edca_setting_DL[HT_IOT_PEER_MAX] = { 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0xa44f, 0x5ea44f}; static u32 edca_setting_UL[HT_IOT_PEER_MAX] = @@ -36,11 +34,11 @@ static u32 edca_setting_UL[HT_IOT_PEER_MAX] = /*------------------------Define global variable-----------------------------*/ -// Debug variable ? +/* Debug variable ? */ dig_t dm_digtable; -// Store current software write register content for MAC PHY. +/* Store current software write register content for MAC PHY. */ u8 dm_shadow[16][256] = {{0}}; -// For Dynamic Rx Path Selection by Signal Strength +/* For Dynamic Rx Path Selection by Signal Strength */ DRxPathSel DM_RxPathSelTable; /*------------------------Define global variable-----------------------------*/ @@ -56,24 +54,24 @@ extern void dm_check_fsync(struct net_device *dev); /*---------------------Define local function prototype-----------------------*/ -// DM --> Rate Adaptive +/* DM --> Rate Adaptive */ static void dm_check_rate_adaptive(struct net_device *dev); -// DM --> Bandwidth switch +/* DM --> Bandwidth switch */ static void dm_init_bandwidth_autoswitch(struct net_device *dev); static void dm_bandwidth_autoswitch(struct net_device *dev); -// DM --> TX power control -//static void dm_initialize_txpower_tracking(struct net_device *dev); +/* DM --> TX power control */ +/*static void dm_initialize_txpower_tracking(struct net_device *dev);*/ static void dm_check_txpower_tracking(struct net_device *dev); -//static void dm_txpower_reset_recovery(struct net_device *dev); +/*static void dm_txpower_reset_recovery(struct net_device *dev);*/ -// DM --> Dynamic Init Gain by RSSI +/* DM --> Dynamic Init Gain by RSSI */ static void dm_dig_init(struct net_device *dev); static void dm_ctrl_initgain_byrssi(struct net_device *dev); static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev); @@ -84,61 +82,61 @@ static void dm_pd_th(struct net_device *dev); static void dm_cs_ratio(struct net_device *dev); static void dm_init_ctstoself(struct net_device *dev); -// DM --> EDCA turbo mode control +/* DM --> EDCA turbo mode control */ static void dm_check_edca_turbo(struct net_device *dev); -//static void dm_gpio_change_rf(struct net_device *dev); -// DM --> Check PBC +/*static void dm_gpio_change_rf(struct net_device *dev);*/ +/* DM --> Check PBC */ static void dm_check_pbc_gpio(struct net_device *dev); -// DM --> Check current RX RF path state +/* DM --> Check current RX RF path state */ static void dm_check_rx_path_selection(struct net_device *dev); static void dm_init_rxpath_selection(struct net_device *dev); static void dm_rxpath_sel_byrssi(struct net_device *dev); -// DM --> Fsync for broadcom ap +/* DM --> Fsync for broadcom ap */ static void dm_init_fsync(struct net_device *dev); static void dm_deInit_fsync(struct net_device *dev); -//Added by vivi, 20080522 +/* Added by vivi, 20080522 */ static void dm_check_txrateandretrycount(struct net_device *dev); /*---------------------Define local function prototype-----------------------*/ -/*---------------------Define of Tx Power Control For Near/Far Range --------*/ //Add by Jacken 2008/02/18 +/*---------------------Define of Tx Power Control For Near/Far Range --------*/ /*Add by Jacken 2008/02/18 */ static void dm_init_dynamic_txpower(struct net_device *dev); static void dm_dynamic_txpower(struct net_device *dev); -// DM --> For rate adaptive and DIG, we must send RSSI to firmware +/* DM --> For rate adaptive and DIG, we must send RSSI to firmware */ static void dm_send_rssi_tofw(struct net_device *dev); static void dm_ctstoself(struct net_device *dev); /*---------------------------Define function prototype------------------------*/ -//================================================================================ -// HW Dynamic mechanism interface. -//================================================================================ - -// -// Description: -// Prepare SW resource for HW dynamic mechanism. -// -// Assumption: -// This function is only invoked at driver intialization once. -// -// +/* + * ================================================================================ + * HW Dynamic mechanism interface. + * ================================================================================ + * + * + * Description: + * Prepare SW resource for HW dynamic mechanism. + * + * Assumption: + * This function is only invoked at driver intialization once. + */ void init_hal_dm(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - // Undecorated Smoothed Signal Strength, it can utilized to dynamic mechanism. + /* Undecorated Smoothed Signal Strength, it can utilized to dynamic mechanism. */ priv->undecorated_smoothed_pwdb = -1; - //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. + /* Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. */ dm_init_dynamic_txpower(dev); init_rate_adaptive(dev); - //dm_initialize_txpower_tracking(dev); + /*dm_initialize_txpower_tracking(dev);*/ dm_dig_init(dev); dm_init_edca_turbo(dev); dm_init_bandwidth_autoswitch(dev); @@ -146,7 +144,7 @@ void init_hal_dm(struct net_device *dev) dm_init_rxpath_selection(dev); dm_init_ctstoself(dev); -} // InitHalDm +} /* InitHalDm */ void deinit_hal_dm(struct net_device *dev) { @@ -208,16 +206,16 @@ void dm_CheckRxAggregation(struct net_device *dev) { lastTxOkCnt = priv->stats.txbytesunicast; lastRxOkCnt = priv->stats.rxbytesunicast; -} // dm_CheckEdcaTurbo +} /* dm_CheckEdcaTurbo */ #endif void hal_dm_watchdog(struct net_device *dev) { - //struct r8192_priv *priv = ieee80211_priv(dev); + /*struct r8192_priv *priv = ieee80211_priv(dev);*/ - //static u8 previous_bssid[6] ={0}; + /*static u8 previous_bssid[6] ={0};*/ /*Add by amy 2008/05/15 ,porting from windows code.*/ dm_check_rate_adaptive(dev); @@ -230,22 +228,22 @@ void hal_dm_watchdog(struct net_device *dev) dm_check_rx_path_selection(dev); dm_check_fsync(dev); - // Add by amy 2008-05-15 porting from windows code. + /* Add by amy 2008-05-15 porting from windows code. */ dm_check_pbc_gpio(dev); dm_send_rssi_tofw(dev); dm_ctstoself(dev); #ifdef USB_RX_AGGREGATION_SUPPORT dm_CheckRxAggregation(dev); #endif -} //HalDmWatchDog +} /* HalDmWatchDog */ /* - * Decide Rate Adaptive Set according to distance (signal strength) - * 01/11/2008 MHC Modify input arguments and RATR table level. - * 01/16/2008 MHC RF_Type is assigned in ReadAdapterInfo(). We must call - * the function after making sure RF_Type. - */ + * Decide Rate Adaptive Set according to distance (signal strength) + * 01/11/2008 MHC Modify input arguments and RATR table level. + * 01/16/2008 MHC RF_Type is assigned in ReadAdapterInfo(). We must call + * the function after making sure RF_Type. + */ void init_rate_adaptive(struct net_device *dev) { @@ -270,14 +268,16 @@ void init_rate_adaptive(struct net_device *dev) if (priv->rf_type == RF_2T4R) { - // 07/10/08 MH Modify for RA smooth scheme. - /* 2008/01/11 MH Modify 2T RATR table for different RSSI. 080515 porting by amy from windows code.*/ + /* + * 07/10/08 MH Modify for RA smooth scheme. + * 2008/01/11 MH Modify 2T RATR table for different RSSI. 080515 porting by amy from windows code. + */ pra->upper_rssi_threshold_ratr = 0x8f0f0000; pra->middle_rssi_threshold_ratr = 0x8f0ff000; pra->low_rssi_threshold_ratr = 0x8f0ff001; pra->low_rssi_threshold_ratr_40M = 0x8f0ff005; pra->low_rssi_threshold_ratr_20M = 0x8f0ff001; - pra->ping_rssi_ratr = 0x0000000d;//cosa add for test + pra->ping_rssi_ratr = 0x0000000d;/* cosa add for test */ } else if (priv->rf_type == RF_1T2R) { @@ -286,10 +286,10 @@ void init_rate_adaptive(struct net_device *dev) pra->low_rssi_threshold_ratr = 0x000ff001; pra->low_rssi_threshold_ratr_40M = 0x000ff005; pra->low_rssi_threshold_ratr_20M = 0x000ff001; - pra->ping_rssi_ratr = 0x0000000d;//cosa add for test + pra->ping_rssi_ratr = 0x0000000d;/* cosa add for test */ } -} // InitRateAdaptive +} /* InitRateAdaptive */ /*----------------------------------------------------------------------------- @@ -325,21 +325,19 @@ static void dm_check_rate_adaptive(struct net_device *dev) return; } - if(pra->rate_adaptive_disabled)//this variable is set by ioctl. + if(pra->rate_adaptive_disabled) /* this variable is set by ioctl. */ return; - // TODO: Only 11n mode is implemented currently, + /* TODO: Only 11n mode is implemented currently, */ if(!(priv->ieee80211->mode == WIRELESS_MODE_N_24G || priv->ieee80211->mode == WIRELESS_MODE_N_5G)) return; if(priv->ieee80211->state == IEEE80211_LINKED) { - // RT_TRACE(COMP_RATE, "dm_CheckRateAdaptive(): \t"); + /*RT_TRACE(COMP_RATE, "dm_CheckRateAdaptive(): \t");*/ - // - // Check whether Short GI is enabled - // + /* Check whether Short GI is enabled */ bshort_gi_enabled = (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) || (!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz); @@ -360,7 +358,7 @@ static void dm_check_rate_adaptive(struct net_device *dev) pra->low_rssi_threshold_ratr = (pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; } - //cosa add for test + /* cosa add for test */ pra->ping_rssi_ratr = (pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; @@ -387,56 +385,56 @@ static void dm_check_rate_adaptive(struct net_device *dev) (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M); } - //DbgPrint("[DM] THresh H/L=%d/%d\n\r", RATR.HighRSSIThreshForRA, RATR.LowRSSIThreshForRA); + /*DbgPrint("[DM] THresh H/L=%d/%d\n\r", RATR.HighRSSIThreshForRA, RATR.LowRSSIThreshForRA);*/ if(priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA) { - //DbgPrint("[DM] RSSI=%d STA=HIGH\n\r", pHalData->UndecoratedSmoothedPWDB); + /*DbgPrint("[DM] RSSI=%d STA=HIGH\n\r", pHalData->UndecoratedSmoothedPWDB);*/ pra->ratr_state = DM_RATR_STA_HIGH; targetRATR = pra->upper_rssi_threshold_ratr; }else if(priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA) { - //DbgPrint("[DM] RSSI=%d STA=Middle\n\r", pHalData->UndecoratedSmoothedPWDB); + /*DbgPrint("[DM] RSSI=%d STA=Middle\n\r", pHalData->UndecoratedSmoothedPWDB);*/ pra->ratr_state = DM_RATR_STA_MIDDLE; targetRATR = pra->middle_rssi_threshold_ratr; }else { - //DbgPrint("[DM] RSSI=%d STA=LOW\n\r", pHalData->UndecoratedSmoothedPWDB); + /*DbgPrint("[DM] RSSI=%d STA=LOW\n\r", pHalData->UndecoratedSmoothedPWDB);*/ pra->ratr_state = DM_RATR_STA_LOW; targetRATR = pra->low_rssi_threshold_ratr; } - //cosa add for test + /* cosa add for test */ if(pra->ping_rssi_enable) { - //pHalData->UndecoratedSmoothedPWDB = 19; + /*pHalData->UndecoratedSmoothedPWDB = 19;*/ if(priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5)) { if((priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) || ping_rssi_state) { - //DbgPrint("TestRSSI = %d, set RATR to 0x%x \n", pHalData->UndecoratedSmoothedPWDB, pRA->TestRSSIRATR); + /*DbgPrint("TestRSSI = %d, set RATR to 0x%x \n", pHalData->UndecoratedSmoothedPWDB, pRA->TestRSSIRATR);*/ pra->ratr_state = DM_RATR_STA_LOW; targetRATR = pra->ping_rssi_ratr; ping_rssi_state = 1; } - //else - // DbgPrint("TestRSSI is between the range. \n"); + /*else + DbgPrint("TestRSSI is between the range. \n");*/ } else { - //DbgPrint("TestRSSI Recover to 0x%x \n", targetRATR); + /*DbgPrint("TestRSSI Recover to 0x%x \n", targetRATR);*/ ping_rssi_state = 0; } } - // 2008.04.01 - // For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7. + /* + * 2008.04.01 + * For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7. + */ if(priv->ieee80211->GetHalfNmodeSupportByAPsHandler(dev)) targetRATR &= 0xf00fffff; - // - // Check whether updating of RATR0 is required - // + /* Check whether updating of RATR0 is required */ read_nic_dword(dev, RATR0, ¤tRATR); if(targetRATR != currentRATR) { @@ -459,7 +457,7 @@ static void dm_check_rate_adaptive(struct net_device *dev) pra->ratr_state = DM_RATR_STA_MAX; } -} // dm_CheckRateAdaptive +} /* dm_CheckRateAdaptive */ static void dm_init_bandwidth_autoswitch(struct net_device *dev) @@ -471,7 +469,7 @@ static void dm_init_bandwidth_autoswitch(struct net_device *dev) priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false; priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable = false; -} // dm_init_bandwidth_autoswitch +} /* dm_init_bandwidth_autoswitch */ static void dm_bandwidth_autoswitch(struct net_device *dev) @@ -481,66 +479,66 @@ static void dm_bandwidth_autoswitch(struct net_device *dev) if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||!priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable){ return; } - if(priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false){//If send packets in 40 Mhz in 20/40 + if(priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false){/* If send packets in 40 Mhz in 20/40 */ if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz) priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true; - }else{//in force send packets in 20 Mhz in 20/40 + }else{/* in force send packets in 20 Mhz in 20/40 */ if(priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz) priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false; } -} // dm_BandwidthAutoSwitch +} /* dm_BandwidthAutoSwitch */ -//OFDM default at 0db, index=6. +/* OFDM default at 0db, index=6. */ static u32 OFDMSwingTable[OFDM_Table_Length] = { - 0x7f8001fe, // 0, +6db - 0x71c001c7, // 1, +5db - 0x65400195, // 2, +4db - 0x5a400169, // 3, +3db - 0x50800142, // 4, +2db - 0x47c0011f, // 5, +1db - 0x40000100, // 6, +0db ===> default, upper for higher temperature, lower for low temperature - 0x390000e4, // 7, -1db - 0x32c000cb, // 8, -2db - 0x2d4000b5, // 9, -3db - 0x288000a2, // 10, -4db - 0x24000090, // 11, -5db - 0x20000080, // 12, -6db - 0x1c800072, // 13, -7db - 0x19800066, // 14, -8db - 0x26c0005b, // 15, -9db - 0x24400051, // 16, -10db - 0x12000048, // 17, -11db - 0x10000040 // 18, -12db + 0x7f8001fe, /* 0, +6db */ + 0x71c001c7, /* 1, +5db */ + 0x65400195, /* 2, +4db */ + 0x5a400169, /* 3, +3db */ + 0x50800142, /* 4, +2db */ + 0x47c0011f, /* 5, +1db */ + 0x40000100, /* 6, +0db ===> default, upper for higher temperature, lower for low temperature */ + 0x390000e4, /* 7, -1db */ + 0x32c000cb, /* 8, -2db */ + 0x2d4000b5, /* 9, -3db */ + 0x288000a2, /* 10, -4db */ + 0x24000090, /* 11, -5db */ + 0x20000080, /* 12, -6db */ + 0x1c800072, /* 13, -7db */ + 0x19800066, /* 14, -8db */ + 0x26c0005b, /* 15, -9db */ + 0x24400051, /* 16, -10db */ + 0x12000048, /* 17, -11db */ + 0x10000040 /* 18, -12db */ }; static u8 CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, // 0, +0db ===> CCK40M default - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, // 1, -1db - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, // 2, -2db - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, // 3, -3db - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, // 4, -4db - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, // 5, -5db - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, // 6, -6db ===> CCK20M default - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, // 7, -7db - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, // 8, -8db - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, // 9, -9db - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, // 10, -10db - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01} // 11, -11db + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0db ===> CCK40M default */ + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 1, -1db */ + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 2, -2db */ + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 3, -3db */ + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 4, -4db */ + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 5, -5db */ + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 6, -6db ===> CCK20M default */ + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 7, -7db */ + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 8, -8db */ + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 9, -9db */ + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 10, -10db */ + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01} /* 11, -11db */ }; static u8 CCKSwingTable_Ch14[CCK_Table_length][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, // 0, +0db ===> CCK40M default - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, // 1, -1db - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, // 2, -2db - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, // 3, -3db - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, // 4, -4db - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, // 5, -5db - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, // 6, -6db ===> CCK20M default - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, // 7, -7db - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, // 8, -8db - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, // 9, -9db - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, // 10, -10db - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00} // 11, -11db + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0db ===> CCK40M default */ + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 1, -1db */ + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 2, -2db */ + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 3, -3db */ + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 4, -4db */ + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 5, -5db */ + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 6, -6db ===> CCK20M default */ + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 7, -7db */ + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 8, -8db */ + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 9, -9db */ + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 10, -10db */ + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00} /* 11, -11db */ }; static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) @@ -554,7 +552,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) u32 Value; u8 Pwr_Flag; u16 Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver=0; - //RT_STATUS rtStatus = RT_STATUS_SUCCESS; + /*RT_STATUS rtStatus = RT_STATUS_SUCCESS;*/ bool rtStatus = true; u32 delta=0; @@ -570,8 +568,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) RT_TRACE(COMP_POWER_TRACKING, "powerlevelOFDM24G = %x\n", powerlevelOFDM24G); for(j = 0; j<=30; j++) -{ //fill tx_cmd - +{ /* fill tx_cmd */ tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING; tx_cmd.Length = 4; tx_cmd.Value = Value; @@ -581,7 +578,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n"); } mdelay(1); - //DbgPrint("hi, vivi, strange\n"); + /*DbgPrint("hi, vivi, strange\n");*/ for(i = 0;i <= 30; i++) { read_nic_byte(dev, 0x1ba, &Pwr_Flag); @@ -607,7 +604,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]); } - //check if the report value is right + /* check if the report value is right */ for(k = 0;k < 5; k++) { if(tmp_report[k] <= 20) @@ -636,8 +633,8 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) TSSI_13dBm = priv->TSSI_13dBm; RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm); - //if(abs(Avg_TSSI_Meas_from_driver - TSSI_13dBm) <= E_FOR_TX_POWER_TRACK) - // For MacOS-compatible + /*if(abs(Avg_TSSI_Meas_from_driver - TSSI_13dBm) <= E_FOR_TX_POWER_TRACK)*/ + /* For MacOS-compatible */ if(Avg_TSSI_Meas_from_driver > TSSI_13dBm) delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm; else @@ -739,9 +736,9 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) if(!priv->btxpower_trackingInit) { - //Query OFDM default setting + /* Query OFDM default setting */ tmpRegA= rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord); - for(i=0; ibtxpower_trackingInit = TRUE; - //pHalData->TXPowercount = 0; + /*pHalData->TXPowercount = 0;*/ return; } - //========================== - // this is only for test, should be masked - //========================== + /* + * ========================== + * this is only for test, should be masked + * ========================== + */ - // read and filter out unreasonable value - tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078); // 0x12: RF Reg[10:7] + /* read and filter out unreasonable value */ + tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078); /* 0x12: RF Reg[10:7] */ RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d \n", tmpRegA); if(tmpRegA < 3 || tmpRegA > 13) return; - if(tmpRegA >= 12) // if over 12, TP will be bad when high temperature + if(tmpRegA >= 12) /* if over 12, TP will be bad when high temperature */ tmpRegA = 12; RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d \n", tmpRegA); - priv->ThermalMeter[0] = ThermalMeterVal; //We use fixed value by Bryant's suggestion - priv->ThermalMeter[1] = ThermalMeterVal; //We use fixed value by Bryant's suggestion + priv->ThermalMeter[0] = ThermalMeterVal; /* We use fixed value by Bryant's suggestion */ + priv->ThermalMeter[1] = ThermalMeterVal; /* We use fixed value by Bryant's suggestion */ - //Get current RF-A temperature index - if(priv->ThermalMeter[0] >= (u8)tmpRegA) //lower temperature + /* Get current RF-A temperature index */ + if(priv->ThermalMeter[0] >= (u8)tmpRegA) /* lower temperature */ { tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA); tmpCCK40Mindex = tmpCCK20Mindex - 6; @@ -798,16 +797,16 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) else { tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]); - if(tmpval >= 6) // higher temperature - tmpOFDMindex = tmpCCK20Mindex = 0; // max to +6dB + if(tmpval >= 6) /* higher temperature */ + tmpOFDMindex = tmpCCK20Mindex = 0; /* max to +6dB */ else tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval; tmpCCK40Mindex = 0; } - //DbgPrint("%ddb, tmpOFDMindex = %d, tmpCCK20Mindex = %d, tmpCCK40Mindex = %d", - //((u1Byte)tmpRegA - pHalData->ThermalMeter[0]), - //tmpOFDMindex, tmpCCK20Mindex, tmpCCK40Mindex); - if(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) //40M + /*DbgPrint("%ddb, tmpOFDMindex = %d, tmpCCK20Mindex = %d, tmpCCK40Mindex = %d", + ((u1Byte)tmpRegA - pHalData->ThermalMeter[0]), + tmpOFDMindex, tmpCCK20Mindex, tmpCCK40Mindex);*/ + if(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) /* 40M */ tmpCCKindex = tmpCCK40Mindex; else tmpCCKindex = tmpCCK20Mindex; @@ -831,7 +830,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) if(CCKSwingNeedUpdate) { - //DbgPrint("Update CCK Swing, CCK_index = %d\n", pHalData->CCK_index); + /*DbgPrint("Update CCK Swing, CCK_index = %d\n", pHalData->CCK_index);*/ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } if(priv->OFDM_index != tmpOFDMindex) @@ -862,7 +861,7 @@ static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev) struct r8192_priv *priv = ieee80211_priv(dev); - //Initial the Tx BB index and mapping value + /* Initial the Tx BB index and mapping value */ priv->txbbgain_table[0].txbb_iq_amplifygain = 12; priv->txbbgain_table[0].txbbgain_value=0x7f8001fe; priv->txbbgain_table[1].txbb_iq_amplifygain = 11; @@ -938,8 +937,10 @@ static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev) priv->txbbgain_table[36].txbb_iq_amplifygain = -24; priv->txbbgain_table[36].txbbgain_value=0x10000040; - //ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29 - //This Table is for CH1~CH13 + /* + * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29 + * This Table is for CH1~CH13 + */ priv->cck_txbbgain_table[0].ccktxbb_valuearray[0] = 0x36; priv->cck_txbbgain_table[0].ccktxbb_valuearray[1] = 0x35; priv->cck_txbbgain_table[0].ccktxbb_valuearray[2] = 0x2e; @@ -1147,8 +1148,10 @@ static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev) priv->cck_txbbgain_table[22].ccktxbb_valuearray[6] = 0x03; priv->cck_txbbgain_table[22].ccktxbb_valuearray[7] = 0x01; - //ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29 - //This Table is for CH14 + /* + * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29 + * This Table is for CH14 + */ priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[0] = 0x36; priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[1] = 0x35; priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[2] = 0x2e; @@ -1366,9 +1369,11 @@ static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - // Tx Power tracking by Thermal Meter requires Firmware R/W 3-wire. This mechanism - // can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w - // 3-wire by driver causes RF to go into a wrong state. + /* + * Tx Power tracking by Thermal Meter requires Firmware R/W 3-wire. This mechanism + * can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w + * 3-wire by driver causes RF to go into a wrong state. + */ if(priv->ieee80211->FwRWRF) priv->btxpower_tracking = TRUE; else @@ -1385,7 +1390,7 @@ void dm_initialize_txpower_tracking(struct net_device *dev) dm_InitializeTXPowerTracking_TSSI(dev); else dm_InitializeTXPowerTracking_ThermalMeter(dev); -}// dm_InitializeTXPowerTracking +} /* dm_InitializeTXPowerTracking */ static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev) @@ -1411,7 +1416,7 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); static u8 TM_Trigger; - //DbgPrint("dm_CheckTXPowerTracking() \n"); + /*DbgPrint("dm_CheckTXPowerTracking() \n");*/ if(!priv->btxpower_tracking) return; else @@ -1425,9 +1430,11 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) if(!TM_Trigger) { - //Attention!! You have to write all 12bits of data to RF, or it may cause RF to crash - //actually write reg0x02 bit1=0, then bit1=1. - //DbgPrint("Trigger ThermalMeter, write RF reg0x2 = 0x4d to 0x4f\n"); + /* + * Attention!! You have to write all 12bits of data to RF, or it may cause RF to crash + * actually write reg0x02 bit1=0, then bit1=1. + * DbgPrint("Trigger ThermalMeter, write RF reg0x2 = 0x4d to 0x4f\n"); + */ rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); @@ -1437,7 +1444,7 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) } else { - //DbgPrint("Schedule TxPowerTrackingWorkItem\n"); + /*DbgPrint("Schedule TxPowerTrackingWorkItem\n");*/ queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0); TM_Trigger = 0; } @@ -1447,7 +1454,7 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) static void dm_check_txpower_tracking(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - //static u32 tx_power_track_counter = 0; + /*static u32 tx_power_track_counter = 0;*/ #ifdef RTL8190P dm_CheckTXPowerTracking_TSSI(dev); @@ -1458,28 +1465,28 @@ static void dm_check_txpower_tracking(struct net_device *dev) dm_CheckTXPowerTracking_ThermalMeter(dev); #endif -} // dm_CheckTXPowerTracking +} /* dm_CheckTXPowerTracking */ static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool bInCH14) { u32 TempVal; struct r8192_priv *priv = ieee80211_priv(dev); - //Write 0xa22 0xa23 + /* Write 0xa22 0xa23 */ TempVal = 0; if(!bInCH14){ - //Write 0xa22 0xa23 + /* Write 0xa22 0xa23 */ TempVal = priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[0] + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8) ; rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); - //Write 0xa24 ~ 0xa27 + /* Write 0xa24 ~ 0xa27 */ TempVal = priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[2] + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[3]<<8) + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[4]<<16)+ (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[5]<<24); rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); - //Write 0xa28 0xa29 + /* Write 0xa28 0xa29 */ TempVal = priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[6] + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8) ; @@ -1491,13 +1498,13 @@ static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool bInCH14) (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8) ; rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); - //Write 0xa24 ~ 0xa27 + /* Write 0xa24 ~ 0xa27 */ TempVal = priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[2] + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[3]<<8) + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[4]<<16)+ (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[5]<<24); rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); - //Write 0xa28 0xa29 + /* Write 0xa28 0xa29 */ TempVal = priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[6] + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8) ; @@ -1515,13 +1522,13 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH TempVal = 0; if(!bInCH14) { - //Write 0xa22 0xa23 + /* Write 0xa22 0xa23 */ TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8) ; rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter1, TempVal); - //Write 0xa24 ~ 0xa27 + /* Write 0xa24 ~ 0xa27 */ TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][2] + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][3]<<8) + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][4]<<16)+ @@ -1529,7 +1536,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter2, TempVal); - //Write 0xa28 0xa29 + /* Write 0xa28 0xa29 */ TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8) ; @@ -1539,15 +1546,15 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH } else { -// priv->CCKTxPowerAdjustCntNotCh14++; //cosa add for debug. - //Write 0xa22 0xa23 + /*priv->CCKTxPowerAdjustCntNotCh14++; cosa add for debug.*/ + /* Write 0xa22 0xa23 */ TempVal = CCKSwingTable_Ch14[priv->CCK_index][0] + (CCKSwingTable_Ch14[priv->CCK_index][1]<<8) ; rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter1, TempVal); - //Write 0xa24 ~ 0xa27 + /* Write 0xa24 ~ 0xa27 */ TempVal = CCKSwingTable_Ch14[priv->CCK_index][2] + (CCKSwingTable_Ch14[priv->CCK_index][3]<<8) + (CCKSwingTable_Ch14[priv->CCK_index][4]<<16)+ @@ -1555,7 +1562,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter2, TempVal); - //Write 0xa28 0xa29 + /* Write 0xa28 0xa29 */ TempVal = CCKSwingTable_Ch14[priv->CCK_index][6] + (CCKSwingTable_Ch14[priv->CCK_index][7]<<8) ; @@ -1568,7 +1575,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH void dm_cck_txpower_adjust(struct net_device *dev, bool binch14) -{ // dm_CCKTxPowerAdjust +{ /* dm_CCKTxPowerAdjust */ struct r8192_priv *priv = ieee80211_priv(dev); if(priv->bDcut == TRUE) @@ -1598,7 +1605,7 @@ static void dm_txpower_reset_recovery( RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFC_txPowerTrackingIndex is %x\n",priv->rfc_txpowertrackingindex); RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF C I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbb_iq_amplifygain); -} // dm_TXPowerResetRecovery +} /* dm_TXPowerResetRecovery */ void dm_restore_dynamic_mechanism_state(struct net_device *dev) { @@ -1611,12 +1618,10 @@ void dm_restore_dynamic_mechanism_state(struct net_device *dev) return; } - // - // Restore previous state for rate adaptive - // + /* Restore previous state for rate adaptive */ if(priv->rate_adaptive.rate_adaptive_disabled) return; - // TODO: Only 11n mode is implemented currently, + /* TODO: Only 11n mode is implemented currently, */ if(!(priv->ieee80211->mode==WIRELESS_MODE_N_24G || priv->ieee80211->mode==WIRELESS_MODE_N_5G)) return; @@ -1624,38 +1629,36 @@ void dm_restore_dynamic_mechanism_state(struct net_device *dev) /* 2007/11/15 MH Copy from 8190PCI. */ u32 ratr_value; ratr_value = reg_ratr; - if(priv->rf_type == RF_1T2R) // 1T2R, Spatial Stream 2 should be disabled + if(priv->rf_type == RF_1T2R) /* 1T2R, Spatial Stream 2 should be disabled */ { ratr_value &= ~(RATE_ALL_OFDM_2SS); - //DbgPrint("HW_VAR_TATR_0 from 0x%x ==> 0x%x\n", ((pu4Byte)(val))[0], ratr_value); + /*DbgPrint("HW_VAR_TATR_0 from 0x%x ==> 0x%x\n", ((pu4Byte)(val))[0], ratr_value);*/ } - //DbgPrint("set HW_VAR_TATR_0 = 0x%x\n", ratr_value); - //cosa PlatformEFIOWrite4Byte(Adapter, RATR0, ((pu4Byte)(val))[0]); + /*DbgPrint("set HW_VAR_TATR_0 = 0x%x\n", ratr_value);*/ + /*cosa PlatformEFIOWrite4Byte(Adapter, RATR0, ((pu4Byte)(val))[0]);*/ write_nic_dword(dev, RATR0, ratr_value); write_nic_byte(dev, UFWP, 1); } - //Restore TX Power Tracking Index + /* Restore TX Power Tracking Index */ if (priv->btxpower_trackingInit && priv->btxpower_tracking) dm_txpower_reset_recovery(dev); - // - //Restore BB Initial Gain - // + /* Restore BB Initial Gain */ dm_bb_initialgain_restore(dev); -} // DM_RestoreDynamicMechanismState +} /* DM_RestoreDynamicMechanismState */ static void dm_bb_initialgain_restore(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - u32 bit_mask = 0x7f; //Bit0~ Bit6 + u32 bit_mask = 0x7f; /* Bit0~ Bit6 */ if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) return; - //Disable Initial Gain - //PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800); - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + /* Disable Initial Gain */ + /*PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800);*/ + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); /* Only clear byte 1 and rewrite. */ rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bit_mask, (u32)priv->initgain_backup.xaagccore1); rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bit_mask, (u32)priv->initgain_backup.xbagccore1); rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, bit_mask, (u32)priv->initgain_backup.xcagccore1); @@ -1668,36 +1671,36 @@ static void dm_bb_initialgain_restore(struct net_device *dev) RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc60 is %x\n",priv->initgain_backup.xcagccore1); RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc68 is %x\n",priv->initgain_backup.xdagccore1); RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n",priv->initgain_backup.cca); - //Enable Initial Gain - //PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x100); - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); // Only clear byte 1 and rewrite. + /* Enable Initial Gain */ + /*PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x100);*/ + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); /* Only clear byte 1 and rewrite. */ -} // dm_BBInitialGainRestore +} /* dm_BBInitialGainRestore */ void dm_backup_dynamic_mechanism_state(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - // Fsync to avoid reset + /* Fsync to avoid reset */ priv->bswitch_fsync = false; priv->bfsync_processing = false; - //Backup BB InitialGain + /* Backup BB InitialGain */ dm_bb_initialgain_backup(dev); -} // DM_BackupDynamicMechanismState +} /* DM_BackupDynamicMechanismState */ static void dm_bb_initialgain_backup(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - u32 bit_mask = bMaskByte0; //Bit0~ Bit6 + u32 bit_mask = bMaskByte0; /* Bit0~ Bit6 */ if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) return; - //PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800); - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + /*PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800);*/ + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); /* Only clear byte 1 and rewrite. */ priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bit_mask); priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bit_mask); priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bit_mask); @@ -1711,7 +1714,7 @@ static void dm_bb_initialgain_backup(struct net_device *dev) RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc68 is %x\n",priv->initgain_backup.xdagccore1); RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xa0a is %x\n",priv->initgain_backup.cca); -} // dm_BBInitialGainBakcup +} /* dm_BBInitialGainBakcup */ #endif /*----------------------------------------------------------------------------- @@ -1822,7 +1825,7 @@ static void dm_dig_init(struct net_device *dev) /* 2007/10/05 MH Disable DIG scheme now. Not tested. */ dm_digtable.dig_enable_flag = true; dm_digtable.dig_algorithm = DIG_ALGO_BY_RSSI; - dm_digtable.dbg_mode = DM_DBG_OFF; //off=by real rssi value, on=by DM_DigTable.Rssi_val for new dig + dm_digtable.dbg_mode = DM_DBG_OFF; /* off=by real rssi value, on=by DM_DigTable.Rssi_val for new dig */ dm_digtable.dig_algorithm_switch = 0; /* 2007/10/04 MH Define init gain threshold. */ @@ -1836,7 +1839,7 @@ static void dm_dig_init(struct net_device *dev) dm_digtable.rssi_high_power_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW; dm_digtable.rssi_high_power_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH; - dm_digtable.rssi_val = 50; //for new dig debug rssi value + dm_digtable.rssi_val = 50; /* for new dig debug rssi value */ dm_digtable.backoff_val = DM_DIG_BACKOFF; dm_digtable.rx_gain_range_max = DM_DIG_MAX; if(priv->CustomerID == RT_CID_819x_Netcore) @@ -1874,7 +1877,7 @@ static void dm_ctrl_initgain_byrssi(struct net_device *dev) dm_ctrl_initgain_byrssi_by_fwfalse_alarm(dev); else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) dm_ctrl_initgain_byrssi_by_driverrssi(dev); -// ; + /* ; */ else return; } @@ -1890,15 +1893,16 @@ static void dm_ctrl_initgain_byrssi_by_driverrssi( if (dm_digtable.dig_enable_flag == false) return; - //DbgPrint("Dig by Sw Rssi \n"); - if(dm_digtable.dig_algorithm_switch) // if switched algorithm, we have to disable FW Dig. + /*DbgPrint("Dig by Sw Rssi \n");*/ + if(dm_digtable.dig_algorithm_switch) /* if switched algorithm, we have to disable FW Dig. */ fw_dig = 0; - if(fw_dig <= 3) // execute several times to make sure the FW Dig is disabled - {// FW DIG Off + if(fw_dig <= 3) + { /* execute several times to make sure the FW Dig is disabled */ + /* FW DIG Off */ for(i=0; i<3; i++) - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); /* Only clear byte 1 and rewrite. */ fw_dig++; - dm_digtable.dig_state = DM_STA_DIG_OFF; //fw dig off. + dm_digtable.dig_state = DM_STA_DIG_OFF; /* fw dig off. */ } if(priv->ieee80211->state == IEEE80211_LINKED) @@ -1906,12 +1910,12 @@ static void dm_ctrl_initgain_byrssi_by_driverrssi( else dm_digtable.cur_connect_state = DIG_DISCONNECT; - //DbgPrint("DM_DigTable.PreConnectState = %d, DM_DigTable.CurConnectState = %d \n", - //DM_DigTable.PreConnectState, DM_DigTable.CurConnectState); + /*DbgPrint("DM_DigTable.PreConnectState = %d, DM_DigTable.CurConnectState = %d \n", + DM_DigTable.PreConnectState, DM_DigTable.CurConnectState);*/ if(dm_digtable.dbg_mode == DM_DBG_OFF) dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb; - //DbgPrint("DM_DigTable.Rssi_val = %d \n", DM_DigTable.Rssi_val); + /*DbgPrint("DM_DigTable.Rssi_val = %d \n", DM_DigTable.Rssi_val);*/ dm_initial_gain(dev); dm_pd_th(dev); dm_cs_ratio(dev); @@ -1934,23 +1938,23 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( if(dm_digtable.dig_algorithm_switch) { dm_digtable.dig_state = DM_STA_DIG_MAX; - // Fw DIG On. + /* Fw DIG On. */ for(i=0; i<3; i++) - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); // Only clear byte 1 and rewrite. + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); /* Only clear byte 1 and rewrite.*/ dm_digtable.dig_algorithm_switch = 0; } if (priv->ieee80211->state != IEEE80211_LINKED) return; - // For smooth, we can not change DIG state. + /* For smooth, we can not change DIG state. */ if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) && (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh)) { return; } - //DbgPrint("Dig by Fw False Alarm\n"); - //if (DM_DigTable.Dig_State == DM_STA_DIG_OFF) + /*DbgPrint("Dig by Fw False Alarm\n");*/ + /*if (DM_DigTable.Dig_State == DM_STA_DIG_OFF)*/ /*DbgPrint("DIG Check\n\r RSSI=%d LOW=%d HIGH=%d STATE=%d", pHalData->UndecoratedSmoothedPWDB, DM_DigTable.RssiLowThresh, DM_DigTable.RssiHighThresh, DM_DigTable.Dig_State);*/ @@ -1970,42 +1974,42 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( reset_cnt = priv->reset_count; } - // If DIG is off, DIG high power state must reset. + /* If DIG is off, DIG high power state must reset. */ dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX; dm_digtable.dig_state = DM_STA_DIG_OFF; - // 1.1 DIG Off. - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite. + /* 1.1 DIG Off. */ + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); /* Only clear byte 1 and rewrite. */ - // 1.2 Set initial gain. + /* 1.2 Set initial gain. */ write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x17); write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x17); write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x17); write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17); - // 1.3 Lower PD_TH for OFDM. + /* 1.3 Lower PD_TH for OFDM. */ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { - /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ - // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + /* + * 2008/01/11 MH 40MHZ 90/92 register are not the same. + * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + */ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(pAdapter, rOFDM0_RxDetector1, 0x40); + else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E) + else + PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x40); */ - //else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E) - - - //else - //PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x40); } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); - // 1.4 Lower CS ratio for CCK. + /* 1.4 Lower CS ratio for CCK. */ write_nic_byte(dev, 0xa0a, 0x08); - // 1.5 Higher EDCCA. - //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x325); + /* 1.5 Higher EDCCA. */ + /*PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x325);*/ return; } @@ -2031,10 +2035,12 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( } dm_digtable.dig_state = DM_STA_DIG_ON; - //DbgPrint("DIG ON\n\r"); + /*DbgPrint("DIG ON\n\r");*/ - // 2.1 Set initial gain. - // 2008/02/26 MH SD3-Jerry suggest to prevent dirty environment. + /* + * 2.1 Set initial gain. + * 2008/02/26 MH SD3-Jerry suggest to prevent dirty environment. + */ if (reset_flag == 1) { write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c); @@ -2050,33 +2056,36 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x20); } - // 2.2 Higher PD_TH for OFDM. + /* 2.2 Higher PD_TH for OFDM. */ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { - /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ - // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + /* + * 2008/01/11 MH 40MHZ 90/92 register are not the same. + * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + */ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); /* else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E) + else + PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x42); */ - //else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E) - - //else - //PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x42); } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); - // 2.3 Higher CS ratio for CCK. + /* 2.3 Higher CS ratio for CCK. */ write_nic_byte(dev, 0xa0a, 0xcd); - // 2.4 Lower EDCCA. - /* 2008/01/11 MH 90/92 series are the same. */ - //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x346); + /* + * 2.4 Lower EDCCA. + * 2008/01/11 MH 90/92 series are the same. + */ + /*PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x346);*/ - // 2.5 DIG On. - rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); // Only clear byte 1 and rewrite. + /* 2.5 DIG On. */ + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); /* Only clear byte 1 and rewrite. */ } @@ -2107,16 +2116,19 @@ static void dm_ctrl_initgain_byrssi_highpwr( struct r8192_priv *priv = ieee80211_priv(dev); static u32 reset_cnt_highpwr; - // For smooth, we can not change high power DIG state in the range. + /* For smooth, we can not change high power DIG state in the range. */ if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_high_power_lowthresh) && (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_highthresh)) { return; } - /* 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if - it is larger than a threshold and then execute the step below. */ - // 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue. + /* + * 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if + * it is larger than a threshold and then execute the step below. + * + * 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue. + */ if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh) { if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON && @@ -2125,7 +2137,7 @@ static void dm_ctrl_initgain_byrssi_highpwr( else dm_digtable.dig_highpwr_state = DM_STA_DIG_ON; - // 3.1 Higher PD_TH for OFDM for high power state. + /* 3.1 Higher PD_TH for OFDM for high power state. */ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); @@ -2149,7 +2161,7 @@ static void dm_ctrl_initgain_byrssi_highpwr( if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh && priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) { - // 3.2 Recover PD_TH for OFDM for normal power region. + /* 3.2 Recover PD_TH for OFDM for normal power region. */ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); @@ -2194,7 +2206,7 @@ static void dm_initial_gain( else dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val; } - else //current state is disconnected + else /* current state is disconnected */ { if(dm_digtable.cur_ig_value == 0) dm_digtable.cur_ig_value = priv->DefaultInitialGain[0]; @@ -2202,14 +2214,14 @@ static void dm_initial_gain( dm_digtable.cur_ig_value = dm_digtable.pre_ig_value; } } - else // disconnected -> connected or connected -> disconnected + else /* disconnected -> connected or connected -> disconnected */ { dm_digtable.cur_ig_value = priv->DefaultInitialGain[0]; dm_digtable.pre_ig_value = 0; } - //DbgPrint("DM_DigTable.CurIGValue = 0x%x, DM_DigTable.PreIGValue = 0x%x\n", DM_DigTable.CurIGValue, DM_DigTable.PreIGValue); + /*DbgPrint("DM_DigTable.CurIGValue = 0x%x, DM_DigTable.PreIGValue = 0x%x\n", DM_DigTable.CurIGValue, DM_DigTable.PreIGValue);*/ - // if silent reset happened, we should rewrite the values back + /* if silent reset happened, we should rewrite the values back */ if(priv->reset_count != reset_cnt) { force_write = 1; @@ -2225,8 +2237,8 @@ static void dm_initial_gain( || !initialized || force_write) { initial_gain = (u8)dm_digtable.cur_ig_value; - //DbgPrint("Write initial gain = 0x%x\n", initial_gain); - // Set initial gain. + /*DbgPrint("Write initial gain = 0x%x\n", initial_gain);*/ + /* Set initial gain. */ write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain); write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain); write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain); @@ -2270,12 +2282,12 @@ static void dm_pd_th( dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; } } - else // disconnected -> connected or connected -> disconnected + else /* disconnected -> connected or connected -> disconnected */ { dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; } - // if silent reset happened, we should rewrite the values back + /* if silent reset happened, we should rewrite the values back */ if(priv->reset_count != reset_cnt) { force_write = 1; @@ -2286,14 +2298,16 @@ static void dm_pd_th( if((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) || (initialized<=3) || force_write) { - //DbgPrint("Write PD_TH state = %d\n", DM_DigTable.CurPD_THState); + /*DbgPrint("Write PD_TH state = %d\n", DM_DigTable.CurPD_THState);*/ if(dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) { - // Lower PD_TH for OFDM. + /* Lower PD_TH for OFDM. */ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { - /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ - // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + /* + * 2008/01/11 MH 40MHZ 90/92 register are not the same. + * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + */ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x40); @@ -2304,11 +2318,13 @@ static void dm_pd_th( } else if(dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER) { - // Higher PD_TH for OFDM. + /* Higher PD_TH for OFDM. */ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { - /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */ - // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + /* + * 2008/01/11 MH 40MHZ 90/92 register are not the same. + * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. + */ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); @@ -2319,7 +2335,7 @@ static void dm_pd_th( } else if(dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) { - // Higher PD_TH for OFDM for high power state. + /* Higher PD_TH for OFDM for high power state. */ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); @@ -2367,12 +2383,12 @@ static void dm_cs_ratio( dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; } } - else // disconnected -> connected or connected -> disconnected + else /* disconnected -> connected or connected -> disconnected */ { dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; } - // if silent reset happened, we should rewrite the values back + /* if silent reset happened, we should rewrite the values back */ if(priv->reset_count != reset_cnt) { force_write = 1; @@ -2384,15 +2400,15 @@ static void dm_cs_ratio( if((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) || !initialized || force_write) { - //DbgPrint("Write CS_ratio state = %d\n", DM_DigTable.CurCS_ratioState); + /*DbgPrint("Write CS_ratio state = %d\n", DM_DigTable.CurCS_ratioState);*/ if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER) { - // Lower CS ratio for CCK. + /* Lower CS ratio for CCK. */ write_nic_byte(dev, 0xa0a, 0x08); } else if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER) { - // Higher CS ratio for CCK. + /* Higher CS ratio for CCK. */ write_nic_byte(dev, 0xa0a, 0xcd); } dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state; @@ -2409,41 +2425,41 @@ void dm_init_edca_turbo(struct net_device *dev) priv->bcurrent_turbo_EDCA = false; priv->ieee80211->bis_any_nonbepkts = false; priv->bis_cur_rdlstate = false; -} // dm_init_edca_turbo +} /* dm_init_edca_turbo */ static void dm_check_edca_turbo( struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; - //PSTA_QOS pStaQos = pMgntInfo->pStaQos; + /*PSTA_QOS pStaQos = pMgntInfo->pStaQos;*/ - // Keep past Tx/Rx packet count for RT-to-RT EDCA turbo. + /* Keep past Tx/Rx packet count for RT-to-RT EDCA turbo. */ static unsigned long lastTxOkCnt; static unsigned long lastRxOkCnt; unsigned long curTxOkCnt = 0; unsigned long curRxOkCnt = 0; - // - // Do not be Turbo if it's under WiFi config and Qos Enabled, because the EDCA parameters - // should follow the settings from QAP. By Bruce, 2007-12-07. - // + /* + * Do not be Turbo if it's under WiFi config and Qos Enabled, because the EDCA parameters + * should follow the settings from QAP. By Bruce, 2007-12-07. + */ if(priv->ieee80211->state != IEEE80211_LINKED) goto dm_CheckEdcaTurbo_EXIT; - // We do not turn on EDCA turbo mode for some AP that has IOT issue + /* We do not turn on EDCA turbo mode for some AP that has IOT issue */ if(priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO) goto dm_CheckEdcaTurbo_EXIT; -// printk("========>%s():bis_any_nonbepkts is %d\n",__func__,priv->bis_any_nonbepkts); - // Check the status for current condition. + /*printk("========>%s():bis_any_nonbepkts is %d\n",__func__,priv->bis_any_nonbepkts);*/ + /* Check the status for current condition. */ if(!priv->ieee80211->bis_any_nonbepkts) { curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; - // For RT-AP, we needs to turn it on when Rx>Tx + /* For RT-AP, we needs to turn it on when Rx>Tx */ if(curRxOkCnt > 4*curTxOkCnt) { - //printk("%s():curRxOkCnt > 4*curTxOkCnt\n"); + /*printk("%s():curRxOkCnt > 4*curTxOkCnt\n");*/ if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]); @@ -2453,7 +2469,7 @@ static void dm_check_edca_turbo( else { - //printk("%s():curRxOkCnt < 4*curTxOkCnt\n"); + /*printk("%s():curRxOkCnt < 4*curTxOkCnt\n");*/ if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { write_nic_dword(dev, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]); @@ -2466,10 +2482,10 @@ static void dm_check_edca_turbo( } else { - // - // Turn Off EDCA turbo here. - // Restore original EDCA according to the declaration of AP. - // + /* + * Turn Off EDCA turbo here. + * Restore original EDCA according to the declaration of AP. + */ if(priv->bcurrent_turbo_EDCA) { @@ -2479,30 +2495,32 @@ static void dm_check_edca_turbo( struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters; u8 mode = priv->ieee80211->mode; - // For Each time updating EDCA parameter, reset EDCA turbo mode status. + /* For Each time updating EDCA parameter, reset EDCA turbo mode status. */ dm_init_edca_turbo(dev); u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime; u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0]))<< AC_PARAM_TXOP_LIMIT_OFFSET)| (((u32)(qos_parameters->cw_max[0]))<< AC_PARAM_ECW_MAX_OFFSET)| (((u32)(qos_parameters->cw_min[0]))<< AC_PARAM_ECW_MIN_OFFSET)| ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET)); - //write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam); + /*write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);*/ write_nic_dword(dev, EDCAPARA_BE, u4bAcParam); - // Check ACM bit. - // If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13. + /* + * Check ACM bit. + * If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13. + */ { - // TODO: Modified this part and try to set acm control in only 1 IO processing!! + /* TODO: Modified this part and try to set acm control in only 1 IO processing!! */ PACI_AIFSN pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]); u8 AcmCtrl; read_nic_byte(dev, AcmHwCtrl, &AcmCtrl); if(pAciAifsn->f.ACM) - { // ACM bit is 1. + { /* ACM bit is 1. */ AcmCtrl |= AcmHw_BeqEn; } else - { // ACM bit is 0. + { /* ACM bit is 0. */ AcmCtrl &= (~AcmHw_BeqEn); } @@ -2516,11 +2534,11 @@ static void dm_check_edca_turbo( dm_CheckEdcaTurbo_EXIT: - // Set variables for next time. + /* Set variables for next time. */ priv->ieee80211->bis_any_nonbepkts = false; lastTxOkCnt = priv->stats.txbytesunicast; lastRxOkCnt = priv->stats.rxbytesunicast; -} // dm_CheckEdcaTurbo +} /* dm_CheckEdcaTurbo */ static void dm_init_ctstoself(struct net_device *dev) { @@ -2554,12 +2572,12 @@ static void dm_ctstoself(struct net_device *dev) { curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; - if(curRxOkCnt > 4*curTxOkCnt) //downlink, disable CTS to self + if(curRxOkCnt > 4*curTxOkCnt) /* downlink, disable CTS to self */ { pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF; - //DbgPrint("dm_CTSToSelf() ==> CTS to self disabled -- downlink\n"); + /*DbgPrint("dm_CTSToSelf() ==> CTS to self disabled -- downlink\n");*/ } - else //uplink + else /* uplink */ { pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF; } @@ -2597,8 +2615,10 @@ static void dm_check_pbc_gpio(struct net_device *dev) if (tmp1byte&BIT6 || tmp1byte&BIT0) { - // Here we only set bPbcPressed to TRUE - // After trigger PBC, the variable will be set to FALSE + /* + * Here we only set bPbcPressed to TRUE + * After trigger PBC, the variable will be set to FALSE + */ RT_TRACE(COMP_IO, "CheckPbcGPIO - PBC is pressed\n"); priv->bpbc_pressed = true; } @@ -2626,7 +2646,7 @@ void dm_rf_pathcheck_workitemcallback(struct work_struct *work) struct delayed_work *dwork = container_of(work,struct delayed_work,work); struct r8192_priv *priv = container_of(dwork,struct r8192_priv,rfpath_check_wq); struct net_device *dev =priv->ieee80211->dev; - //bool bactually_set = false; + /*bool bactually_set = false;*/ u8 rfpath = 0, i; @@ -2634,7 +2654,7 @@ void dm_rf_pathcheck_workitemcallback(struct work_struct *work) always be the same. We only read 0xc04 now. */ read_nic_byte(dev, 0xc04, &rfpath); - // Check Bit 0-3, it means if RF A-D is enabled. + /* Check Bit 0-3, it means if RF A-D is enabled. */ for (i = 0; i < RF90_PATH_MAX; i++) { if (rfpath & (0x01<CustomerID == RT_CID_819x_Netcore) @@ -2674,8 +2694,8 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) struct r8192_priv *priv = ieee80211_priv(dev); u8 i, max_rssi_index=0, min_rssi_index=0, sec_rssi_index=0, rf_num=0; u8 tmp_max_rssi=0, tmp_min_rssi=0, tmp_sec_rssi=0; - u8 cck_default_Rx=0x2; //RF-C - u8 cck_optional_Rx=0x3;//RF-D + u8 cck_default_Rx=0x2; /* RF-C */ + u8 cck_optional_Rx=0x3; /* RF-D */ long tmp_cck_max_pwdb=0, tmp_cck_min_pwdb=0, tmp_cck_sec_pwdb=0; u8 cck_rx_ver2_max_index=0, cck_rx_ver2_min_index=0, cck_rx_ver2_sec_index=0; u8 cur_rf_rssi; @@ -2698,11 +2718,11 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) if(priv->ieee80211->mode == WIRELESS_MODE_B) { - DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; //pure B mode, fixed cck version2 - //DbgPrint("Pure B mode, use cck rx version2 \n"); + DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; /* pure B mode, fixed cck version2 */ + /*DbgPrint("Pure B mode, use cck rx version2 \n");*/ } - //decide max/sec/min rssi index + /* decide max/sec/min rssi index */ for (i=0; i= tmp_max_rssi) { tmp_max_rssi = cur_rf_rssi; @@ -2741,7 +2762,7 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) max_rssi_index = i; } else if(cur_rf_rssi == tmp_max_rssi) - { // let sec and min point to the different index + { /* let sec and min point to the different index */ tmp_sec_rssi = cur_rf_rssi; sec_rssi_index = i; } @@ -2753,29 +2774,29 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) else if(cur_rf_rssi == tmp_sec_rssi) { if(tmp_sec_rssi == tmp_min_rssi) - { // let sec and min point to the different index + { /* let sec and min point to the different index */ tmp_sec_rssi = cur_rf_rssi; sec_rssi_index = i; } else { - // This case we don't need to set any index + /* This case we don't need to set any index */ } } else if((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi)) { - // This case we don't need to set any index + /* This case we don't need to set any index */ } else if(cur_rf_rssi == tmp_min_rssi) { if(tmp_sec_rssi == tmp_min_rssi) - { // let sec and min point to the different index + { /* let sec and min point to the different index */ tmp_min_rssi = cur_rf_rssi; min_rssi_index = i; } else { - // This case we don't need to set any index + /* This case we don't need to set any index */ } } else if(cur_rf_rssi < tmp_min_rssi) @@ -2788,7 +2809,7 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) } rf_num = 0; - // decide max/sec/min cck pwdb index + /* decide max/sec/min cck pwdb index */ if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) { for (i=0; i= tmp_cck_max_pwdb) { tmp_cck_max_pwdb = cur_cck_pwdb; @@ -2826,7 +2847,7 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) cck_rx_ver2_max_index = i; } else if(cur_cck_pwdb == tmp_cck_max_pwdb) - { // let sec and min point to the different index + { /* let sec and min point to the different index */ tmp_cck_sec_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; } @@ -2838,29 +2859,29 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) else if(cur_cck_pwdb == tmp_cck_sec_pwdb) { if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb) - { // let sec and min point to the different index + { /* let sec and min point to the different index */ tmp_cck_sec_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; } else { - // This case we don't need to set any index + /* This case we don't need to set any index */ } } else if((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb)) { - // This case we don't need to set any index + /* This case we don't need to set any index */ } else if(cur_cck_pwdb == tmp_cck_min_pwdb) { if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb) - { // let sec and min point to the different index + { /* let sec and min point to the different index */ tmp_cck_min_pwdb = cur_cck_pwdb; cck_rx_ver2_min_index = i; } else { - // This case we don't need to set any index + /* This case we don't need to set any index */ } } else if(cur_cck_pwdb < tmp_cck_min_pwdb) @@ -2875,8 +2896,10 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) } - // Set CCK Rx path - // reg0xA07[3:2]=cck default rx path, reg0xa07[1:0]=cck optional rx path. + /* + * Set CCK Rx path + * reg0xA07[3:2]=cck default rx path, reg0xa07[1:0]=cck optional rx path. + */ update_cck_rx_path = 0; if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) { @@ -2890,11 +2913,11 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) { if((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH) { - //record the enabled rssi threshold + /* record the enabled rssi threshold */ DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5; - //disable the BB Rx path, OFDM - rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<>i) & 0x1) //disabled rf + if((DM_RxPathSelTable.disabledRF>>i) & 0x1) /* disabled rf */ { if(tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i]) { - //enable the BB Rx path - //DbgPrint("RF-%d is enabled. \n", 0x1<ieee80211->fsync_firstdiff_ratethreshold= 100; priv->ieee80211->fsync_seconddiff_ratethreshold= 200; priv->ieee80211->fsync_state = Default_Fsync; - priv->framesyncMonitor = 1; // current default 0xc38 monitor on + priv->framesyncMonitor = 1; /* current default 0xc38 monitor on */ init_timer(&priv->fsync_timer); priv->fsync_timer.data = (unsigned long)dev; @@ -2993,7 +3016,7 @@ void dm_fsync_timer_callback(unsigned long data) priv->ieee80211->bfsync_enable && (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) { - // Count rate 54, MCS [7], [12, 13, 14, 15] + /* Count rate 54, MCS [7], [12, 13, 14, 15] */ u32 rate_bitmap; for(rate_index = 0; rate_index <= 27; rate_index++) { @@ -3010,13 +3033,13 @@ void dm_fsync_timer_callback(unsigned long data) { u32 DiffNum = priv->rateCountDiffRecord - rate_count_diff; - // Continue count + /* Continue count */ if(DiffNum >= priv->ieee80211->fsync_seconddiff_ratethreshold) priv->ContinueDiffCount++; else priv->ContinueDiffCount = 0; - // Continue count over + /* Continue count over */ if(priv->ContinueDiffCount >=2) { bSwitchFromCountDiff = true; @@ -3025,11 +3048,11 @@ void dm_fsync_timer_callback(unsigned long data) } else { - // Stop the continued count + /* Stop the continued count */ priv->ContinueDiffCount = 0; } - //If Count diff <= FsyncRateCountThreshold + /* If Count diff <= FsyncRateCountThreshold */ if(rate_count_diff <= priv->ieee80211->fsync_firstdiff_ratethreshold) { bSwitchFromCountDiff = true; @@ -3038,7 +3061,7 @@ void dm_fsync_timer_callback(unsigned long data) priv->rate_record = rate_count; priv->rateCountDiffRecord = rate_count_diff; RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync); - // if we never receive those mcs rate and rssi > 30 % then switch fsyn + /* if we never receive those mcs rate and rssi > 30 % then switch fsyn */ if(priv->undecorated_smoothed_pwdb > priv->ieee80211->fsync_rssi_threshold && bSwitchFromCountDiff) { bDoubleTimeInterval = true; @@ -3078,7 +3101,7 @@ void dm_fsync_timer_callback(unsigned long data) } else { - // Let Register return to default value; + /* Let Register return to default value; */ if(priv->bswitch_fsync) { priv->bswitch_fsync = false; @@ -3106,7 +3129,7 @@ static void dm_EndSWFsync(struct net_device *dev) RT_TRACE(COMP_HALDM, "%s\n", __func__); del_timer_sync(&(priv->fsync_timer)); - // Let Register return to default value; + /* Let Register return to default value; */ if(priv->bswitch_fsync) { priv->bswitch_fsync = false; @@ -3128,9 +3151,9 @@ static void dm_StartSWFsync(struct net_device *dev) u32 rateBitmap; RT_TRACE(COMP_HALDM, "%s\n", __func__); - // Initial rate record to zero, start to record. + /* Initial rate record to zero, start to record. */ priv->rate_record = 0; - // Initialize continue diff count to zero, start to record. + /* Initialize continue diff count to zero, start to record. */ priv->ContinueDiffCount = 0; priv->rateCountDiffRecord = 0; priv->bswitch_fsync = false; @@ -3174,7 +3197,7 @@ void dm_check_fsync(struct net_device *dev) #define RegC38_NonFsync_Other_AP 1 #define RegC38_Fsync_AP_BCM 2 struct r8192_priv *priv = ieee80211_priv(dev); - //u32 framesyncC34; + /*u32 framesyncC34;*/ static u8 reg_c38_State=RegC38_Default; static u32 reset_cnt; @@ -3224,7 +3247,7 @@ void dm_check_fsync(struct net_device *dev) if(priv->framesyncMonitor) { if(reg_c38_State != RegC38_Fsync_AP_BCM) - { //For broadcom AP we write different default value + { /* For broadcom AP we write different default value */ write_nic_byte(dev, rOFDM0_RxDetector3, 0x95); reg_c38_State = RegC38_Fsync_AP_BCM; @@ -3267,7 +3290,7 @@ void dm_check_fsync(struct net_device *dev) { write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; - //DbgPrint("Fsync is idle, rssi>=40, write 0xc38 = 0x%x \n", pHalData->framesync); + /*DbgPrint("Fsync is idle, rssi>=40, write 0xc38 = 0x%x \n", pHalData->framesync);*/ } } } @@ -3277,7 +3300,7 @@ void dm_check_fsync(struct net_device *dev) { write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; - //DbgPrint("Fsync is idle, not connected, write 0xc38 = 0x%x \n", pHalData->framesync); + /*DbgPrint("Fsync is idle, not connected, write 0xc38 = 0x%x \n", pHalData->framesync);*/ } } } @@ -3285,11 +3308,11 @@ void dm_check_fsync(struct net_device *dev) if(priv->framesyncMonitor) { if(priv->reset_count != reset_cnt) - { //After silent reset, the reg_c38_State will be returned to default value + { /* After silent reset, the reg_c38_State will be returned to default value */ write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; reset_cnt = priv->reset_count; - //DbgPrint("reg_c38_State = 0 for silent reset. \n"); + /*DbgPrint("reg_c38_State = 0 for silent reset. \n");*/ } } else @@ -3298,7 +3321,7 @@ void dm_check_fsync(struct net_device *dev) { write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; - //DbgPrint("framesync no monitor, write 0xc38 = 0x%x \n", pHalData->framesync); + /*DbgPrint("framesync no monitor, write 0xc38 = 0x%x \n", pHalData->framesync);*/ } } } @@ -3329,7 +3352,7 @@ void dm_shadow_init(struct net_device *dev) for (offset = 0; offset < 256; offset++) { read_nic_byte(dev, offset+page*256, &dm_shadow[page][offset]); - //DbgPrint("P-%d/O-%02x=%02x\r\n", page, offset, DM_Shadow[page][offset]); + /*DbgPrint("P-%d/O-%02x=%02x\r\n", page, offset, DM_Shadow[page][offset]);*/ } for (page = 8; page < 11; page++) @@ -3364,8 +3387,8 @@ static void dm_init_dynamic_txpower(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. - priv->ieee80211->bdynamic_txpower_enable = true; //Default to enable Tx Power Control + /* Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code. */ + priv->ieee80211->bdynamic_txpower_enable = true; /* Default to enable Tx Power Control */ priv->bLastDTPFlag_High = false; priv->bLastDTPFlag_Low = false; priv->bDynamicTxHighPower = false; @@ -3383,7 +3406,7 @@ static void dm_dynamic_txpower(struct net_device *dev) priv->bDynamicTxLowPower = false; return; } - //printk("priv->ieee80211->current_network.unknown_cap_exist is %d ,priv->ieee80211->current_network.broadcom_cap_exist is %d\n",priv->ieee80211->current_network.unknown_cap_exist,priv->ieee80211->current_network.broadcom_cap_exist); + /*printk("priv->ieee80211->current_network.unknown_cap_exist is %d ,priv->ieee80211->current_network.broadcom_cap_exist is %d\n",priv->ieee80211->current_network.unknown_cap_exist,priv->ieee80211->current_network.broadcom_cap_exist);*/ if((priv->ieee80211->current_network.atheros_cap_exist) && (priv->ieee80211->mode == IEEE_G)){ txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH; txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW; @@ -3394,7 +3417,7 @@ static void dm_dynamic_txpower(struct net_device *dev) txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW; } -// printk("=======>%s(): txhipower_threshhold is %d,txlowpower_threshold is %d\n",__func__,txhipower_threshhold,txlowpower_threshold); + /*printk("=======>%s(): txhipower_threshhold is %d,txlowpower_threshold is %d\n",__func__,txhipower_threshhold,txlowpower_threshold);*/ RT_TRACE(COMP_TXAGC,"priv->undecorated_smoothed_pwdb = %ld \n" , priv->undecorated_smoothed_pwdb); if(priv->ieee80211->state == IEEE80211_LINKED) @@ -3406,12 +3429,12 @@ static void dm_dynamic_txpower(struct net_device *dev) } else { - // high power state check + /* high power state check */ if(priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true) { priv->bDynamicTxHighPower = false; } - // low power state check + /* low power state check */ if(priv->undecorated_smoothed_pwdb < 35) { priv->bDynamicTxLowPower = true; @@ -3424,7 +3447,7 @@ static void dm_dynamic_txpower(struct net_device *dev) } else { - //pHalData->bTXPowerCtrlforNearFarRange = !pHalData->bTXPowerCtrlforNearFarRange; + /*pHalData->bTXPowerCtrlforNearFarRange = !pHalData->bTXPowerCtrlforNearFarRange;*/ priv->bDynamicTxHighPower = false; priv->bDynamicTxLowPower = false; } @@ -3439,27 +3462,27 @@ static void dm_dynamic_txpower(struct net_device *dev) #endif rtl8192_phy_setTxPower(dev,priv->ieee80211->current_network.channel); - //pHalData->bStartTxCtrlByTPCNFR = FALSE; //Clear th flag of Set TX Power from Sitesurvey + /*pHalData->bStartTxCtrlByTPCNFR = FALSE; Clear th flag of Set TX Power from Sitesurvey*/ } priv->bLastDTPFlag_High = priv->bDynamicTxHighPower; priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower; } /* dm_dynamic_txpower */ -//added by vivi, for read tx rate and retrycount +/* added by vivi, for read tx rate and retrycount */ static void dm_check_txrateandretrycount(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); struct ieee80211_device *ieee = priv->ieee80211; - //for 11n tx rate -// priv->stats.CurrentShowTxate = read_nic_byte(dev, Current_Tx_Rate_Reg); + /* for 11n tx rate */ + /*priv->stats.CurrentShowTxate = read_nic_byte(dev, Current_Tx_Rate_Reg);*/ read_nic_byte(dev, Current_Tx_Rate_Reg, &ieee->softmac_stats.CurrentShowTxate); - //printk("=============>tx_rate_reg:%x\n", ieee->softmac_stats.CurrentShowTxate); - //for initial tx rate -// priv->stats.last_packet_rate = read_nic_byte(dev, Initial_Tx_Rate_Reg); + /*printk("=============>tx_rate_reg:%x\n", ieee->softmac_stats.CurrentShowTxate);*/ + /* for initial tx rate */ + /*priv->stats.last_packet_rate = read_nic_byte(dev, Initial_Tx_Rate_Reg);*/ read_nic_byte(dev, Initial_Tx_Rate_Reg, &ieee->softmac_stats.last_packet_rate); - //for tx tx retry count -// priv->stats.txretrycount = read_nic_dword(dev, Tx_Retry_Count_Reg); + /* for tx tx retry count */ + /*priv->stats.txretrycount = read_nic_dword(dev, Tx_Retry_Count_Reg);*/ read_nic_dword(dev, Tx_Retry_Count_Reg, &ieee->softmac_stats.txretrycount); } @@ -3467,9 +3490,11 @@ static void dm_send_rssi_tofw(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - // If we test chariot, we should stop the TX command ? - // Because 92E will always silent reset when we send tx command. We use register - // 0x1e0(byte) to notify driver. + /* + * If we test chariot, we should stop the TX command ? + * Because 92E will always silent reset when we send tx command. We use register + * 0x1e0(byte) to notify driver. + */ write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb); return; } -- cgit v0.10.2 From 04d695d777e141d8e36fa4f7e1ef208ccf7079c6 Mon Sep 17 00:00:00 2001 From: Lorenzo Stoakes Date: Sat, 24 Jan 2015 15:45:22 +0000 Subject: staging: rtl8192u: fix whitespace and alignment This patch fixes warnings/errors raised by checkpatch.pl relating to whitespace in r8192U_dm.c, removes inconsistent whitespace, and additionally fixes some vertical alignment issues. Signed-off-by: Lorenzo Stoakes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index 6112c7d..2c3d894 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -22,11 +22,12 @@ Major Change History: #include "r819xU_cmdpkt.h" /*---------------------------Define Local Constant---------------------------*/ /* Indicate different AP vendor for IOT issue. */ -static u32 edca_setting_DL[HT_IOT_PEER_MAX] = - { 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0xa44f, 0x5ea44f}; -static u32 edca_setting_UL[HT_IOT_PEER_MAX] = - { 0x5e4322, 0xa44f, 0x5e4322, 0x604322, 0x5ea44f, 0x5ea44f}; - +static u32 edca_setting_DL[HT_IOT_PEER_MAX] = { + 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0x00a44f, 0x5ea44f +}; +static u32 edca_setting_UL[HT_IOT_PEER_MAX] = { + 0x5e4322, 0x00a44f, 0x5e4322, 0x604322, 0x5ea44f, 0x5ea44f +}; #define RTK_UL_EDCA 0xa44f #define RTK_DL_EDCA 0x5e4322 @@ -37,7 +38,7 @@ static u32 edca_setting_UL[HT_IOT_PEER_MAX] = /* Debug variable ? */ dig_t dm_digtable; /* Store current software write register content for MAC PHY. */ -u8 dm_shadow[16][256] = {{0}}; +u8 dm_shadow[16][256] = { {0} }; /* For Dynamic Rx Path Selection by Signal Strength */ DRxPathSel DM_RxPathSelTable; /*------------------------Define global variable-----------------------------*/ @@ -66,11 +67,8 @@ static void dm_bandwidth_autoswitch(struct net_device *dev); static void dm_check_txpower_tracking(struct net_device *dev); - - /*static void dm_txpower_reset_recovery(struct net_device *dev);*/ - /* DM --> Dynamic Init Gain by RSSI */ static void dm_dig_init(struct net_device *dev); static void dm_ctrl_initgain_byrssi(struct net_device *dev); @@ -89,13 +87,11 @@ static void dm_check_edca_turbo(struct net_device *dev); /* DM --> Check PBC */ static void dm_check_pbc_gpio(struct net_device *dev); - /* DM --> Check current RX RF path state */ static void dm_check_rx_path_selection(struct net_device *dev); static void dm_init_rxpath_selection(struct net_device *dev); static void dm_rxpath_sel_byrssi(struct net_device *dev); - /* DM --> Fsync for broadcom ap */ static void dm_init_fsync(struct net_device *dev); static void dm_deInit_fsync(struct net_device *dev); @@ -109,7 +105,6 @@ static void dm_check_txrateandretrycount(struct net_device *dev); static void dm_init_dynamic_txpower(struct net_device *dev); static void dm_dynamic_txpower(struct net_device *dev); - /* DM --> For rate adaptive and DIG, we must send RSSI to firmware */ static void dm_send_rssi_tofw(struct net_device *dev); static void dm_ctstoself(struct net_device *dev); @@ -148,14 +143,12 @@ void init_hal_dm(struct net_device *dev) void deinit_hal_dm(struct net_device *dev) { - dm_deInit_fsync(dev); - } - #ifdef USB_RX_AGGREGATION_SUPPORT -void dm_CheckRxAggregation(struct net_device *dev) { +void dm_CheckRxAggregation(struct net_device *dev) +{ struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev); PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo; static unsigned long lastTxOkCnt; @@ -184,14 +177,15 @@ void dm_CheckRxAggregation(struct net_device *dev) { if ((curTxOkCnt + curRxOkCnt) < 15000000) return; - if(curTxOkCnt > 4*curRxOkCnt) { + if (curTxOkCnt > 4*curRxOkCnt) { if (priv->bCurrentRxAggrEnable) { write_nic_dword(dev, 0x1a8, 0); priv->bCurrentRxAggrEnable = false; } - }else{ + } else { if (!priv->bCurrentRxAggrEnable && !pHTInfo->bCurrentRT2RTAggregation) { u32 ulValue; + ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) | (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout); /* @@ -209,8 +203,6 @@ void dm_CheckRxAggregation(struct net_device *dev) { } /* dm_CheckEdcaTurbo */ #endif - - void hal_dm_watchdog(struct net_device *dev) { /*struct r8192_priv *priv = ieee80211_priv(dev);*/ @@ -237,7 +229,6 @@ void hal_dm_watchdog(struct net_device *dev) #endif } /* HalDmWatchDog */ - /* * Decide Rate Adaptive Set according to distance (signal strength) * 01/11/2008 MHC Modify input arguments and RATR table level. @@ -246,7 +237,6 @@ void hal_dm_watchdog(struct net_device *dev) */ void init_rate_adaptive(struct net_device *dev) { - struct r8192_priv *priv = ieee80211_priv(dev); prate_adaptive pra = (prate_adaptive)&priv->rate_adaptive; @@ -259,15 +249,13 @@ void init_rate_adaptive(struct net_device *dev) pra->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M; pra->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M; - if(priv->CustomerID == RT_CID_819x_Netcore) + if (priv->CustomerID == RT_CID_819x_Netcore) pra->ping_rssi_enable = 1; else pra->ping_rssi_enable = 0; pra->ping_rssi_thresh_for_ra = 15; - - if (priv->rf_type == RF_2T4R) - { + if (priv->rf_type == RF_2T4R) { /* * 07/10/08 MH Modify for RA smooth scheme. * 2008/01/11 MH Modify 2T RATR table for different RSSI. 080515 porting by amy from windows code. @@ -278,9 +266,7 @@ void init_rate_adaptive(struct net_device *dev) pra->low_rssi_threshold_ratr_40M = 0x8f0ff005; pra->low_rssi_threshold_ratr_20M = 0x8f0ff001; pra->ping_rssi_ratr = 0x0000000d;/* cosa add for test */ - } - else if (priv->rf_type == RF_1T2R) - { + } else if (priv->rf_type == RF_1T2R) { pra->upper_rssi_threshold_ratr = 0x000f0000; pra->middle_rssi_threshold_ratr = 0x000ff000; pra->low_rssi_threshold_ratr = 0x000ff001; @@ -291,7 +277,6 @@ void init_rate_adaptive(struct net_device *dev) } /* InitRateAdaptive */ - /*----------------------------------------------------------------------------- * Function: dm_check_rate_adaptive() * @@ -318,111 +303,91 @@ static void dm_check_rate_adaptive(struct net_device *dev) bool bshort_gi_enabled = false; static u8 ping_rssi_state; - - if(!priv->up) - { + if (!priv->up) { RT_TRACE(COMP_RATE, "<---- dm_check_rate_adaptive(): driver is going to unload\n"); return; } - if(pra->rate_adaptive_disabled) /* this variable is set by ioctl. */ + if (pra->rate_adaptive_disabled) /* this variable is set by ioctl. */ return; /* TODO: Only 11n mode is implemented currently, */ - if(!(priv->ieee80211->mode == WIRELESS_MODE_N_24G || - priv->ieee80211->mode == WIRELESS_MODE_N_5G)) - return; + if (!(priv->ieee80211->mode == WIRELESS_MODE_N_24G || + priv->ieee80211->mode == WIRELESS_MODE_N_5G)) + return; - if(priv->ieee80211->state == IEEE80211_LINKED) - { + if (priv->ieee80211->state == IEEE80211_LINKED) { /*RT_TRACE(COMP_RATE, "dm_CheckRateAdaptive(): \t");*/ /* Check whether Short GI is enabled */ bshort_gi_enabled = (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) || (!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz); - pra->upper_rssi_threshold_ratr = - (pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + (pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0); pra->middle_rssi_threshold_ratr = - (pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + (pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0); - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { pra->low_rssi_threshold_ratr = - (pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; - } - else - { + (pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0); + } else { pra->low_rssi_threshold_ratr = - (pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + (pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0); } /* cosa add for test */ pra->ping_rssi_ratr = - (pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + (pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31:0); /* 2007/10/08 MH We support RA smooth scheme now. When it is the first time to link with AP. We will not change upper/lower threshold. If STA stay in high or low level, we must change two different threshold to prevent jumping frequently. */ - if (pra->ratr_state == DM_RATR_STA_HIGH) - { + if (pra->ratr_state == DM_RATR_STA_HIGH) { HighRSSIThreshForRA = pra->high2low_rssi_thresh_for_ra; - LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ? (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M); - } - else if (pra->ratr_state == DM_RATR_STA_LOW) - { + } else if (pra->ratr_state == DM_RATR_STA_LOW) { HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra; - LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ? (pra->low2high_rssi_thresh_for_ra40M):(pra->low2high_rssi_thresh_for_ra20M); - } - else - { + } else { HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra; - LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ? (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M); } /*DbgPrint("[DM] THresh H/L=%d/%d\n\r", RATR.HighRSSIThreshForRA, RATR.LowRSSIThreshForRA);*/ - if(priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA) - { + if (priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA) { /*DbgPrint("[DM] RSSI=%d STA=HIGH\n\r", pHalData->UndecoratedSmoothedPWDB);*/ pra->ratr_state = DM_RATR_STA_HIGH; targetRATR = pra->upper_rssi_threshold_ratr; - }else if(priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA) - { + } else if (priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA) { /*DbgPrint("[DM] RSSI=%d STA=Middle\n\r", pHalData->UndecoratedSmoothedPWDB);*/ pra->ratr_state = DM_RATR_STA_MIDDLE; targetRATR = pra->middle_rssi_threshold_ratr; - }else - { + } else { /*DbgPrint("[DM] RSSI=%d STA=LOW\n\r", pHalData->UndecoratedSmoothedPWDB);*/ pra->ratr_state = DM_RATR_STA_LOW; targetRATR = pra->low_rssi_threshold_ratr; } /* cosa add for test */ - if(pra->ping_rssi_enable) - { + if (pra->ping_rssi_enable) { /*pHalData->UndecoratedSmoothedPWDB = 19;*/ - if(priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5)) - { - if((priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) || - ping_rssi_state) - { - /*DbgPrint("TestRSSI = %d, set RATR to 0x%x \n", pHalData->UndecoratedSmoothedPWDB, pRA->TestRSSIRATR);*/ + if (priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5)) { + if ((priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) || + ping_rssi_state) { + /*DbgPrint("TestRSSI = %d, set RATR to 0x%x\n", pHalData->UndecoratedSmoothedPWDB, pRA->TestRSSIRATR);*/ pra->ratr_state = DM_RATR_STA_LOW; targetRATR = pra->ping_rssi_ratr; ping_rssi_state = 1; } /*else - DbgPrint("TestRSSI is between the range. \n");*/ - } - else - { - /*DbgPrint("TestRSSI Recover to 0x%x \n", targetRATR);*/ + DbgPrint("TestRSSI is between the range.\n");*/ + } else { + /*DbgPrint("TestRSSI Recover to 0x%x\n", targetRATR);*/ ping_rssi_state = 0; } } @@ -431,18 +396,17 @@ static void dm_check_rate_adaptive(struct net_device *dev) * 2008.04.01 * For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7. */ - if(priv->ieee80211->GetHalfNmodeSupportByAPsHandler(dev)) - targetRATR &= 0xf00fffff; + if (priv->ieee80211->GetHalfNmodeSupportByAPsHandler(dev)) + targetRATR &= 0xf00fffff; /* Check whether updating of RATR0 is required */ read_nic_dword(dev, RATR0, ¤tRATR); - if(targetRATR != currentRATR) - { + if (targetRATR != currentRATR) { u32 ratr_value; + ratr_value = targetRATR; - RT_TRACE(COMP_RATE,"currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR); - if(priv->rf_type == RF_1T2R) - { + RT_TRACE(COMP_RATE, "currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR); + if (priv->rf_type == RF_1T2R) { ratr_value &= ~(RATE_ALL_OFDM_2SS); } write_nic_dword(dev, RATR0, ratr_value); @@ -451,15 +415,12 @@ static void dm_check_rate_adaptive(struct net_device *dev) pra->last_ratr = targetRATR; } - } - else - { + } else { pra->ratr_state = DM_RATR_STA_MAX; } } /* dm_CheckRateAdaptive */ - static void dm_init_bandwidth_autoswitch(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); @@ -471,19 +432,18 @@ static void dm_init_bandwidth_autoswitch(struct net_device *dev) } /* dm_init_bandwidth_autoswitch */ - static void dm_bandwidth_autoswitch(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||!priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable){ + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 || !priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable) { return; } - if(priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false){/* If send packets in 40 Mhz in 20/40 */ - if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz) + if (priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false) { /* If send packets in 40 Mhz in 20/40 */ + if (priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz) priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true; - }else{/* in force send packets in 20 Mhz in 20/40 */ - if(priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz) + } else { /* in force send packets in 20 Mhz in 20/40 */ + if (priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz) priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false; } } /* dm_BandwidthAutoSwitch */ @@ -547,14 +507,14 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) bool bHighpowerstate, viviflag = FALSE; DCMD_TXCMD_T tx_cmd; u8 powerlevelOFDM24G; - int i =0, j = 0, k = 0; - u8 RF_Type, tmp_report[5]={0, 0, 0, 0, 0}; + int i = 0, j = 0, k = 0; + u8 RF_Type, tmp_report[5] = {0, 0, 0, 0, 0}; u32 Value; u8 Pwr_Flag; - u16 Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver=0; + u16 Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver = 0; /*RT_STATUS rtStatus = RT_STATUS_SUCCESS;*/ bool rtStatus = true; - u32 delta=0; + u32 delta = 0; write_nic_byte(dev, 0x1ba, 0); @@ -567,163 +527,137 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) RT_TRACE(COMP_POWER_TRACKING, "powerlevelOFDM24G = %x\n", powerlevelOFDM24G); - for(j = 0; j<=30; j++) -{ /* fill tx_cmd */ - tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING; - tx_cmd.Length = 4; - tx_cmd.Value = Value; - rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12); - if (rtStatus == RT_STATUS_FAILURE) - { - RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n"); - } - mdelay(1); - /*DbgPrint("hi, vivi, strange\n");*/ - for(i = 0;i <= 30; i++) - { - read_nic_byte(dev, 0x1ba, &Pwr_Flag); - - if (Pwr_Flag == 0) - { - mdelay(1); - continue; - } - read_nic_word(dev, 0x13c, &Avg_TSSI_Meas); - if(Avg_TSSI_Meas == 0) - { - write_nic_byte(dev, 0x1ba, 0); - break; - } - - for(k = 0;k < 5; k++) - { - if(k !=4) - read_nic_byte(dev, 0x134+k, &tmp_report[k]); - else - read_nic_byte(dev, 0x13e, &tmp_report[k]); - RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]); - } - - /* check if the report value is right */ - for(k = 0;k < 5; k++) - { - if(tmp_report[k] <= 20) - { - viviflag =TRUE; + for (j = 0; j <= 30; j++) { /* fill tx_cmd */ + tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING; + tx_cmd.Length = 4; + tx_cmd.Value = Value; + rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12); + if (rtStatus == RT_STATUS_FAILURE) { + RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n"); + } + mdelay(1); + /*DbgPrint("hi, vivi, strange\n");*/ + for (i = 0; i <= 30; i++) { + read_nic_byte(dev, 0x1ba, &Pwr_Flag); + + if (Pwr_Flag == 0) { + mdelay(1); + continue; + } + read_nic_word(dev, 0x13c, &Avg_TSSI_Meas); + if (Avg_TSSI_Meas == 0) { + write_nic_byte(dev, 0x1ba, 0); break; } - } - if(viviflag ==TRUE) - { - write_nic_byte(dev, 0x1ba, 0); - viviflag = FALSE; - RT_TRACE(COMP_POWER_TRACKING, "we filtered the data\n"); - for(k = 0;k < 5; k++) - tmp_report[k] = 0; - break; - } - - for(k = 0;k < 5; k++) - { - Avg_TSSI_Meas_from_driver += tmp_report[k]; - } - Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5; - RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver); - TSSI_13dBm = priv->TSSI_13dBm; - RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm); - - /*if(abs(Avg_TSSI_Meas_from_driver - TSSI_13dBm) <= E_FOR_TX_POWER_TRACK)*/ - /* For MacOS-compatible */ - if(Avg_TSSI_Meas_from_driver > TSSI_13dBm) - delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm; - else - delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver; + for (k = 0; k < 5; k++) { + if (k != 4) + read_nic_byte(dev, 0x134+k, &tmp_report[k]); + else + read_nic_byte(dev, 0x13e, &tmp_report[k]); + RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]); + } - if(delta <= E_FOR_TX_POWER_TRACK) - { - priv->ieee80211->bdynamic_txpower_enable = TRUE; - write_nic_byte(dev, 0x1ba, 0); - RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n"); - RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); - RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); - RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); - RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); - return; - } - else - { - if(Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) - { - if (priv->rfa_txpowertrackingindex > 0) - { - priv->rfa_txpowertrackingindex--; - if(priv->rfa_txpowertrackingindex_real > 4) - { - priv->rfa_txpowertrackingindex_real--; - rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); - } + /* check if the report value is right */ + for (k = 0; k < 5; k++) { + if (tmp_report[k] <= 20) { + viviflag = TRUE; + break; } } - else - { - if (priv->rfa_txpowertrackingindex < 36) - { - priv->rfa_txpowertrackingindex++; - priv->rfa_txpowertrackingindex_real++; - rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); + if (viviflag == TRUE) { + write_nic_byte(dev, 0x1ba, 0); + viviflag = FALSE; + RT_TRACE(COMP_POWER_TRACKING, "we filtered the data\n"); + for (k = 0; k < 5; k++) + tmp_report[k] = 0; + break; + } - } + for (k = 0; k < 5; k++) { + Avg_TSSI_Meas_from_driver += tmp_report[k]; } - priv->cck_present_attentuation_difference - = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default; - if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) - priv->cck_present_attentuation - = priv->cck_present_attentuation_20Mdefault + priv->cck_present_attentuation_difference; + Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5; + RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver); + TSSI_13dBm = priv->TSSI_13dBm; + RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm); + + /*if (abs(Avg_TSSI_Meas_from_driver - TSSI_13dBm) <= E_FOR_TX_POWER_TRACK)*/ + /* For MacOS-compatible */ + if (Avg_TSSI_Meas_from_driver > TSSI_13dBm) + delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm; else - priv->cck_present_attentuation - = priv->cck_present_attentuation_40Mdefault + priv->cck_present_attentuation_difference; + delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver; + + if (delta <= E_FOR_TX_POWER_TRACK) { + priv->ieee80211->bdynamic_txpower_enable = TRUE; + write_nic_byte(dev, 0x1ba, 0); + RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n"); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); + return; + } else { + if (Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) { + if (priv->rfa_txpowertrackingindex > 0) { + priv->rfa_txpowertrackingindex--; + if (priv->rfa_txpowertrackingindex_real > 4) { + priv->rfa_txpowertrackingindex_real--; + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); + } + } + } else { + if (priv->rfa_txpowertrackingindex < 36) { + priv->rfa_txpowertrackingindex++; + priv->rfa_txpowertrackingindex_real++; + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); - if(priv->cck_present_attentuation > -1&&priv->cck_present_attentuation <23) - { - if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) - { - priv->bcck_in_ch14 = TRUE; - dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); - } - else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) - { - priv->bcck_in_ch14 = FALSE; - dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + } } + priv->cck_present_attentuation_difference + = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default; + + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + priv->cck_present_attentuation + = priv->cck_present_attentuation_20Mdefault + priv->cck_present_attentuation_difference; else - dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + priv->cck_present_attentuation + = priv->cck_present_attentuation_40Mdefault + priv->cck_present_attentuation_difference; + + if (priv->cck_present_attentuation > -1 && priv->cck_present_attentuation < 23) { + if (priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) { + priv->bcck_in_ch14 = TRUE; + dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + } else if (priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) { + priv->bcck_in_ch14 = FALSE; + dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + } else + dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + } + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); + + if (priv->cck_present_attentuation_difference <= -12 || priv->cck_present_attentuation_difference >= 24) { + priv->ieee80211->bdynamic_txpower_enable = TRUE; + write_nic_byte(dev, 0x1ba, 0); + RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n"); + return; + } + } - RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); - RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); - RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); - RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); - - if (priv->cck_present_attentuation_difference <= -12||priv->cck_present_attentuation_difference >= 24) - { - priv->ieee80211->bdynamic_txpower_enable = TRUE; write_nic_byte(dev, 0x1ba, 0); - RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n"); - return; + Avg_TSSI_Meas_from_driver = 0; + for (k = 0; k < 5; k++) + tmp_report[k] = 0; + break; } - - - } - write_nic_byte(dev, 0x1ba, 0); - Avg_TSSI_Meas_from_driver = 0; - for(k = 0;k < 5; k++) - tmp_report[k] = 0; - break; } -} - priv->ieee80211->bdynamic_txpower_enable = TRUE; - write_nic_byte(dev, 0x1ba, 0); + priv->ieee80211->bdynamic_txpower_enable = TRUE; + write_nic_byte(dev, 0x1ba, 0); } static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) @@ -732,17 +666,14 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) struct r8192_priv *priv = ieee80211_priv(dev); u32 tmpRegA, TempCCk; u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval; - int i =0, CCKSwingNeedUpdate=0; + int i = 0, CCKSwingNeedUpdate = 0; - if(!priv->btxpower_trackingInit) - { + if (!priv->btxpower_trackingInit) { /* Query OFDM default setting */ - tmpRegA= rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord); - for(i=0; iOFDM_index= (u8)i; + tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord); + for (i = 0; i < OFDM_Table_Length; i++) { /* find the index */ + if (tmpRegA == OFDMSwingTable[i]) { + priv->OFDM_index = (u8)i; RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, OFDM_index=0x%x\n", rOFDM0_XATxIQImbalance, tmpRegA, priv->OFDM_index); } @@ -750,11 +681,9 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) /* Query CCK default setting From 0xa22 */ TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2); - for(i=0 ; iCCK_index =(u8) i; + for (i = 0; i < CCK_Table_length; i++) { + if (TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0]) { + priv->CCK_index = (u8) i; RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, CCK_index=0x%x\n", rCCK0_TxFilter1, TempCCk, priv->CCK_index); break; @@ -773,32 +702,30 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) /* read and filter out unreasonable value */ tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078); /* 0x12: RF Reg[10:7] */ - RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d \n", tmpRegA); - if(tmpRegA < 3 || tmpRegA > 13) + RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d\n", tmpRegA); + if (tmpRegA < 3 || tmpRegA > 13) return; - if(tmpRegA >= 12) /* if over 12, TP will be bad when high temperature */ + if (tmpRegA >= 12) /* if over 12, TP will be bad when high temperature */ tmpRegA = 12; - RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d \n", tmpRegA); + RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d\n", tmpRegA); priv->ThermalMeter[0] = ThermalMeterVal; /* We use fixed value by Bryant's suggestion */ priv->ThermalMeter[1] = ThermalMeterVal; /* We use fixed value by Bryant's suggestion */ /* Get current RF-A temperature index */ - if(priv->ThermalMeter[0] >= (u8)tmpRegA) /* lower temperature */ - { + if (priv->ThermalMeter[0] >= (u8)tmpRegA) { /* lower temperature */ tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA); tmpCCK40Mindex = tmpCCK20Mindex - 6; - if(tmpOFDMindex >= OFDM_Table_Length) + if (tmpOFDMindex >= OFDM_Table_Length) tmpOFDMindex = OFDM_Table_Length-1; - if(tmpCCK20Mindex >= CCK_Table_length) + if (tmpCCK20Mindex >= CCK_Table_length) tmpCCK20Mindex = CCK_Table_length-1; - if(tmpCCK40Mindex >= CCK_Table_length) + if (tmpCCK40Mindex >= CCK_Table_length) tmpCCK40Mindex = CCK_Table_length-1; - } - else - { + } else { tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]); - if(tmpval >= 6) /* higher temperature */ - tmpOFDMindex = tmpCCK20Mindex = 0; /* max to +6dB */ + + if (tmpval >= 6) /* higher temperature */ + tmpOFDMindex = tmpCCK20Mindex = 0; /* max to +6dB */ else tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval; tmpCCK40Mindex = 0; @@ -806,35 +733,29 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) /*DbgPrint("%ddb, tmpOFDMindex = %d, tmpCCK20Mindex = %d, tmpCCK40Mindex = %d", ((u1Byte)tmpRegA - pHalData->ThermalMeter[0]), tmpOFDMindex, tmpCCK20Mindex, tmpCCK40Mindex);*/ - if(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) /* 40M */ + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) /* 40M */ tmpCCKindex = tmpCCK40Mindex; else tmpCCKindex = tmpCCK20Mindex; - if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) - { + if (priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) { priv->bcck_in_ch14 = TRUE; CCKSwingNeedUpdate = 1; - } - else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) - { + } else if (priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) { priv->bcck_in_ch14 = FALSE; CCKSwingNeedUpdate = 1; } - if(priv->CCK_index != tmpCCKindex) - { + if (priv->CCK_index != tmpCCKindex) { priv->CCK_index = tmpCCKindex; CCKSwingNeedUpdate = 1; } - if(CCKSwingNeedUpdate) - { + if (CCKSwingNeedUpdate) { /*DbgPrint("Update CCK Swing, CCK_index = %d\n", pHalData->CCK_index);*/ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } - if(priv->OFDM_index != tmpOFDMindex) - { + if (priv->OFDM_index != tmpOFDMindex) { priv->OFDM_index = tmpOFDMindex; rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->OFDM_index]); RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n", @@ -845,97 +766,95 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev) void dm_txpower_trackingcallback(struct work_struct *work) { - struct delayed_work *dwork = container_of(work,struct delayed_work,work); - struct r8192_priv *priv = container_of(dwork,struct r8192_priv,txpower_tracking_wq); - struct net_device *dev = priv->ieee80211->dev; + struct delayed_work *dwork = container_of(work, struct delayed_work, work); + struct r8192_priv *priv = container_of(dwork, struct r8192_priv, txpower_tracking_wq); + struct net_device *dev = priv->ieee80211->dev; - if(priv->bDcut == TRUE) + if (priv->bDcut == TRUE) dm_TXPowerTrackingCallback_TSSI(dev); else dm_TXPowerTrackingCallback_ThermalMeter(dev); } - static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev) { - struct r8192_priv *priv = ieee80211_priv(dev); /* Initial the Tx BB index and mapping value */ priv->txbbgain_table[0].txbb_iq_amplifygain = 12; - priv->txbbgain_table[0].txbbgain_value=0x7f8001fe; + priv->txbbgain_table[0].txbbgain_value = 0x7f8001fe; priv->txbbgain_table[1].txbb_iq_amplifygain = 11; - priv->txbbgain_table[1].txbbgain_value=0x788001e2; + priv->txbbgain_table[1].txbbgain_value = 0x788001e2; priv->txbbgain_table[2].txbb_iq_amplifygain = 10; - priv->txbbgain_table[2].txbbgain_value=0x71c001c7; + priv->txbbgain_table[2].txbbgain_value = 0x71c001c7; priv->txbbgain_table[3].txbb_iq_amplifygain = 9; - priv->txbbgain_table[3].txbbgain_value=0x6b8001ae; + priv->txbbgain_table[3].txbbgain_value = 0x6b8001ae; priv->txbbgain_table[4].txbb_iq_amplifygain = 8; - priv->txbbgain_table[4].txbbgain_value=0x65400195; + priv->txbbgain_table[4].txbbgain_value = 0x65400195; priv->txbbgain_table[5].txbb_iq_amplifygain = 7; - priv->txbbgain_table[5].txbbgain_value=0x5fc0017f; + priv->txbbgain_table[5].txbbgain_value = 0x5fc0017f; priv->txbbgain_table[6].txbb_iq_amplifygain = 6; - priv->txbbgain_table[6].txbbgain_value=0x5a400169; + priv->txbbgain_table[6].txbbgain_value = 0x5a400169; priv->txbbgain_table[7].txbb_iq_amplifygain = 5; - priv->txbbgain_table[7].txbbgain_value=0x55400155; + priv->txbbgain_table[7].txbbgain_value = 0x55400155; priv->txbbgain_table[8].txbb_iq_amplifygain = 4; - priv->txbbgain_table[8].txbbgain_value=0x50800142; + priv->txbbgain_table[8].txbbgain_value = 0x50800142; priv->txbbgain_table[9].txbb_iq_amplifygain = 3; - priv->txbbgain_table[9].txbbgain_value=0x4c000130; + priv->txbbgain_table[9].txbbgain_value = 0x4c000130; priv->txbbgain_table[10].txbb_iq_amplifygain = 2; - priv->txbbgain_table[10].txbbgain_value=0x47c0011f; + priv->txbbgain_table[10].txbbgain_value = 0x47c0011f; priv->txbbgain_table[11].txbb_iq_amplifygain = 1; - priv->txbbgain_table[11].txbbgain_value=0x43c0010f; + priv->txbbgain_table[11].txbbgain_value = 0x43c0010f; priv->txbbgain_table[12].txbb_iq_amplifygain = 0; - priv->txbbgain_table[12].txbbgain_value=0x40000100; + priv->txbbgain_table[12].txbbgain_value = 0x40000100; priv->txbbgain_table[13].txbb_iq_amplifygain = -1; - priv->txbbgain_table[13].txbbgain_value=0x3c8000f2; + priv->txbbgain_table[13].txbbgain_value = 0x3c8000f2; priv->txbbgain_table[14].txbb_iq_amplifygain = -2; - priv->txbbgain_table[14].txbbgain_value=0x390000e4; + priv->txbbgain_table[14].txbbgain_value = 0x390000e4; priv->txbbgain_table[15].txbb_iq_amplifygain = -3; - priv->txbbgain_table[15].txbbgain_value=0x35c000d7; + priv->txbbgain_table[15].txbbgain_value = 0x35c000d7; priv->txbbgain_table[16].txbb_iq_amplifygain = -4; - priv->txbbgain_table[16].txbbgain_value=0x32c000cb; + priv->txbbgain_table[16].txbbgain_value = 0x32c000cb; priv->txbbgain_table[17].txbb_iq_amplifygain = -5; - priv->txbbgain_table[17].txbbgain_value=0x300000c0; + priv->txbbgain_table[17].txbbgain_value = 0x300000c0; priv->txbbgain_table[18].txbb_iq_amplifygain = -6; - priv->txbbgain_table[18].txbbgain_value=0x2d4000b5; + priv->txbbgain_table[18].txbbgain_value = 0x2d4000b5; priv->txbbgain_table[19].txbb_iq_amplifygain = -7; - priv->txbbgain_table[19].txbbgain_value=0x2ac000ab; + priv->txbbgain_table[19].txbbgain_value = 0x2ac000ab; priv->txbbgain_table[20].txbb_iq_amplifygain = -8; - priv->txbbgain_table[20].txbbgain_value=0x288000a2; + priv->txbbgain_table[20].txbbgain_value = 0x288000a2; priv->txbbgain_table[21].txbb_iq_amplifygain = -9; - priv->txbbgain_table[21].txbbgain_value=0x26000098; + priv->txbbgain_table[21].txbbgain_value = 0x26000098; priv->txbbgain_table[22].txbb_iq_amplifygain = -10; - priv->txbbgain_table[22].txbbgain_value=0x24000090; + priv->txbbgain_table[22].txbbgain_value = 0x24000090; priv->txbbgain_table[23].txbb_iq_amplifygain = -11; - priv->txbbgain_table[23].txbbgain_value=0x22000088; + priv->txbbgain_table[23].txbbgain_value = 0x22000088; priv->txbbgain_table[24].txbb_iq_amplifygain = -12; - priv->txbbgain_table[24].txbbgain_value=0x20000080; + priv->txbbgain_table[24].txbbgain_value = 0x20000080; priv->txbbgain_table[25].txbb_iq_amplifygain = -13; - priv->txbbgain_table[25].txbbgain_value=0x1a00006c; + priv->txbbgain_table[25].txbbgain_value = 0x1a00006c; priv->txbbgain_table[26].txbb_iq_amplifygain = -14; - priv->txbbgain_table[26].txbbgain_value=0x1c800072; + priv->txbbgain_table[26].txbbgain_value = 0x1c800072; priv->txbbgain_table[27].txbb_iq_amplifygain = -15; - priv->txbbgain_table[27].txbbgain_value=0x18000060; + priv->txbbgain_table[27].txbbgain_value = 0x18000060; priv->txbbgain_table[28].txbb_iq_amplifygain = -16; - priv->txbbgain_table[28].txbbgain_value=0x19800066; + priv->txbbgain_table[28].txbbgain_value = 0x19800066; priv->txbbgain_table[29].txbb_iq_amplifygain = -17; - priv->txbbgain_table[29].txbbgain_value=0x15800056; + priv->txbbgain_table[29].txbbgain_value = 0x15800056; priv->txbbgain_table[30].txbb_iq_amplifygain = -18; - priv->txbbgain_table[30].txbbgain_value=0x26c0005b; + priv->txbbgain_table[30].txbbgain_value = 0x26c0005b; priv->txbbgain_table[31].txbb_iq_amplifygain = -19; - priv->txbbgain_table[31].txbbgain_value=0x14400051; + priv->txbbgain_table[31].txbbgain_value = 0x14400051; priv->txbbgain_table[32].txbb_iq_amplifygain = -20; - priv->txbbgain_table[32].txbbgain_value=0x24400051; + priv->txbbgain_table[32].txbbgain_value = 0x24400051; priv->txbbgain_table[33].txbb_iq_amplifygain = -21; - priv->txbbgain_table[33].txbbgain_value=0x1300004c; + priv->txbbgain_table[33].txbbgain_value = 0x1300004c; priv->txbbgain_table[34].txbb_iq_amplifygain = -22; - priv->txbbgain_table[34].txbbgain_value=0x12000048; + priv->txbbgain_table[34].txbbgain_value = 0x12000048; priv->txbbgain_table[35].txbb_iq_amplifygain = -23; - priv->txbbgain_table[35].txbbgain_value=0x11000044; + priv->txbbgain_table[35].txbbgain_value = 0x11000044; priv->txbbgain_table[36].txbb_iq_amplifygain = -24; - priv->txbbgain_table[36].txbbgain_value=0x10000040; + priv->txbbgain_table[36].txbbgain_value = 0x10000040; /* * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29 @@ -1374,7 +1293,7 @@ static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev) * can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w * 3-wire by driver causes RF to go into a wrong state. */ - if(priv->ieee80211->FwRWRF) + if (priv->ieee80211->FwRWRF) priv->btxpower_tracking = TRUE; else priv->btxpower_tracking = FALSE; @@ -1382,54 +1301,46 @@ static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev) priv->btxpower_trackingInit = FALSE; } - void dm_initialize_txpower_tracking(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - if(priv->bDcut == TRUE) + + if (priv->bDcut == TRUE) dm_InitializeTXPowerTracking_TSSI(dev); else dm_InitializeTXPowerTracking_ThermalMeter(dev); } /* dm_InitializeTXPowerTracking */ - static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); static u32 tx_power_track_counter; - if(!priv->btxpower_tracking) + if (!priv->btxpower_tracking) return; - else - { - if((tx_power_track_counter % 30 == 0)&&(tx_power_track_counter != 0)) - { - queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0); + else { + if ((tx_power_track_counter % 30 == 0) && (tx_power_track_counter != 0)) { + queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); } tx_power_track_counter++; } - } - static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); static u8 TM_Trigger; - /*DbgPrint("dm_CheckTXPowerTracking() \n");*/ - if(!priv->btxpower_tracking) + /*DbgPrint("dm_CheckTXPowerTracking()\n");*/ + if (!priv->btxpower_tracking) return; - else - { - if(priv->txpower_count <= 2) - { + else { + if (priv->txpower_count <= 2) { priv->txpower_count++; return; } } - if(!TM_Trigger) - { + if (!TM_Trigger) { /* * Attention!! You have to write all 12bits of data to RF, or it may cause RF to crash * actually write reg0x02 bit1=0, then bit1=1. @@ -1441,25 +1352,22 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); TM_Trigger = 1; return; - } - else - { + } else { /*DbgPrint("Schedule TxPowerTrackingWorkItem\n");*/ - queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0); + queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); TM_Trigger = 0; } } - static void dm_check_txpower_tracking(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); /*static u32 tx_power_track_counter = 0;*/ -#ifdef RTL8190P +#ifdef RTL8190P dm_CheckTXPowerTracking_TSSI(dev); #else - if(priv->bDcut == TRUE) + if (priv->bDcut == TRUE) dm_CheckTXPowerTracking_TSSI(dev); else dm_CheckTXPowerTracking_ThermalMeter(dev); @@ -1467,17 +1375,17 @@ static void dm_check_txpower_tracking(struct net_device *dev) } /* dm_CheckTXPowerTracking */ - static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool bInCH14) { u32 TempVal; struct r8192_priv *priv = ieee80211_priv(dev); + /* Write 0xa22 0xa23 */ TempVal = 0; - if(!bInCH14){ + if (!bInCH14) { /* Write 0xa22 0xa23 */ TempVal = priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[0] + - (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8) ; + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8); rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); /* Write 0xa24 ~ 0xa27 */ @@ -1488,14 +1396,12 @@ static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool bInCH14) rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); /* Write 0xa28 0xa29 */ TempVal = priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[6] + - (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8) ; + (priv->cck_txbbgain_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8); rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); - } - else - { + } else { TempVal = priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[0] + - (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8) ; + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[1]<<8); rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); /* Write 0xa24 ~ 0xa27 */ @@ -1506,25 +1412,22 @@ static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool bInCH14) rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); /* Write 0xa28 0xa29 */ TempVal = priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[6] + - (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8) ; + (priv->cck_txbbgain_ch14_table[priv->cck_present_attentuation].ccktxbb_valuearray[7]<<8); rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); } - - } -static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH14) +static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH14) { u32 TempVal; struct r8192_priv *priv = ieee80211_priv(dev); TempVal = 0; - if(!bInCH14) - { + if (!bInCH14) { /* Write 0xa22 0xa23 */ TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] + - (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8) ; + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8); rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter1, TempVal); @@ -1538,18 +1441,16 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH rCCK0_TxFilter2, TempVal); /* Write 0xa28 0xa29 */ TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] + - (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8) ; + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8); rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_DebugPort, TempVal); - } - else - { + } else { /*priv->CCKTxPowerAdjustCntNotCh14++; cosa add for debug.*/ /* Write 0xa22 0xa23 */ TempVal = CCKSwingTable_Ch14[priv->CCK_index][0] + - (CCKSwingTable_Ch14[priv->CCK_index][1]<<8) ; + (CCKSwingTable_Ch14[priv->CCK_index][1]<<8); rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", @@ -1564,7 +1465,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH rCCK0_TxFilter2, TempVal); /* Write 0xa28 0xa29 */ TempVal = CCKSwingTable_Ch14[priv->CCK_index][6] + - (CCKSwingTable_Ch14[priv->CCK_index][7]<<8) ; + (CCKSwingTable_Ch14[priv->CCK_index][7]<<8); rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", @@ -1572,20 +1473,17 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH } } - - void dm_cck_txpower_adjust(struct net_device *dev, bool binch14) { /* dm_CCKTxPowerAdjust */ - struct r8192_priv *priv = ieee80211_priv(dev); - if(priv->bDcut == TRUE) + + if (priv->bDcut == TRUE) dm_CCKTxPowerAdjust_TSSI(dev, binch14); else dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14); } - -#ifndef RTL8192U +#ifndef RTL8192U static void dm_txpower_reset_recovery( struct net_device *dev ) @@ -1594,16 +1492,16 @@ static void dm_txpower_reset_recovery( RT_TRACE(COMP_POWER_TRACKING, "Start Reset Recovery ==>\n"); rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFA_txPowerTrackingIndex is %x\n",priv->rfa_txpowertrackingindex); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF A I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbb_iq_amplifygain); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: CCK Attenuation is %d dB\n",priv->cck_present_attentuation); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n", priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFA_txPowerTrackingIndex is %x\n", priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF A I/Q Amplify Gain is %ld\n", priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbb_iq_amplifygain); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: CCK Attenuation is %d dB\n", priv->cck_present_attentuation); dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFC_txPowerTrackingIndex is %x\n",priv->rfc_txpowertrackingindex); - RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF C I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbb_iq_amplifygain); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n", priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFC_txPowerTrackingIndex is %x\n", priv->rfc_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF C I/Q Amplify Gain is %ld\n", priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbb_iq_amplifygain); } /* dm_TXPowerResetRecovery */ @@ -1612,25 +1510,25 @@ void dm_restore_dynamic_mechanism_state(struct net_device *dev) struct r8192_priv *priv = ieee80211_priv(dev); u32 reg_ratr = priv->rate_adaptive.last_ratr; - if(!priv->up) - { + if (!priv->up) { RT_TRACE(COMP_RATE, "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n"); return; } /* Restore previous state for rate adaptive */ - if(priv->rate_adaptive.rate_adaptive_disabled) + if (priv->rate_adaptive.rate_adaptive_disabled) return; /* TODO: Only 11n mode is implemented currently, */ - if(!(priv->ieee80211->mode==WIRELESS_MODE_N_24G || - priv->ieee80211->mode==WIRELESS_MODE_N_5G)) - return; + if (!(priv->ieee80211->mode == WIRELESS_MODE_N_24G || + priv->ieee80211->mode == WIRELESS_MODE_N_5G)) + return; + { /* 2007/11/15 MH Copy from 8190PCI. */ u32 ratr_value; + ratr_value = reg_ratr; - if(priv->rf_type == RF_1T2R) /* 1T2R, Spatial Stream 2 should be disabled */ - { + if (priv->rf_type == RF_1T2R) { /* 1T2R, Spatial Stream 2 should be disabled */ ratr_value &= ~(RATE_ALL_OFDM_2SS); /*DbgPrint("HW_VAR_TATR_0 from 0x%x ==> 0x%x\n", ((pu4Byte)(val))[0], ratr_value);*/ } @@ -1653,7 +1551,7 @@ static void dm_bb_initialgain_restore(struct net_device *dev) struct r8192_priv *priv = ieee80211_priv(dev); u32 bit_mask = 0x7f; /* Bit0~ Bit6 */ - if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) return; /* Disable Initial Gain */ @@ -1666,18 +1564,17 @@ static void dm_bb_initialgain_restore(struct net_device *dev) bit_mask = bMaskByte2; rtl8192_setBBreg(dev, rCCK0_CCA, bit_mask, (u32)priv->initgain_backup.cca); - RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n",priv->initgain_backup.xaagccore1); - RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc58 is %x\n",priv->initgain_backup.xbagccore1); - RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc60 is %x\n",priv->initgain_backup.xcagccore1); - RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc68 is %x\n",priv->initgain_backup.xdagccore1); - RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n",priv->initgain_backup.cca); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n", priv->initgain_backup.xaagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc58 is %x\n", priv->initgain_backup.xbagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc60 is %x\n", priv->initgain_backup.xcagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc68 is %x\n", priv->initgain_backup.xdagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n", priv->initgain_backup.cca); /* Enable Initial Gain */ /*PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x100);*/ rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); /* Only clear byte 1 and rewrite. */ } /* dm_BBInitialGainRestore */ - void dm_backup_dynamic_mechanism_state(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); @@ -1690,13 +1587,12 @@ void dm_backup_dynamic_mechanism_state(struct net_device *dev) } /* DM_BackupDynamicMechanismState */ - static void dm_bb_initialgain_backup(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); u32 bit_mask = bMaskByte0; /* Bit0~ Bit6 */ - if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) return; /*PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800);*/ @@ -1708,11 +1604,11 @@ static void dm_bb_initialgain_backup(struct net_device *dev) bit_mask = bMaskByte2; priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, bit_mask); - RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n",priv->initgain_backup.xaagccore1); - RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc58 is %x\n",priv->initgain_backup.xbagccore1); - RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc60 is %x\n",priv->initgain_backup.xcagccore1); - RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc68 is %x\n",priv->initgain_backup.xdagccore1); - RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xa0a is %x\n",priv->initgain_backup.cca); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n", priv->initgain_backup.xaagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc58 is %x\n", priv->initgain_backup.xbagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc60 is %x\n", priv->initgain_backup.xcagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc68 is %x\n", priv->initgain_backup.xdagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xa0a is %x\n", priv->initgain_backup.cca); } /* dm_BBInitialGainBakcup */ @@ -1737,67 +1633,44 @@ static void dm_bb_initialgain_backup(struct net_device *dev) void dm_change_dynamic_initgain_thresh(struct net_device *dev, u32 dm_type, u32 dm_value) { - if (dm_type == DIG_TYPE_THRESH_HIGH) - { + if (dm_type == DIG_TYPE_THRESH_HIGH) { dm_digtable.rssi_high_thresh = dm_value; - } - else if (dm_type == DIG_TYPE_THRESH_LOW) - { + } else if (dm_type == DIG_TYPE_THRESH_LOW) { dm_digtable.rssi_low_thresh = dm_value; - } - else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) - { + } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) { dm_digtable.rssi_high_power_highthresh = dm_value; - } - else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) - { + } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) { dm_digtable.rssi_high_power_highthresh = dm_value; - } - else if (dm_type == DIG_TYPE_ENABLE) - { + } else if (dm_type == DIG_TYPE_ENABLE) { dm_digtable.dig_state = DM_STA_DIG_MAX; dm_digtable.dig_enable_flag = true; - } - else if (dm_type == DIG_TYPE_DISABLE) - { + } else if (dm_type == DIG_TYPE_DISABLE) { dm_digtable.dig_state = DM_STA_DIG_MAX; dm_digtable.dig_enable_flag = false; - } - else if (dm_type == DIG_TYPE_DBG_MODE) - { - if(dm_value >= DM_DBG_MAX) + } else if (dm_type == DIG_TYPE_DBG_MODE) { + if (dm_value >= DM_DBG_MAX) dm_value = DM_DBG_OFF; dm_digtable.dbg_mode = (u8)dm_value; - } - else if (dm_type == DIG_TYPE_RSSI) - { - if(dm_value > 100) + } else if (dm_type == DIG_TYPE_RSSI) { + if (dm_value > 100) dm_value = 30; dm_digtable.rssi_val = (long)dm_value; - } - else if (dm_type == DIG_TYPE_ALGORITHM) - { + } else if (dm_type == DIG_TYPE_ALGORITHM) { if (dm_value >= DIG_ALGO_MAX) dm_value = DIG_ALGO_BY_FALSE_ALARM; - if(dm_digtable.dig_algorithm != (u8)dm_value) + if (dm_digtable.dig_algorithm != (u8)dm_value) dm_digtable.dig_algorithm_switch = 1; dm_digtable.dig_algorithm = (u8)dm_value; - } - else if (dm_type == DIG_TYPE_BACKOFF) - { - if(dm_value > 30) + } else if (dm_type == DIG_TYPE_BACKOFF) { + if (dm_value > 30) dm_value = 30; dm_digtable.backoff_val = (u8)dm_value; - } - else if(dm_type == DIG_TYPE_RX_GAIN_MIN) - { - if(dm_value == 0) + } else if (dm_type == DIG_TYPE_RX_GAIN_MIN) { + if (dm_value == 0) dm_value = 0x1; dm_digtable.rx_gain_range_min = (u8)dm_value; - } - else if(dm_type == DIG_TYPE_RX_GAIN_MAX) - { - if(dm_value > 0x50) + } else if (dm_type == DIG_TYPE_RX_GAIN_MAX) { + if (dm_value > 0x50) dm_value = 0x50; dm_digtable.rx_gain_range_max = (u8)dm_value; } @@ -1842,14 +1715,13 @@ static void dm_dig_init(struct net_device *dev) dm_digtable.rssi_val = 50; /* for new dig debug rssi value */ dm_digtable.backoff_val = DM_DIG_BACKOFF; dm_digtable.rx_gain_range_max = DM_DIG_MAX; - if(priv->CustomerID == RT_CID_819x_Netcore) + if (priv->CustomerID == RT_CID_819x_Netcore) dm_digtable.rx_gain_range_min = DM_DIG_MIN_Netcore; else dm_digtable.rx_gain_range_min = DM_DIG_MIN; } /* dm_dig_init */ - /*----------------------------------------------------------------------------- * Function: dm_ctrl_initgain_byrssi() * @@ -1869,20 +1741,18 @@ static void dm_dig_init(struct net_device *dev) *---------------------------------------------------------------------------*/ static void dm_ctrl_initgain_byrssi(struct net_device *dev) { - if (dm_digtable.dig_enable_flag == false) return; - if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) + if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) dm_ctrl_initgain_byrssi_by_fwfalse_alarm(dev); - else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + else if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) dm_ctrl_initgain_byrssi_by_driverrssi(dev); /* ; */ else return; } - static void dm_ctrl_initgain_byrssi_by_driverrssi( struct net_device *dev) { @@ -1893,33 +1763,33 @@ static void dm_ctrl_initgain_byrssi_by_driverrssi( if (dm_digtable.dig_enable_flag == false) return; - /*DbgPrint("Dig by Sw Rssi \n");*/ - if(dm_digtable.dig_algorithm_switch) /* if switched algorithm, we have to disable FW Dig. */ + /*DbgPrint("Dig by Sw Rssi\n");*/ + if (dm_digtable.dig_algorithm_switch) /* if switched algorithm, we have to disable FW Dig. */ fw_dig = 0; - if(fw_dig <= 3) - { /* execute several times to make sure the FW Dig is disabled */ + + if (fw_dig <= 3) { /* execute several times to make sure the FW Dig is disabled */ /* FW DIG Off */ - for(i=0; i<3; i++) + for (i = 0; i < 3; i++) rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); /* Only clear byte 1 and rewrite. */ fw_dig++; dm_digtable.dig_state = DM_STA_DIG_OFF; /* fw dig off. */ } - if(priv->ieee80211->state == IEEE80211_LINKED) + if (priv->ieee80211->state == IEEE80211_LINKED) dm_digtable.cur_connect_state = DIG_CONNECT; else dm_digtable.cur_connect_state = DIG_DISCONNECT; - /*DbgPrint("DM_DigTable.PreConnectState = %d, DM_DigTable.CurConnectState = %d \n", + /*DbgPrint("DM_DigTable.PreConnectState = %d, DM_DigTable.CurConnectState = %d\n", DM_DigTable.PreConnectState, DM_DigTable.CurConnectState);*/ - if(dm_digtable.dbg_mode == DM_DBG_OFF) + if (dm_digtable.dbg_mode == DM_DBG_OFF) dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb; - /*DbgPrint("DM_DigTable.Rssi_val = %d \n", DM_DigTable.Rssi_val);*/ + /*DbgPrint("DM_DigTable.Rssi_val = %d\n", DM_DigTable.Rssi_val);*/ dm_initial_gain(dev); dm_pd_th(dev); dm_cs_ratio(dev); - if(dm_digtable.dig_algorithm_switch) + if (dm_digtable.dig_algorithm_switch) dm_digtable.dig_algorithm_switch = 0; dm_digtable.pre_connect_state = dm_digtable.cur_connect_state; @@ -1935,11 +1805,10 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( if (dm_digtable.dig_enable_flag == false) return; - if(dm_digtable.dig_algorithm_switch) - { + if (dm_digtable.dig_algorithm_switch) { dm_digtable.dig_state = DM_STA_DIG_MAX; /* Fw DIG On. */ - for(i=0; i<3; i++) + for (i = 0; i < 3; i++) rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); /* Only clear byte 1 and rewrite.*/ dm_digtable.dig_algorithm_switch = 0; } @@ -1950,9 +1819,8 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( /* For smooth, we can not change DIG state. */ if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) && (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh)) - { return; - } + /*DbgPrint("Dig by Fw False Alarm\n");*/ /*if (DM_DigTable.Dig_State == DM_STA_DIG_OFF)*/ /*DbgPrint("DIG Check\n\r RSSI=%d LOW=%d HIGH=%d STATE=%d", @@ -1960,17 +1828,13 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( DM_DigTable.RssiHighThresh, DM_DigTable.Dig_State);*/ /* 1. When RSSI decrease, We have to judge if it is smaller than a threshold and then execute the step below. */ - if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh)) - { + if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh)) { /* 2008/02/05 MH When we execute silent reset, the DIG PHY parameters will be reset to init value. We must prevent the condition. */ if (dm_digtable.dig_state == DM_STA_DIG_OFF && - (priv->reset_count == reset_cnt)) - { + (priv->reset_count == reset_cnt)) { return; - } - else - { + } else { reset_cnt = priv->reset_count; } @@ -1988,8 +1852,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17); /* 1.3 Lower PD_TH for OFDM. */ - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { /* * 2008/01/11 MH 40MHZ 90/92 register are not the same. * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. @@ -2001,8 +1864,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( else PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x40); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); /* 1.4 Lower CS ratio for CCK. */ @@ -2016,18 +1878,14 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( /* 2. When RSSI increase, We have to judge if it is larger than a threshold and then execute the step below. */ - if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh)) - { + if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh)) { u8 reset_flag = 0; if (dm_digtable.dig_state == DM_STA_DIG_ON && - (priv->reset_count == reset_cnt)) - { + (priv->reset_count == reset_cnt)) { dm_ctrl_initgain_byrssi_highpwr(dev); return; - } - else - { + } else { if (priv->reset_count != reset_cnt) reset_flag = 1; @@ -2041,15 +1899,12 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( * 2.1 Set initial gain. * 2008/02/26 MH SD3-Jerry suggest to prevent dirty environment. */ - if (reset_flag == 1) - { + if (reset_flag == 1) { write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c); write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x2c); write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x2c); write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x2c); - } - else - { + } else { write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x20); write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x20); write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x20); @@ -2057,8 +1912,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( } /* 2.2 Higher PD_TH for OFDM. */ - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { /* * 2008/01/11 MH 40MHZ 90/92 register are not the same. * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. @@ -2071,8 +1925,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( else PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x42); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); /* 2.3 Higher CS ratio for CCK. */ @@ -2093,7 +1946,6 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( } /* dm_CtrlInitGainByRssi */ - /*----------------------------------------------------------------------------- * Function: dm_ctrl_initgain_byrssi_highpwr() * @@ -2119,9 +1971,7 @@ static void dm_ctrl_initgain_byrssi_highpwr( /* For smooth, we can not change high power DIG state in the range. */ if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_high_power_lowthresh) && (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_highthresh)) - { return; - } /* * 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if @@ -2129,8 +1979,7 @@ static void dm_ctrl_initgain_byrssi_highpwr( * * 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue. */ - if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh) - { + if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh) { if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON && (priv->reset_count == reset_cnt_highpwr)) return; @@ -2138,39 +1987,32 @@ static void dm_ctrl_initgain_byrssi_highpwr( dm_digtable.dig_highpwr_state = DM_STA_DIG_ON; /* 3.1 Higher PD_TH for OFDM for high power state. */ - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x43); - } - else - { - if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF&& + } else { + if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF && (priv->reset_count == reset_cnt_highpwr)) return; else dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF; if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh && - priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) - { + priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) { /* 3.2 Recover PD_TH for OFDM for normal power region. */ - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); } } @@ -2179,51 +2021,42 @@ static void dm_ctrl_initgain_byrssi_highpwr( } /* dm_CtrlInitGainByRssiHighPwr */ - static void dm_initial_gain( struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - u8 initial_gain=0; + u8 initial_gain = 0; static u8 initialized, force_write; static u32 reset_cnt; u8 tmp; - if(dm_digtable.dig_algorithm_switch) - { + if (dm_digtable.dig_algorithm_switch) { initialized = 0; reset_cnt = 0; } - if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) - { - if(dm_digtable.cur_connect_state == DIG_CONNECT) - { - if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max) + if (dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) { + if (dm_digtable.cur_connect_state == DIG_CONNECT) { + if ((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max) dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max; - else if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min) + else if ((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min) dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min; else dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val; - } - else /* current state is disconnected */ - { - if(dm_digtable.cur_ig_value == 0) + } else { /* current state is disconnected */ + if (dm_digtable.cur_ig_value == 0) dm_digtable.cur_ig_value = priv->DefaultInitialGain[0]; else dm_digtable.cur_ig_value = dm_digtable.pre_ig_value; } - } - else /* disconnected -> connected or connected -> disconnected */ - { + } else { /* disconnected -> connected or connected -> disconnected */ dm_digtable.cur_ig_value = priv->DefaultInitialGain[0]; dm_digtable.pre_ig_value = 0; } /*DbgPrint("DM_DigTable.CurIGValue = 0x%x, DM_DigTable.PreIGValue = 0x%x\n", DM_DigTable.CurIGValue, DM_DigTable.PreIGValue);*/ /* if silent reset happened, we should rewrite the values back */ - if(priv->reset_count != reset_cnt) - { + if (priv->reset_count != reset_cnt) { force_write = 1; reset_cnt = priv->reset_count; } @@ -2233,9 +2066,8 @@ static void dm_initial_gain( force_write = 1; { - if((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value) - || !initialized || force_write) - { + if ((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value) + || !initialized || force_write) { initial_gain = (u8)dm_digtable.cur_ig_value; /*DbgPrint("Write initial gain = 0x%x\n", initial_gain);*/ /* Set initial gain. */ @@ -2257,16 +2089,13 @@ static void dm_pd_th( static u8 initialized, force_write; static u32 reset_cnt; - if(dm_digtable.dig_algorithm_switch) - { + if (dm_digtable.dig_algorithm_switch) { initialized = 0; reset_cnt = 0; } - if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) - { - if(dm_digtable.cur_connect_state == DIG_CONNECT) - { + if (dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) { + if (dm_digtable.cur_connect_state == DIG_CONNECT) { if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh) dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER; else if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)) @@ -2276,34 +2105,26 @@ static void dm_pd_th( dm_digtable.curpd_thstate = DIG_PD_AT_NORMAL_POWER; else dm_digtable.curpd_thstate = dm_digtable.prepd_thstate; - } - else - { + } else { dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; } - } - else /* disconnected -> connected or connected -> disconnected */ - { + } else { /* disconnected -> connected or connected -> disconnected */ dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; } /* if silent reset happened, we should rewrite the values back */ - if(priv->reset_count != reset_cnt) - { + if (priv->reset_count != reset_cnt) { force_write = 1; reset_cnt = priv->reset_count; } { - if((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) || - (initialized<=3) || force_write) - { + if ((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) || + (initialized <= 3) || force_write) { /*DbgPrint("Write PD_TH state = %d\n", DM_DigTable.CurPD_THState);*/ - if(dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) - { + if (dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) { /* Lower PD_TH for OFDM. */ - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { /* * 2008/01/11 MH 40MHZ 90/92 register are not the same. * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. @@ -2312,15 +2133,11 @@ static void dm_pd_th( /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x40); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); - } - else if(dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER) - { + } else if (dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER) { /* Higher PD_TH for OFDM. */ - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { /* * 2008/01/11 MH 40MHZ 90/92 register are not the same. * 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same. @@ -2329,25 +2146,20 @@ static void dm_pd_th( /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); - } - else if(dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) - { + } else if (dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) { /* Higher PD_TH for OFDM for high power state. */ - if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) - { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); */ - } - else + } else write_nic_byte(dev, rOFDM0_RxDetector1, 0x43); } dm_digtable.prepd_thstate = dm_digtable.curpd_thstate; - if(initialized <= 3) + if (initialized <= 3) initialized++; force_write = 0; } @@ -2361,53 +2173,39 @@ static void dm_cs_ratio( static u8 initialized, force_write; static u32 reset_cnt; - if(dm_digtable.dig_algorithm_switch) - { + if (dm_digtable.dig_algorithm_switch) { initialized = 0; reset_cnt = 0; } - if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) - { - if(dm_digtable.cur_connect_state == DIG_CONNECT) - { + if (dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) { + if (dm_digtable.cur_connect_state == DIG_CONNECT) { if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)) dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh)) dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER; else dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state; - } - else - { + } else { dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; } - } - else /* disconnected -> connected or connected -> disconnected */ - { + } else /* disconnected -> connected or connected -> disconnected */ dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; - } /* if silent reset happened, we should rewrite the values back */ - if(priv->reset_count != reset_cnt) - { + if (priv->reset_count != reset_cnt) { force_write = 1; reset_cnt = priv->reset_count; } - { - if((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) || - !initialized || force_write) - { + if ((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) || + !initialized || force_write) { /*DbgPrint("Write CS_ratio state = %d\n", DM_DigTable.CurCS_ratioState);*/ - if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER) - { + if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER) { /* Lower CS ratio for CCK. */ write_nic_byte(dev, 0xa0a, 0x08); - } - else if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER) - { + } else if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER) { /* Higher CS ratio for CCK. */ write_nic_byte(dev, 0xa0a, 0xcd); } @@ -2444,34 +2242,27 @@ static void dm_check_edca_turbo( * Do not be Turbo if it's under WiFi config and Qos Enabled, because the EDCA parameters * should follow the settings from QAP. By Bruce, 2007-12-07. */ - if(priv->ieee80211->state != IEEE80211_LINKED) + if (priv->ieee80211->state != IEEE80211_LINKED) goto dm_CheckEdcaTurbo_EXIT; /* We do not turn on EDCA turbo mode for some AP that has IOT issue */ - if(priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO) + if (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO) goto dm_CheckEdcaTurbo_EXIT; - /*printk("========>%s():bis_any_nonbepkts is %d\n",__func__,priv->bis_any_nonbepkts);*/ + /*printk("========>%s():bis_any_nonbepkts is %d\n", __func__, priv->bis_any_nonbepkts);*/ /* Check the status for current condition. */ - if(!priv->ieee80211->bis_any_nonbepkts) - { + if (!priv->ieee80211->bis_any_nonbepkts) { curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; /* For RT-AP, we needs to turn it on when Rx>Tx */ - if(curRxOkCnt > 4*curTxOkCnt) - { + if (curRxOkCnt > 4*curTxOkCnt) { /*printk("%s():curRxOkCnt > 4*curTxOkCnt\n");*/ - if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) - { + if (!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]); priv->bis_cur_rdlstate = true; } - } - else - { - + } else { /*printk("%s():curRxOkCnt < 4*curTxOkCnt\n");*/ - if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) - { + if (priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) { write_nic_dword(dev, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]); priv->bis_cur_rdlstate = false; } @@ -2479,16 +2270,12 @@ static void dm_check_edca_turbo( } priv->bcurrent_turbo_EDCA = true; - } - else - { + } else { /* * Turn Off EDCA turbo here. * Restore original EDCA according to the declaration of AP. */ - if(priv->bcurrent_turbo_EDCA) - { - + if (priv->bcurrent_turbo_EDCA) { { u8 u1bAIFS; u32 u4bAcParam; @@ -2497,10 +2284,10 @@ static void dm_check_edca_turbo( /* For Each time updating EDCA parameter, reset EDCA turbo mode status. */ dm_init_edca_turbo(dev); - u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime; - u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0]))<< AC_PARAM_TXOP_LIMIT_OFFSET)| - (((u32)(qos_parameters->cw_max[0]))<< AC_PARAM_ECW_MAX_OFFSET)| - (((u32)(qos_parameters->cw_min[0]))<< AC_PARAM_ECW_MIN_OFFSET)| + u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime; + u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0])) << AC_PARAM_TXOP_LIMIT_OFFSET)| + (((u32)(qos_parameters->cw_max[0])) << AC_PARAM_ECW_MAX_OFFSET)| + (((u32)(qos_parameters->cw_min[0])) << AC_PARAM_ECW_MIN_OFFSET)| ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET)); /*write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);*/ write_nic_dword(dev, EDCAPARA_BE, u4bAcParam); @@ -2514,17 +2301,16 @@ static void dm_check_edca_turbo( PACI_AIFSN pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]); u8 AcmCtrl; + read_nic_byte(dev, AcmHwCtrl, &AcmCtrl); - if(pAciAifsn->f.ACM) - { /* ACM bit is 1. */ + + if (pAciAifsn->f.ACM) { /* ACM bit is 1. */ AcmCtrl |= AcmHw_BeqEn; - } - else - { /* ACM bit is 0. */ + } else { /* ACM bit is 0. */ AcmCtrl &= (~AcmHw_BeqEn); } - RT_TRACE(COMP_QOS,"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl) ; + RT_TRACE(COMP_QOS, "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl); write_nic_byte(dev, AcmHwCtrl, AcmCtrl); } } @@ -2532,7 +2318,6 @@ static void dm_check_edca_turbo( } } - dm_CheckEdcaTurbo_EXIT: /* Set variables for next time. */ priv->ieee80211->bis_any_nonbepkts = false; @@ -2557,8 +2342,7 @@ static void dm_ctstoself(struct net_device *dev) unsigned long curTxOkCnt = 0; unsigned long curRxOkCnt = 0; - if(priv->ieee80211->bCTSToSelfEnable != TRUE) - { + if (priv->ieee80211->bCTSToSelfEnable != TRUE) { pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF; return; } @@ -2568,17 +2352,13 @@ static void dm_ctstoself(struct net_device *dev) 3. <50 disable, >55 enable */ - if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) - { + if (pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) { curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; - if(curRxOkCnt > 4*curTxOkCnt) /* downlink, disable CTS to self */ - { + if (curRxOkCnt > 4*curTxOkCnt) { /* downlink, disable CTS to self */ pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF; /*DbgPrint("dm_CTSToSelf() ==> CTS to self disabled -- downlink\n");*/ - } - else /* uplink */ - { + } else { /* uplink */ pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF; } @@ -2608,13 +2388,11 @@ static void dm_check_pbc_gpio(struct net_device *dev) struct r8192_priv *priv = ieee80211_priv(dev); u8 tmp1byte; - read_nic_byte(dev, GPI, &tmp1byte); - if(tmp1byte == 0xff) + if (tmp1byte == 0xff) return; - if (tmp1byte&BIT6 || tmp1byte&BIT0) - { + if (tmp1byte&BIT6 || tmp1byte&BIT0) { /* * Here we only set bPbcPressed to TRUE * After trigger PBC, the variable will be set to FALSE @@ -2643,26 +2421,24 @@ static void dm_check_pbc_gpio(struct net_device *dev) *---------------------------------------------------------------------------*/ void dm_rf_pathcheck_workitemcallback(struct work_struct *work) { - struct delayed_work *dwork = container_of(work,struct delayed_work,work); - struct r8192_priv *priv = container_of(dwork,struct r8192_priv,rfpath_check_wq); - struct net_device *dev =priv->ieee80211->dev; - /*bool bactually_set = false;*/ + struct delayed_work *dwork = container_of(work, struct delayed_work, work); + struct r8192_priv *priv = container_of(dwork, struct r8192_priv, rfpath_check_wq); + struct net_device *dev = priv->ieee80211->dev; + /*bool bactually_set = false;*/ u8 rfpath = 0, i; - /* 2008/01/30 MH After discussing with SD3 Jerry, 0xc04/0xd04 register will always be the same. We only read 0xc04 now. */ read_nic_byte(dev, 0xc04, &rfpath); /* Check Bit 0-3, it means if RF A-D is enabled. */ - for (i = 0; i < RF90_PATH_MAX; i++) - { + for (i = 0; i < RF90_PATH_MAX; i++) { if (rfpath & (0x01<brfpath_rxenable[i] = 1; else priv->brfpath_rxenable[i] = 0; } - if(!DM_RxPathSelTable.Enable) + if (!DM_RxPathSelTable.Enable) return; dm_rxpath_sel_byrssi(dev); @@ -2672,17 +2448,17 @@ static void dm_init_rxpath_selection(struct net_device *dev) { u8 i; struct r8192_priv *priv = ieee80211_priv(dev); + DM_RxPathSelTable.Enable = 1; /* default enabled */ DM_RxPathSelTable.SS_TH_low = RxPathSelection_SS_TH_low; DM_RxPathSelTable.diff_TH = RxPathSelection_diff_TH; - if(priv->CustomerID == RT_CID_819x_Netcore) + if (priv->CustomerID == RT_CID_819x_Netcore) DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; else DM_RxPathSelTable.cck_method = CCK_Rx_Version_1; DM_RxPathSelTable.DbgMode = DM_DBG_OFF; DM_RxPathSelTable.disabledRF = 0; - for(i=0; i<4; i++) - { + for (i = 0; i < 4; i++) { DM_RxPathSelTable.rf_rssi[i] = 50; DM_RxPathSelTable.cck_pwdb_sta[i] = -64; DM_RxPathSelTable.rf_enable_rssi_th[i] = 100; @@ -2692,22 +2468,21 @@ static void dm_init_rxpath_selection(struct net_device *dev) static void dm_rxpath_sel_byrssi(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - u8 i, max_rssi_index=0, min_rssi_index=0, sec_rssi_index=0, rf_num=0; - u8 tmp_max_rssi=0, tmp_min_rssi=0, tmp_sec_rssi=0; - u8 cck_default_Rx=0x2; /* RF-C */ - u8 cck_optional_Rx=0x3; /* RF-D */ - long tmp_cck_max_pwdb=0, tmp_cck_min_pwdb=0, tmp_cck_sec_pwdb=0; - u8 cck_rx_ver2_max_index=0, cck_rx_ver2_min_index=0, cck_rx_ver2_sec_index=0; + u8 i, max_rssi_index = 0, min_rssi_index = 0, sec_rssi_index = 0, rf_num = 0; + u8 tmp_max_rssi = 0, tmp_min_rssi = 0, tmp_sec_rssi = 0; + u8 cck_default_Rx = 0x2; /* RF-C */ + u8 cck_optional_Rx = 0x3; /* RF-D */ + long tmp_cck_max_pwdb = 0, tmp_cck_min_pwdb = 0, tmp_cck_sec_pwdb = 0; + u8 cck_rx_ver2_max_index = 0, cck_rx_ver2_min_index = 0, cck_rx_ver2_sec_index = 0; u8 cur_rf_rssi; long cur_cck_pwdb; static u8 disabled_rf_cnt, cck_Rx_Path_initialized; u8 update_cck_rx_path; - if(priv->rf_type != RF_2T4R) + if (priv->rf_type != RF_2T4R) return; - if(!cck_Rx_Path_initialized) - { + if (!cck_Rx_Path_initialized) { read_nic_byte(dev, 0xa07, &DM_RxPathSelTable.cck_Rx_path); DM_RxPathSelTable.cck_Rx_path &= 0xf; cck_Rx_Path_initialized = 1; @@ -2716,91 +2491,63 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) read_nic_byte(dev, 0xc04, &DM_RxPathSelTable.disabledRF); DM_RxPathSelTable.disabledRF = ~DM_RxPathSelTable.disabledRF & 0xf; - if(priv->ieee80211->mode == WIRELESS_MODE_B) - { + if (priv->ieee80211->mode == WIRELESS_MODE_B) { DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; /* pure B mode, fixed cck version2 */ - /*DbgPrint("Pure B mode, use cck rx version2 \n");*/ + /*DbgPrint("Pure B mode, use cck rx version2\n");*/ } /* decide max/sec/min rssi index */ - for (i=0; istats.rx_rssi_percentage[i]; - if(priv->brfpath_rxenable[i]) - { + if (priv->brfpath_rxenable[i]) { rf_num++; cur_rf_rssi = DM_RxPathSelTable.rf_rssi[i]; - if(rf_num == 1) - { /* find first enabled rf path and the rssi values */ + if (rf_num == 1) { /* find first enabled rf path and the rssi values */ /* initialize, set all rssi index to the same one */ max_rssi_index = min_rssi_index = sec_rssi_index = i; tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi; - } - else if(rf_num == 2) - { /* we pick up the max index first, and let sec and min to be the same one */ - if(cur_rf_rssi >= tmp_max_rssi) - { + } else if (rf_num == 2) { /* we pick up the max index first, and let sec and min to be the same one */ + if (cur_rf_rssi >= tmp_max_rssi) { tmp_max_rssi = cur_rf_rssi; max_rssi_index = i; - } - else - { + } else { tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi; sec_rssi_index = min_rssi_index = i; } - } - else - { - if(cur_rf_rssi > tmp_max_rssi) - { + } else { + if (cur_rf_rssi > tmp_max_rssi) { tmp_sec_rssi = tmp_max_rssi; sec_rssi_index = max_rssi_index; tmp_max_rssi = cur_rf_rssi; max_rssi_index = i; - } - else if(cur_rf_rssi == tmp_max_rssi) - { /* let sec and min point to the different index */ + } else if (cur_rf_rssi == tmp_max_rssi) { /* let sec and min point to the different index */ tmp_sec_rssi = cur_rf_rssi; sec_rssi_index = i; - } - else if((cur_rf_rssi < tmp_max_rssi) &&(cur_rf_rssi > tmp_sec_rssi)) - { + } else if ((cur_rf_rssi < tmp_max_rssi) && (cur_rf_rssi > tmp_sec_rssi)) { tmp_sec_rssi = cur_rf_rssi; sec_rssi_index = i; - } - else if(cur_rf_rssi == tmp_sec_rssi) - { - if(tmp_sec_rssi == tmp_min_rssi) - { /* let sec and min point to the different index */ + } else if (cur_rf_rssi == tmp_sec_rssi) { + if (tmp_sec_rssi == tmp_min_rssi) { + /* let sec and min point to the different index */ tmp_sec_rssi = cur_rf_rssi; sec_rssi_index = i; - } - else - { + } else { /* This case we don't need to set any index */ } - } - else if((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi)) - { + } else if ((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi)) { /* This case we don't need to set any index */ - } - else if(cur_rf_rssi == tmp_min_rssi) - { - if(tmp_sec_rssi == tmp_min_rssi) - { /* let sec and min point to the different index */ + } else if (cur_rf_rssi == tmp_min_rssi) { + if (tmp_sec_rssi == tmp_min_rssi) { + /* let sec and min point to the different index */ tmp_min_rssi = cur_rf_rssi; min_rssi_index = i; - } - else - { + } else { /* This case we don't need to set any index */ } - } - else if(cur_rf_rssi < tmp_min_rssi) - { + } else if (cur_rf_rssi < tmp_min_rssi) { tmp_min_rssi = cur_rf_rssi; min_rssi_index = i; } @@ -2810,82 +2557,53 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) rf_num = 0; /* decide max/sec/min cck pwdb index */ - if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) - { - for (i=0; ibrfpath_rxenable[i]) - { + if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) { + for (i = 0; i < RF90_PATH_MAX; i++) { + if (priv->brfpath_rxenable[i]) { rf_num++; cur_cck_pwdb = DM_RxPathSelTable.cck_pwdb_sta[i]; - if(rf_num == 1) /* find first enabled rf path and the rssi values */ - { /* initialize, set all rssi index to the same one */ + if (rf_num == 1) { /* find first enabled rf path and the rssi values */ + /* initialize, set all rssi index to the same one */ cck_rx_ver2_max_index = cck_rx_ver2_min_index = cck_rx_ver2_sec_index = i; tmp_cck_max_pwdb = tmp_cck_min_pwdb = tmp_cck_sec_pwdb = cur_cck_pwdb; - } - else if(rf_num == 2) - { /* we pick up the max index first, and let sec and min to be the same one */ - if(cur_cck_pwdb >= tmp_cck_max_pwdb) - { + } else if (rf_num == 2) { /* we pick up the max index first, and let sec and min to be the same one */ + if (cur_cck_pwdb >= tmp_cck_max_pwdb) { tmp_cck_max_pwdb = cur_cck_pwdb; cck_rx_ver2_max_index = i; - } - else - { + } else { tmp_cck_sec_pwdb = tmp_cck_min_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = cck_rx_ver2_min_index = i; } - } - else - { - if(cur_cck_pwdb > tmp_cck_max_pwdb) - { + } else { + if (cur_cck_pwdb > tmp_cck_max_pwdb) { tmp_cck_sec_pwdb = tmp_cck_max_pwdb; cck_rx_ver2_sec_index = cck_rx_ver2_max_index; tmp_cck_max_pwdb = cur_cck_pwdb; cck_rx_ver2_max_index = i; - } - else if(cur_cck_pwdb == tmp_cck_max_pwdb) - { /* let sec and min point to the different index */ + } else if (cur_cck_pwdb == tmp_cck_max_pwdb) { /* let sec and min point to the different index */ tmp_cck_sec_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; - } - else if((cur_cck_pwdb < tmp_cck_max_pwdb) &&(cur_cck_pwdb > tmp_cck_sec_pwdb)) - { + } else if ((cur_cck_pwdb < tmp_cck_max_pwdb) && (cur_cck_pwdb > tmp_cck_sec_pwdb)) { tmp_cck_sec_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; - } - else if(cur_cck_pwdb == tmp_cck_sec_pwdb) - { - if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb) - { /* let sec and min point to the different index */ + } else if (cur_cck_pwdb == tmp_cck_sec_pwdb) { + if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { /* let sec and min point to the different index */ tmp_cck_sec_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; - } - else - { + } else { /* This case we don't need to set any index */ } - } - else if((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb)) - { + } else if ((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb)) { /* This case we don't need to set any index */ - } - else if(cur_cck_pwdb == tmp_cck_min_pwdb) - { - if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb) - { /* let sec and min point to the different index */ + } else if (cur_cck_pwdb == tmp_cck_min_pwdb) { + if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { /* let sec and min point to the different index */ tmp_cck_min_pwdb = cur_cck_pwdb; cck_rx_ver2_min_index = i; - } - else - { + } else { /* This case we don't need to set any index */ } - } - else if(cur_cck_pwdb < tmp_cck_min_pwdb) - { + } else if (cur_cck_pwdb < tmp_cck_min_pwdb) { tmp_cck_min_pwdb = cur_cck_pwdb; cck_rx_ver2_min_index = i; } @@ -2895,24 +2613,20 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) } } - /* * Set CCK Rx path * reg0xA07[3:2]=cck default rx path, reg0xa07[1:0]=cck optional rx path. */ update_cck_rx_path = 0; - if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) - { + if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) { cck_default_Rx = cck_rx_ver2_max_index; cck_optional_Rx = cck_rx_ver2_sec_index; - if(tmp_cck_max_pwdb != -64) + if (tmp_cck_max_pwdb != -64) update_cck_rx_path = 1; } - if(tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2) - { - if((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH) - { + if (tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2) { + if ((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH) { /* record the enabled rssi threshold */ DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5; /* disable the BB Rx path, OFDM */ @@ -2920,31 +2634,25 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<>i) & 0x1) /* disabled rf */ - { - if(tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i]) - { + if (DM_RxPathSelTable.disabledRF) { + for (i = 0; i < 4; i++) { + if ((DM_RxPathSelTable.disabledRF>>i) & 0x1) { /* disabled rf */ + if (tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i]) { /* enable the BB Rx path */ - /*DbgPrint("RF-%d is enabled. \n", 0x1<priv_wq,&priv->rfpath_check_wq,0); -} /* dm_CheckRxRFPath */ + queue_delayed_work(priv->priv_wq, &priv->rfpath_check_wq, 0); +} /* dm_CheckRxRFPath */ -static void dm_init_fsync (struct net_device *dev) +static void dm_init_fsync(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); @@ -2987,8 +2695,8 @@ static void dm_init_fsync (struct net_device *dev) priv->ieee80211->fsync_rssi_threshold = 30; priv->ieee80211->bfsync_enable = false; priv->ieee80211->fsync_multiple_timeinterval = 3; - priv->ieee80211->fsync_firstdiff_ratethreshold= 100; - priv->ieee80211->fsync_seconddiff_ratethreshold= 200; + priv->ieee80211->fsync_firstdiff_ratethreshold = 100; + priv->ieee80211->fsync_seconddiff_ratethreshold = 200; priv->ieee80211->fsync_state = Default_Fsync; priv->framesyncMonitor = 1; /* current default 0xc38 monitor on */ @@ -2997,10 +2705,10 @@ static void dm_init_fsync (struct net_device *dev) priv->fsync_timer.function = dm_fsync_timer_callback; } - static void dm_deInit_fsync(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); + del_timer_sync(&priv->fsync_timer); } @@ -3008,102 +2716,84 @@ void dm_fsync_timer_callback(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct r8192_priv *priv = ieee80211_priv((struct net_device *)data); - u32 rate_index, rate_count = 0, rate_count_diff=0; + u32 rate_index, rate_count = 0, rate_count_diff = 0; bool bSwitchFromCountDiff = false; bool bDoubleTimeInterval = false; - if(priv->ieee80211->state == IEEE80211_LINKED && + if (priv->ieee80211->state == IEEE80211_LINKED && priv->ieee80211->bfsync_enable && - (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) - { + (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) { /* Count rate 54, MCS [7], [12, 13, 14, 15] */ u32 rate_bitmap; - for(rate_index = 0; rate_index <= 27; rate_index++) - { + + for (rate_index = 0; rate_index <= 27; rate_index++) { rate_bitmap = 1 << rate_index; - if(priv->ieee80211->fsync_rate_bitmap & rate_bitmap) - rate_count+= priv->stats.received_rate_histogram[1][rate_index]; + if (priv->ieee80211->fsync_rate_bitmap & rate_bitmap) + rate_count += priv->stats.received_rate_histogram[1][rate_index]; } - if(rate_count < priv->rate_record) + if (rate_count < priv->rate_record) rate_count_diff = 0xffffffff - rate_count + priv->rate_record; else rate_count_diff = rate_count - priv->rate_record; - if(rate_count_diff < priv->rateCountDiffRecord) - { - + if (rate_count_diff < priv->rateCountDiffRecord) { u32 DiffNum = priv->rateCountDiffRecord - rate_count_diff; /* Continue count */ - if(DiffNum >= priv->ieee80211->fsync_seconddiff_ratethreshold) + if (DiffNum >= priv->ieee80211->fsync_seconddiff_ratethreshold) priv->ContinueDiffCount++; else priv->ContinueDiffCount = 0; /* Continue count over */ - if(priv->ContinueDiffCount >=2) - { + if (priv->ContinueDiffCount >= 2) { bSwitchFromCountDiff = true; priv->ContinueDiffCount = 0; } - } - else - { + } else { /* Stop the continued count */ priv->ContinueDiffCount = 0; } /* If Count diff <= FsyncRateCountThreshold */ - if(rate_count_diff <= priv->ieee80211->fsync_firstdiff_ratethreshold) - { + if (rate_count_diff <= priv->ieee80211->fsync_firstdiff_ratethreshold) { bSwitchFromCountDiff = true; priv->ContinueDiffCount = 0; } priv->rate_record = rate_count; priv->rateCountDiffRecord = rate_count_diff; - RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync); + RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff, priv->bswitch_fsync); /* if we never receive those mcs rate and rssi > 30 % then switch fsyn */ - if(priv->undecorated_smoothed_pwdb > priv->ieee80211->fsync_rssi_threshold && bSwitchFromCountDiff) - { + if (priv->undecorated_smoothed_pwdb > priv->ieee80211->fsync_rssi_threshold && bSwitchFromCountDiff) { bDoubleTimeInterval = true; priv->bswitch_fsync = !priv->bswitch_fsync; - if(priv->bswitch_fsync) - { + if (priv->bswitch_fsync) { write_nic_byte(dev, 0xC36, 0x1c); write_nic_byte(dev, 0xC3e, 0x90); - } - else - { + } else { write_nic_byte(dev, 0xC36, 0x5c); write_nic_byte(dev, 0xC3e, 0x96); } - } - else if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->fsync_rssi_threshold) - { - if(priv->bswitch_fsync) - { + } else if (priv->undecorated_smoothed_pwdb <= priv->ieee80211->fsync_rssi_threshold) { + if (priv->bswitch_fsync) { priv->bswitch_fsync = false; write_nic_byte(dev, 0xC36, 0x5c); write_nic_byte(dev, 0xC3e, 0x96); } } - if(bDoubleTimeInterval){ - if(timer_pending(&priv->fsync_timer)) + if (bDoubleTimeInterval) { + if (timer_pending(&priv->fsync_timer)) del_timer_sync(&priv->fsync_timer); priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval*priv->ieee80211->fsync_multiple_timeinterval); add_timer(&priv->fsync_timer); - } - else{ - if(timer_pending(&priv->fsync_timer)) + } else { + if (timer_pending(&priv->fsync_timer)) del_timer_sync(&priv->fsync_timer); priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval); add_timer(&priv->fsync_timer); } - } - else - { + } else { /* Let Register return to default value; */ - if(priv->bswitch_fsync) - { + if (priv->bswitch_fsync) { priv->bswitch_fsync = false; write_nic_byte(dev, 0xC36, 0x5c); write_nic_byte(dev, 0xC3e, 0x96); @@ -3112,7 +2802,7 @@ void dm_fsync_timer_callback(unsigned long data) write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd); } RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount); - RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync); + RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff, priv->bswitch_fsync); } static void dm_StartHWFsync(struct net_device *dev) @@ -3130,8 +2820,7 @@ static void dm_EndSWFsync(struct net_device *dev) del_timer_sync(&(priv->fsync_timer)); /* Let Register return to default value; */ - if(priv->bswitch_fsync) - { + if (priv->bswitch_fsync) { priv->bswitch_fsync = false; write_nic_byte(dev, 0xC36, 0x5c); @@ -3158,23 +2847,19 @@ static void dm_StartSWFsync(struct net_device *dev) priv->rateCountDiffRecord = 0; priv->bswitch_fsync = false; - if(priv->ieee80211->mode == WIRELESS_MODE_N_24G) - { - priv->ieee80211->fsync_firstdiff_ratethreshold= 600; + if (priv->ieee80211->mode == WIRELESS_MODE_N_24G) { + priv->ieee80211->fsync_firstdiff_ratethreshold = 600; priv->ieee80211->fsync_seconddiff_ratethreshold = 0xffff; - } - else - { - priv->ieee80211->fsync_firstdiff_ratethreshold= 200; + } else { + priv->ieee80211->fsync_firstdiff_ratethreshold = 200; priv->ieee80211->fsync_seconddiff_ratethreshold = 200; } - for(rateIndex = 0; rateIndex <= 27; rateIndex++) - { - rateBitmap = 1 << rateIndex; - if(priv->ieee80211->fsync_rate_bitmap & rateBitmap) + for (rateIndex = 0; rateIndex <= 27; rateIndex++) { + rateBitmap = 1 << rateIndex; + if (priv->ieee80211->fsync_rate_bitmap & rateBitmap) priv->rate_record += priv->stats.received_rate_histogram[1][rateIndex]; } - if(timer_pending(&priv->fsync_timer)) + if (timer_pending(&priv->fsync_timer)) del_timer_sync(&priv->fsync_timer); priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval); add_timer(&priv->fsync_timer); @@ -3194,139 +2879,112 @@ static void dm_EndHWFsync(struct net_device *dev) void dm_check_fsync(struct net_device *dev) { #define RegC38_Default 0 -#define RegC38_NonFsync_Other_AP 1 -#define RegC38_Fsync_AP_BCM 2 +#define RegC38_NonFsync_Other_AP 1 +#define RegC38_Fsync_AP_BCM 2 struct r8192_priv *priv = ieee80211_priv(dev); /*u32 framesyncC34;*/ - static u8 reg_c38_State=RegC38_Default; + static u8 reg_c38_State = RegC38_Default; static u32 reset_cnt; RT_TRACE(COMP_HALDM, "RSSI %d TimeInterval %d MultipleTimeInterval %d\n", priv->ieee80211->fsync_rssi_threshold, priv->ieee80211->fsync_time_interval, priv->ieee80211->fsync_multiple_timeinterval); RT_TRACE(COMP_HALDM, "RateBitmap 0x%x FirstDiffRateThreshold %d SecondDiffRateThreshold %d\n", priv->ieee80211->fsync_rate_bitmap, priv->ieee80211->fsync_firstdiff_ratethreshold, priv->ieee80211->fsync_seconddiff_ratethreshold); - if(priv->ieee80211->state == IEEE80211_LINKED && - (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) - { - if(priv->ieee80211->bfsync_enable == 0) - { - switch (priv->ieee80211->fsync_state) - { - case Default_Fsync: - dm_StartHWFsync(dev); - priv->ieee80211->fsync_state = HW_Fsync; - break; - case SW_Fsync: - dm_EndSWFsync(dev); - dm_StartHWFsync(dev); - priv->ieee80211->fsync_state = HW_Fsync; - break; - case HW_Fsync: - default: - break; + if (priv->ieee80211->state == IEEE80211_LINKED && + (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) { + if (priv->ieee80211->bfsync_enable == 0) { + switch (priv->ieee80211->fsync_state) { + case Default_Fsync: + dm_StartHWFsync(dev); + priv->ieee80211->fsync_state = HW_Fsync; + break; + case SW_Fsync: + dm_EndSWFsync(dev); + dm_StartHWFsync(dev); + priv->ieee80211->fsync_state = HW_Fsync; + break; + case HW_Fsync: + default: + break; } - } - else - { - switch (priv->ieee80211->fsync_state) - { - case Default_Fsync: - dm_StartSWFsync(dev); - priv->ieee80211->fsync_state = SW_Fsync; - break; - case HW_Fsync: - dm_EndHWFsync(dev); - dm_StartSWFsync(dev); - priv->ieee80211->fsync_state = SW_Fsync; - break; - case SW_Fsync: - default: - break; - + } else { + switch (priv->ieee80211->fsync_state) { + case Default_Fsync: + dm_StartSWFsync(dev); + priv->ieee80211->fsync_state = SW_Fsync; + break; + case HW_Fsync: + dm_EndHWFsync(dev); + dm_StartSWFsync(dev); + priv->ieee80211->fsync_state = SW_Fsync; + break; + case SW_Fsync: + default: + break; } } - if(priv->framesyncMonitor) - { - if(reg_c38_State != RegC38_Fsync_AP_BCM) - { /* For broadcom AP we write different default value */ + if (priv->framesyncMonitor) { + if (reg_c38_State != RegC38_Fsync_AP_BCM) { + /* For broadcom AP we write different default value */ write_nic_byte(dev, rOFDM0_RxDetector3, 0x95); reg_c38_State = RegC38_Fsync_AP_BCM; } } - } - else - { - switch (priv->ieee80211->fsync_state) - { - case HW_Fsync: - dm_EndHWFsync(dev); - priv->ieee80211->fsync_state = Default_Fsync; - break; - case SW_Fsync: - dm_EndSWFsync(dev); - priv->ieee80211->fsync_state = Default_Fsync; - break; - case Default_Fsync: - default: - break; + } else { + switch (priv->ieee80211->fsync_state) { + case HW_Fsync: + dm_EndHWFsync(dev); + priv->ieee80211->fsync_state = Default_Fsync; + break; + case SW_Fsync: + dm_EndSWFsync(dev); + priv->ieee80211->fsync_state = Default_Fsync; + break; + case Default_Fsync: + default: + break; } - if(priv->framesyncMonitor) - { - if(priv->ieee80211->state == IEEE80211_LINKED) - { - if(priv->undecorated_smoothed_pwdb <= RegC38_TH) - { - if(reg_c38_State != RegC38_NonFsync_Other_AP) - { + if (priv->framesyncMonitor) { + if (priv->ieee80211->state == IEEE80211_LINKED) { + if (priv->undecorated_smoothed_pwdb <= RegC38_TH) { + if (reg_c38_State != RegC38_NonFsync_Other_AP) { write_nic_byte(dev, rOFDM0_RxDetector3, 0x90); reg_c38_State = RegC38_NonFsync_Other_AP; } - } - else if(priv->undecorated_smoothed_pwdb >= (RegC38_TH+5)) - { - if(reg_c38_State) - { + } else if (priv->undecorated_smoothed_pwdb >= (RegC38_TH+5)) { + if (reg_c38_State) { write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; - /*DbgPrint("Fsync is idle, rssi>=40, write 0xc38 = 0x%x \n", pHalData->framesync);*/ + /*DbgPrint("Fsync is idle, rssi>=40, write 0xc38 = 0x%x\n", pHalData->framesync);*/ } } - } - else - { - if(reg_c38_State) - { + } else { + if (reg_c38_State) { write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; - /*DbgPrint("Fsync is idle, not connected, write 0xc38 = 0x%x \n", pHalData->framesync);*/ + /*DbgPrint("Fsync is idle, not connected, write 0xc38 = 0x%x\n", pHalData->framesync);*/ } } } } - if(priv->framesyncMonitor) - { - if(priv->reset_count != reset_cnt) - { /* After silent reset, the reg_c38_State will be returned to default value */ + if (priv->framesyncMonitor) { + if (priv->reset_count != reset_cnt) { /* After silent reset, the reg_c38_State will be returned to default value */ write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; reset_cnt = priv->reset_count; - /*DbgPrint("reg_c38_State = 0 for silent reset. \n");*/ + /*DbgPrint("reg_c38_State = 0 for silent reset.\n");*/ } - } - else - { - if(reg_c38_State) - { + } else { + if (reg_c38_State) { write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); reg_c38_State = RegC38_Default; - /*DbgPrint("framesync no monitor, write 0xc38 = 0x%x \n", pHalData->framesync);*/ + /*DbgPrint("framesync no monitor, write 0xc38 = 0x%x\n", pHalData->framesync);*/ } } } - /*----------------------------------------------------------------------------- * Function: dm_shadow_init() * @@ -3349,8 +3007,7 @@ void dm_shadow_init(struct net_device *dev) u16 offset; for (page = 0; page < 5; page++) - for (offset = 0; offset < 256; offset++) - { + for (offset = 0; offset < 256; offset++) { read_nic_byte(dev, offset+page*256, &dm_shadow[page][offset]); /*DbgPrint("P-%d/O-%02x=%02x\r\n", page, offset, DM_Shadow[page][offset]);*/ } @@ -3398,70 +3055,57 @@ static void dm_init_dynamic_txpower(struct net_device *dev) static void dm_dynamic_txpower(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - unsigned int txhipower_threshhold=0; - unsigned int txlowpower_threshold=0; - if(priv->ieee80211->bdynamic_txpower_enable != true) - { + unsigned int txhipower_threshhold = 0; + unsigned int txlowpower_threshold = 0; + + if (priv->ieee80211->bdynamic_txpower_enable != true) { priv->bDynamicTxHighPower = false; priv->bDynamicTxLowPower = false; return; } - /*printk("priv->ieee80211->current_network.unknown_cap_exist is %d ,priv->ieee80211->current_network.broadcom_cap_exist is %d\n",priv->ieee80211->current_network.unknown_cap_exist,priv->ieee80211->current_network.broadcom_cap_exist);*/ - if((priv->ieee80211->current_network.atheros_cap_exist) && (priv->ieee80211->mode == IEEE_G)){ + /*printk("priv->ieee80211->current_network.unknown_cap_exist is %d , priv->ieee80211->current_network.broadcom_cap_exist is %d\n", priv->ieee80211->current_network.unknown_cap_exist, priv->ieee80211->current_network.broadcom_cap_exist);*/ + if ((priv->ieee80211->current_network.atheros_cap_exist) && (priv->ieee80211->mode == IEEE_G)) { txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH; txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW; - } - else - { + } else { txhipower_threshhold = TX_POWER_NEAR_FIELD_THRESH_HIGH; txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW; } - /*printk("=======>%s(): txhipower_threshhold is %d,txlowpower_threshold is %d\n",__func__,txhipower_threshhold,txlowpower_threshold);*/ - RT_TRACE(COMP_TXAGC,"priv->undecorated_smoothed_pwdb = %ld \n" , priv->undecorated_smoothed_pwdb); + /*printk("=======>%s(): txhipower_threshhold is %d, txlowpower_threshold is %d\n", __func__, txhipower_threshhold, txlowpower_threshold);*/ + RT_TRACE(COMP_TXAGC, "priv->undecorated_smoothed_pwdb = %ld\n", priv->undecorated_smoothed_pwdb); - if(priv->ieee80211->state == IEEE80211_LINKED) - { - if(priv->undecorated_smoothed_pwdb >= txhipower_threshhold) - { + if (priv->ieee80211->state == IEEE80211_LINKED) { + if (priv->undecorated_smoothed_pwdb >= txhipower_threshhold) { priv->bDynamicTxHighPower = true; priv->bDynamicTxLowPower = false; - } - else - { + } else { /* high power state check */ - if(priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true) - { + if (priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true) priv->bDynamicTxHighPower = false; - } + /* low power state check */ - if(priv->undecorated_smoothed_pwdb < 35) - { + if (priv->undecorated_smoothed_pwdb < 35) { priv->bDynamicTxLowPower = true; - } - else if(priv->undecorated_smoothed_pwdb >= 40) - { + } else if (priv->undecorated_smoothed_pwdb >= 40) { priv->bDynamicTxLowPower = false; } } - } - else - { + } else { /*pHalData->bTXPowerCtrlforNearFarRange = !pHalData->bTXPowerCtrlforNearFarRange;*/ priv->bDynamicTxHighPower = false; priv->bDynamicTxLowPower = false; } - if((priv->bDynamicTxHighPower != priv->bLastDTPFlag_High) || - (priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low)) - { - RT_TRACE(COMP_TXAGC,"SetTxPowerLevel8190() channel = %d \n" , priv->ieee80211->current_network.channel); + if ((priv->bDynamicTxHighPower != priv->bLastDTPFlag_High) || + (priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low)) { + RT_TRACE(COMP_TXAGC, "SetTxPowerLevel8190() channel = %d\n", priv->ieee80211->current_network.channel); #if defined(RTL8190P) || defined(RTL8192E) - SetTxPowerLevel8190(Adapter,pHalData->CurrentChannel); + SetTxPowerLevel8190(Adapter, pHalData->CurrentChannel); #endif - rtl8192_phy_setTxPower(dev,priv->ieee80211->current_network.channel); + rtl8192_phy_setTxPower(dev, priv->ieee80211->current_network.channel); /*pHalData->bStartTxCtrlByTPCNFR = FALSE; Clear th flag of Set TX Power from Sitesurvey*/ } priv->bLastDTPFlag_High = priv->bDynamicTxHighPower; -- cgit v0.10.2 From 16da7808300cea62b76dba286f74f0e3d7194f81 Mon Sep 17 00:00:00 2001 From: Lorenzo Stoakes Date: Sat, 24 Jan 2015 15:45:23 +0000 Subject: staging: rtl8192u: remove redundant code This patch fixes warnings/errors raised by checkpatch.pl relating to redundant code in r8192U_dm.c. Signed-off-by: Lorenzo Stoakes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index 2c3d894..1893336 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -406,9 +406,8 @@ static void dm_check_rate_adaptive(struct net_device *dev) ratr_value = targetRATR; RT_TRACE(COMP_RATE, "currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR); - if (priv->rf_type == RF_1T2R) { + if (priv->rf_type == RF_1T2R) ratr_value &= ~(RATE_ALL_OFDM_2SS); - } write_nic_dword(dev, RATR0, ratr_value); write_nic_byte(dev, UFWP, 1); @@ -436,9 +435,8 @@ static void dm_bandwidth_autoswitch(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); - if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 || !priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable) { + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 || !priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable) return; - } if (priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false) { /* If send packets in 40 Mhz in 20/40 */ if (priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz) priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true; @@ -532,9 +530,8 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) tx_cmd.Length = 4; tx_cmd.Value = Value; rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12); - if (rtStatus == RT_STATUS_FAILURE) { + if (rtStatus == RT_STATUS_FAILURE) RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n"); - } mdelay(1); /*DbgPrint("hi, vivi, strange\n");*/ for (i = 0; i <= 30; i++) { @@ -574,9 +571,8 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) break; } - for (k = 0; k < 5; k++) { + for (k = 0; k < 5; k++) Avg_TSSI_Meas_from_driver += tmp_report[k]; - } Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5; RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver); @@ -599,56 +595,55 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev) RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); return; - } else { - if (Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) { - if (priv->rfa_txpowertrackingindex > 0) { - priv->rfa_txpowertrackingindex--; - if (priv->rfa_txpowertrackingindex_real > 4) { - priv->rfa_txpowertrackingindex_real--; - rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); - } - } - } else { - if (priv->rfa_txpowertrackingindex < 36) { - priv->rfa_txpowertrackingindex++; - priv->rfa_txpowertrackingindex_real++; + } + if (Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) { + if (priv->rfa_txpowertrackingindex > 0) { + priv->rfa_txpowertrackingindex--; + if (priv->rfa_txpowertrackingindex_real > 4) { + priv->rfa_txpowertrackingindex_real--; rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); - } } - priv->cck_present_attentuation_difference - = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default; + } else { + if (priv->rfa_txpowertrackingindex < 36) { + priv->rfa_txpowertrackingindex++; + priv->rfa_txpowertrackingindex_real++; + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); - if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) - priv->cck_present_attentuation - = priv->cck_present_attentuation_20Mdefault + priv->cck_present_attentuation_difference; - else - priv->cck_present_attentuation - = priv->cck_present_attentuation_40Mdefault + priv->cck_present_attentuation_difference; - - if (priv->cck_present_attentuation > -1 && priv->cck_present_attentuation < 23) { - if (priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) { - priv->bcck_in_ch14 = TRUE; - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } else if (priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) { - priv->bcck_in_ch14 = FALSE; - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); - } else - dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); } - RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); - RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); - RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); - RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); + } + priv->cck_present_attentuation_difference + = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default; - if (priv->cck_present_attentuation_difference <= -12 || priv->cck_present_attentuation_difference >= 24) { - priv->ieee80211->bdynamic_txpower_enable = TRUE; - write_nic_byte(dev, 0x1ba, 0); - RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n"); - return; - } + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + priv->cck_present_attentuation + = priv->cck_present_attentuation_20Mdefault + priv->cck_present_attentuation_difference; + else + priv->cck_present_attentuation + = priv->cck_present_attentuation_40Mdefault + priv->cck_present_attentuation_difference; + + if (priv->cck_present_attentuation > -1 && priv->cck_present_attentuation < 23) { + if (priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14) { + priv->bcck_in_ch14 = TRUE; + dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + } else if (priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14) { + priv->bcck_in_ch14 = FALSE; + dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + } else + dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + } + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation_difference = %d\n", priv->cck_present_attentuation_difference); + RT_TRACE(COMP_POWER_TRACKING, "priv->cck_present_attentuation = %d\n", priv->cck_present_attentuation); + if (priv->cck_present_attentuation_difference <= -12 || priv->cck_present_attentuation_difference >= 24) { + priv->ieee80211->bdynamic_txpower_enable = TRUE; + write_nic_byte(dev, 0x1ba, 0); + RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n"); + return; } + write_nic_byte(dev, 0x1ba, 0); Avg_TSSI_Meas_from_driver = 0; for (k = 0; k < 5; k++) @@ -1318,12 +1313,9 @@ static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev) if (!priv->btxpower_tracking) return; - else { - if ((tx_power_track_counter % 30 == 0) && (tx_power_track_counter != 0)) { - queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); - } - tx_power_track_counter++; - } + if ((tx_power_track_counter % 30 == 0) && (tx_power_track_counter != 0)) + queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); + tx_power_track_counter++; } static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) @@ -1333,11 +1325,9 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) /*DbgPrint("dm_CheckTXPowerTracking()\n");*/ if (!priv->btxpower_tracking) return; - else { - if (priv->txpower_count <= 2) { - priv->txpower_count++; - return; - } + if (priv->txpower_count <= 2) { + priv->txpower_count++; + return; } if (!TM_Trigger) { @@ -1352,11 +1342,10 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); TM_Trigger = 1; return; - } else { - /*DbgPrint("Schedule TxPowerTrackingWorkItem\n");*/ - queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); - TM_Trigger = 0; } + /*DbgPrint("Schedule TxPowerTrackingWorkItem\n");*/ + queue_delayed_work(priv->priv_wq, &priv->txpower_tracking_wq, 0); + TM_Trigger = 0; } static void dm_check_txpower_tracking(struct net_device *dev) @@ -1828,15 +1817,14 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( DM_DigTable.RssiHighThresh, DM_DigTable.Dig_State);*/ /* 1. When RSSI decrease, We have to judge if it is smaller than a threshold and then execute the step below. */ - if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh)) { + if (priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh) { /* 2008/02/05 MH When we execute silent reset, the DIG PHY parameters will be reset to init value. We must prevent the condition. */ if (dm_digtable.dig_state == DM_STA_DIG_OFF && (priv->reset_count == reset_cnt)) { return; - } else { - reset_cnt = priv->reset_count; } + reset_cnt = priv->reset_count; /* If DIG is off, DIG high power state must reset. */ dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX; @@ -1878,19 +1866,18 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( /* 2. When RSSI increase, We have to judge if it is larger than a threshold and then execute the step below. */ - if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh)) { + if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) { u8 reset_flag = 0; if (dm_digtable.dig_state == DM_STA_DIG_ON && (priv->reset_count == reset_cnt)) { dm_ctrl_initgain_byrssi_highpwr(dev); return; - } else { - if (priv->reset_count != reset_cnt) - reset_flag = 1; - - reset_cnt = priv->reset_count; } + if (priv->reset_count != reset_cnt) + reset_flag = 1; + + reset_cnt = priv->reset_count; dm_digtable.dig_state = DM_STA_DIG_ON; /*DbgPrint("DIG ON\n\r");*/ @@ -1983,8 +1970,7 @@ static void dm_ctrl_initgain_byrssi_highpwr( if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON && (priv->reset_count == reset_cnt_highpwr)) return; - else - dm_digtable.dig_highpwr_state = DM_STA_DIG_ON; + dm_digtable.dig_highpwr_state = DM_STA_DIG_ON; /* 3.1 Higher PD_TH for OFDM for high power state. */ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) { @@ -2000,8 +1986,7 @@ static void dm_ctrl_initgain_byrssi_highpwr( if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF && (priv->reset_count == reset_cnt_highpwr)) return; - else - dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF; + dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF; if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh && priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) { @@ -2098,7 +2083,7 @@ static void dm_pd_th( if (dm_digtable.cur_connect_state == DIG_CONNECT) { if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh) dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER; - else if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)) + else if (dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh) dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) && (dm_digtable.rssi_val < dm_digtable.rssi_high_power_lowthresh)) @@ -2180,9 +2165,9 @@ static void dm_cs_ratio( if (dm_digtable.pre_connect_state == dm_digtable.cur_connect_state) { if (dm_digtable.cur_connect_state == DIG_CONNECT) { - if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)) + if (dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh) dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; - else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh)) + else if (dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER; else dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state; @@ -3085,11 +3070,10 @@ static void dm_dynamic_txpower(struct net_device *dev) priv->bDynamicTxHighPower = false; /* low power state check */ - if (priv->undecorated_smoothed_pwdb < 35) { + if (priv->undecorated_smoothed_pwdb < 35) priv->bDynamicTxLowPower = true; - } else if (priv->undecorated_smoothed_pwdb >= 40) { + else if (priv->undecorated_smoothed_pwdb >= 40) priv->bDynamicTxLowPower = false; - } } } else { /*pHalData->bTXPowerCtrlforNearFarRange = !pHalData->bTXPowerCtrlforNearFarRange;*/ @@ -3140,7 +3124,6 @@ static void dm_send_rssi_tofw(struct net_device *dev) * 0x1e0(byte) to notify driver. */ write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb); - return; } /*---------------------------Define function prototype------------------------*/ -- cgit v0.10.2 From f0e0f8cffa73d5922b8e356c64d9238302763e07 Mon Sep 17 00:00:00 2001 From: Lorenzo Stoakes Date: Sat, 24 Jan 2015 15:45:24 +0000 Subject: staging: rtl8192u: Refactor heavy nesting This patch fixes warnings raised by checkpatch.pl relating to heavily indented lines in r8192U_dm.c by refactoring code to achieve the same outcome indented by one less tab. Signed-off-by: Lorenzo Stoakes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index 1893336..ee6b936 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -2566,28 +2566,25 @@ static void dm_rxpath_sel_byrssi(struct net_device *dev) cck_rx_ver2_sec_index = cck_rx_ver2_max_index; tmp_cck_max_pwdb = cur_cck_pwdb; cck_rx_ver2_max_index = i; - } else if (cur_cck_pwdb == tmp_cck_max_pwdb) { /* let sec and min point to the different index */ + } else if (cur_cck_pwdb == tmp_cck_max_pwdb) { + /* let sec and min point to the different index */ tmp_cck_sec_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; } else if ((cur_cck_pwdb < tmp_cck_max_pwdb) && (cur_cck_pwdb > tmp_cck_sec_pwdb)) { tmp_cck_sec_pwdb = cur_cck_pwdb; cck_rx_ver2_sec_index = i; - } else if (cur_cck_pwdb == tmp_cck_sec_pwdb) { - if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { /* let sec and min point to the different index */ - tmp_cck_sec_pwdb = cur_cck_pwdb; - cck_rx_ver2_sec_index = i; - } else { - /* This case we don't need to set any index */ - } + } else if (cur_cck_pwdb == tmp_cck_sec_pwdb && tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { + /* let sec and min point to the different index */ + tmp_cck_sec_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = i; + /* otherwise we don't need to set any index */ } else if ((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb)) { /* This case we don't need to set any index */ - } else if (cur_cck_pwdb == tmp_cck_min_pwdb) { - if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { /* let sec and min point to the different index */ - tmp_cck_min_pwdb = cur_cck_pwdb; - cck_rx_ver2_min_index = i; - } else { - /* This case we don't need to set any index */ - } + } else if (cur_cck_pwdb == tmp_cck_min_pwdb && tmp_cck_sec_pwdb == tmp_cck_min_pwdb) { + /* let sec and min point to the different index */ + tmp_cck_min_pwdb = cur_cck_pwdb; + cck_rx_ver2_min_index = i; + /* otherwise we don't need to set any index */ } else if (cur_cck_pwdb < tmp_cck_min_pwdb) { tmp_cck_min_pwdb = cur_cck_pwdb; cck_rx_ver2_min_index = i; -- cgit v0.10.2 From 9c18a05c454e8a6436352842e56fb1dd2760b13b Mon Sep 17 00:00:00 2001 From: Vaishali Thakkar Date: Tue, 27 Jan 2015 23:41:13 +0530 Subject: Staging: rtl8192u: Use put_unaligned_le16 in rtl819x_BAProc.c This patch introduces the use of function put_unaligned_le16. This is done using Coccinelle and semantic patch used is as follows: @a@ typedef u16, __le16, uint16_t; {u16,__le16,uint16_t} e16; identifier tmp; expression ptr; expression y,e; type T; type T; @@ - tmp = cpu_to_le16(y); <+... when != tmp ( - memcpy(ptr, (T)&tmp, \(2\|sizeof(u16)\|sizeof(__le16)\|sizeof(uint16_t)\|sizeof(e16)\)); + put_unaligned_le16(y,ptr); | - memcpy(ptr, (T)&tmp, ...); + put_unaligned_le16(y,ptr); ) ...+> ? tmp = e @@ type T; identifier a.tmp; @@ - T tmp; ...when != tmp Signed-off-by: Vaishali Thakkar Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index a9fd2cb..1b4623c 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -4,6 +4,8 @@ * ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue. * WB 2008-05-27 * *****************************************************************************************************************************/ +#include +#include #include "ieee80211.h" #include "rtl819x_BA.h" @@ -110,7 +112,6 @@ static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, P struct sk_buff *skb = NULL; struct ieee80211_hdr_3addr *BAReq = NULL; u8 *tag = NULL; - __le16 tmp = 0; u16 len = ieee->tx_headroom + 9; //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2)) IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __func__, type, Dst, ieee->dev); @@ -149,17 +150,17 @@ static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, P { // Status Code printk("=====>to send ADDBARSP\n"); - tmp = cpu_to_le16(StatusCode); - memcpy(tag, (u8 *)&tmp, 2); + + put_unaligned_le16(StatusCode, tag); tag += 2; } // BA Parameter Set - tmp = cpu_to_le16(pBA->BaParamSet.shortData); - memcpy(tag, (u8 *)&tmp, 2); + + put_unaligned_le16(pBA->BaParamSet.shortData, tag); tag += 2; // BA Timeout Value - tmp = cpu_to_le16(pBA->BaTimeoutValue); - memcpy(tag, (u8 *)&tmp, 2); + + put_unaligned_le16(pBA->BaTimeoutValue, tag); tag += 2; if (ACT_ADDBAREQ == type) @@ -196,7 +197,6 @@ static struct sk_buff *ieee80211_DELBA( struct sk_buff *skb = NULL; struct ieee80211_hdr_3addr *Delba = NULL; u8 *tag = NULL; - __le16 tmp = 0; //len = head len + DELBA Parameter Set(2) + Reason Code(2) u16 len = 6 + ieee->tx_headroom; @@ -230,12 +230,12 @@ static struct sk_buff *ieee80211_DELBA( *tag ++= ACT_DELBA; // DELBA Parameter Set - tmp = cpu_to_le16(DelbaParamSet.shortData); - memcpy(tag, (u8 *)&tmp, 2); + + put_unaligned_le16(DelbaParamSet.shortData, tag); tag += 2; // Reason Code - tmp = cpu_to_le16(ReasonCode); - memcpy(tag, (u8 *)&tmp, 2); + + put_unaligned_le16(ReasonCode, tag); tag += 2; IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); -- cgit v0.10.2 From 7157fda400c7aeeee1eb60d4c6fd31cef822dac0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 26 Jan 2015 16:17:13 -0700 Subject: staging: comedi: das16: absorb das16_ai_enable() This function is only called by das16_cmd_exec(). Absorb it to clarify code. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 4608b01..417ea75 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -451,23 +451,6 @@ struct das16_private_struct { unsigned int can_burst:1; }; -static void das16_ai_enable(struct comedi_device *dev, - unsigned int mode, unsigned int src) -{ - struct das16_private_struct *devpriv = dev->private; - - devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | - DAS16_CTRL_DMAE | - DAS16_CTRL_PACING_MASK); - devpriv->ctrl_reg |= mode; - - if (src == TRIG_EXT) - devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER; - else - devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER; - outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); -} - static void das16_ai_disable(struct comedi_device *dev) { struct das16_private_struct *devpriv = dev->private; @@ -765,7 +748,14 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->timer.expires = jiffies + timer_period(); add_timer(&devpriv->timer); - das16_ai_enable(dev, DAS16_CTRL_DMAE, cmd->convert_src); + /* enable DMA interrupt with external or internal pacing */ + devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_PACING_MASK); + devpriv->ctrl_reg |= DAS16_CTRL_DMAE; + if (cmd->convert_src == TRIG_EXT) + devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER; + else + devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER; + outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); if (devpriv->can_burst) outb(0, dev->iobase + DAS1600_CONV_REG); -- cgit v0.10.2 From fc4e02175285c4642f50ad7b4070848d9e9f63f8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 26 Jan 2015 16:17:14 -0700 Subject: staging: comedi: das16: remove unnecessary das16_ai_disable() The das16_ai_disable() function disables interrupts and the pacer clock. This function is called by the subdevice (*cancel) operation. The comedi core will not call a subdevice (*insn_read) operation while an async command is running due to the s->busy check in parse_insn(). Since all async commands are terminated by a (*cancel), the das16_ai_disable() is not necessary in das16_ai_insn_read(). Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 417ea75..97e5e7dc 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -831,8 +831,6 @@ static int das16_ai_insn_read(struct comedi_device *dev, int ret; int i; - das16_ai_disable(dev); - /* set multiplexer */ outb(chan | (chan << 4), dev->iobase + DAS16_MUX_REG); -- cgit v0.10.2 From c2733a92a64c7f0c48d873a8f75147a8ab33f399 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 26 Jan 2015 16:17:15 -0700 Subject: staging: comedi: das16: absorb das16_ai_disable() This function is only called by das16_cancel(). Absorb it to clarify code. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 97e5e7dc..2564af0 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -451,17 +451,6 @@ struct das16_private_struct { unsigned int can_burst:1; }; -static void das16_ai_disable(struct comedi_device *dev) -{ - struct das16_private_struct *devpriv = dev->private; - - /* disable interrupts, dma and pacer clocked conversions */ - devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | - DAS16_CTRL_DMAE | - DAS16_CTRL_PACING_MASK); - outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); -} - static void das16_interrupt(struct comedi_device *dev) { struct das16_private_struct *devpriv = dev->private; @@ -772,7 +761,11 @@ static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) spin_lock_irqsave(&dev->spinlock, flags); - das16_ai_disable(dev); + /* disable interrupts, dma and pacer clocked conversions */ + devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_DMAE | + DAS16_CTRL_PACING_MASK); + outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); + comedi_isadma_disable(dma->chan); /* disable SW timer */ -- cgit v0.10.2 From 0ce8280e2876091b5c67cb515fae8e9bf3b50bfd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 26 Jan 2015 16:17:16 -0700 Subject: staging: comedi: das16: introduce das16_ai_range() Clarify the (*attach) a bit by introducing a helper function to handle the setup of the analog input 'range_table'. Some of the boards supported by this driver do not have programmable ranges. The analog input subdevice can use optional range information provided by the user during the attach of the driver. Currently this range data is allocated and stored in the private data. Use the subdevice private data member instead and allocate the memory with comedi_alloc_spriv(). The comedi core will automatically free this memory when the driver is detached. If the allocation fails set the 'range_table' to 'range_unknown' instead of failing the driver attach. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 2564af0..cb38e4b 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -443,7 +443,6 @@ struct das16_private_struct { unsigned long adc_byte_count; unsigned int divisor1; unsigned int divisor2; - struct comedi_lrange *user_ai_range_table; struct comedi_lrange *user_ao_range_table; struct timer_list timer; short timer_running; @@ -952,6 +951,42 @@ static void das16_free_dma(struct comedi_device *dev) } } +static const struct comedi_lrange *das16_ai_range(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_devconfig *it, + unsigned int pg_type, + unsigned int status) +{ + unsigned int min = it->options[4]; + unsigned int max = it->options[5]; + + /* get any user-defined input range */ + if (pg_type == das16_pg_none && (min || max)) { + struct comedi_lrange *lrange; + struct comedi_krange *krange; + + /* allocate single-range range table */ + lrange = comedi_alloc_spriv(s, + sizeof(*lrange) + sizeof(*krange)); + if (!lrange) + return &range_unknown; + + /* initialize ai range */ + lrange->length = 1; + krange = lrange->range; + krange->min = min; + krange->max = max; + krange->flags = UNIT_volt; + + return lrange; + } + + /* use software programmable range */ + if (status & DAS16_STATUS_UNIPOLAR) + return das16_ai_uni_lranges[pg_type]; + return das16_ai_bip_lranges[pg_type]; +} + static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct das16_board *board = dev->board_ptr; @@ -1015,23 +1050,6 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) das16_alloc_dma(dev, it->options[2]); - /* get any user-defined input range */ - if (board->ai_pg == das16_pg_none && - (it->options[4] || it->options[5])) { - /* allocate single-range range table */ - lrange = kzalloc(sizeof(*lrange) + sizeof(*krange), GFP_KERNEL); - if (!lrange) - return -ENOMEM; - - /* initialize ai range */ - devpriv->user_ai_range_table = lrange; - lrange->length = 1; - krange = devpriv->user_ai_range_table->range; - krange->min = it->options[4]; - krange->max = it->options[5]; - krange->flags = UNIT_volt; - } - /* get any user-defined output range */ if (it->options[6] || it->options[7]) { /* allocate single-range range table */ @@ -1067,13 +1085,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) } s->len_chanlist = s->n_chan; s->maxdata = board->ai_maxdata; - if (devpriv->user_ai_range_table) { /* user defined ai range */ - s->range_table = devpriv->user_ai_range_table; - } else if (status & DAS16_STATUS_UNIPOLAR) { - s->range_table = das16_ai_uni_lranges[board->ai_pg]; - } else { - s->range_table = das16_ai_bip_lranges[board->ai_pg]; - } + s->range_table = das16_ai_range(dev, s, it, board->ai_pg, status); s->insn_read = das16_ai_insn_read; if (devpriv->dma) { dev->read_subdev = s; @@ -1153,7 +1165,6 @@ static void das16_detach(struct comedi_device *dev) if (dev->iobase) das16_reset(dev); das16_free_dma(dev); - kfree(devpriv->user_ai_range_table); kfree(devpriv->user_ao_range_table); if (devpriv->extra_iobase) -- cgit v0.10.2 From 23a5c3ee7c9a2e0f3bcb229bf0c14ae5971d74c9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 26 Jan 2015 16:17:17 -0700 Subject: staging: comedi: das16: introduce das16_ao_range() Clarify the (*attach) a bit by introducing a helper function to handle the setup of the analog output 'range_table'. Some of the boards supported by this driver do not have programmable ranges. The analog output subdevice can use optional range information provided by the user during the attach of the driver. Currently this range data is allocated and stored in the private data. Use the subdevice private data member instead and allocate the memory with comedi_alloc_spriv(). The comedi core will automatically free this memory when the driver is detached. If the allocation fails set the 'range_table' to 'range_unknown' instead of failing the driver attach. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index cb38e4b..5ad4c38 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -443,7 +443,6 @@ struct das16_private_struct { unsigned long adc_byte_count; unsigned int divisor1; unsigned int divisor2; - struct comedi_lrange *user_ao_range_table; struct timer_list timer; short timer_running; unsigned long extra_iobase; @@ -987,13 +986,42 @@ static const struct comedi_lrange *das16_ai_range(struct comedi_device *dev, return das16_ai_bip_lranges[pg_type]; } +static const struct comedi_lrange *das16_ao_range(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_devconfig *it) +{ + unsigned int min = it->options[6]; + unsigned int max = it->options[7]; + + /* get any user-defined output range */ + if (min || max) { + struct comedi_lrange *lrange; + struct comedi_krange *krange; + + /* allocate single-range range table */ + lrange = comedi_alloc_spriv(s, + sizeof(*lrange) + sizeof(*krange)); + if (!lrange) + return &range_unknown; + + /* initialize ao range */ + lrange->length = 1; + krange = lrange->range; + krange->min = min; + krange->max = max; + krange->flags = UNIT_volt; + + return lrange; + } + + return &range_unknown; +} + static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct das16_board *board = dev->board_ptr; struct das16_private_struct *devpriv; struct comedi_subdevice *s; - struct comedi_lrange *lrange; - struct comedi_krange *krange; unsigned int status; int ret; @@ -1050,22 +1078,6 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) das16_alloc_dma(dev, it->options[2]); - /* get any user-defined output range */ - if (it->options[6] || it->options[7]) { - /* allocate single-range range table */ - lrange = kzalloc(sizeof(*lrange) + sizeof(*krange), GFP_KERNEL); - if (!lrange) - return -ENOMEM; - - /* initialize ao range */ - devpriv->user_ao_range_table = lrange; - lrange->length = 1; - krange = devpriv->user_ao_range_table->range; - krange->min = it->options[6]; - krange->max = it->options[7]; - krange->flags = UNIT_volt; - } - ret = comedi_alloc_subdevices(dev, 4 + board->has_8255); if (ret) return ret; @@ -1103,7 +1115,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->subdev_flags = SDF_WRITABLE; s->n_chan = 2; s->maxdata = 0x0fff; - s->range_table = devpriv->user_ao_range_table; + s->range_table = das16_ao_range(dev, s, it); s->insn_write = das16_ao_insn_write; ret = comedi_alloc_subdev_readback(s); @@ -1165,7 +1177,6 @@ static void das16_detach(struct comedi_device *dev) if (dev->iobase) das16_reset(dev); das16_free_dma(dev); - kfree(devpriv->user_ao_range_table); if (devpriv->extra_iobase) release_region(devpriv->extra_iobase, -- cgit v0.10.2 From 29538110470aec8a9b0a378d10371821d8f6e27e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 26 Jan 2015 16:17:18 -0700 Subject: staging: comedi: das16: change type of private data 'timer_running' This member of the private data is a true/false flag. For aesthetics, change the type to an unsigned int bit-field to save a bit of space. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 5ad4c38..81fa28d 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -444,9 +444,9 @@ struct das16_private_struct { unsigned int divisor1; unsigned int divisor2; struct timer_list timer; - short timer_running; unsigned long extra_iobase; unsigned int can_burst:1; + unsigned int timer_running:1; }; static void das16_interrupt(struct comedi_device *dev) -- cgit v0.10.2 From 42c44682a59a6ea38a301c20a4ec807c6fabdd02 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 26 Jan 2015 16:17:19 -0700 Subject: staging: comedi: das16: use comedi_async 'scans_done' to detect EOA Refactor das16_interrupt() to use the comedi_async 'scans_done' member to detect the End-of-Acquisition for the async command. Use the helper function comedi_nsamples_left() to determine if DMA needs to be restarted. This allows the removal of the private data 'adc_byte_count' and fixes a possible integer overflow issue when that value is calculated. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 81fa28d..3a2a6cc 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -440,7 +440,6 @@ struct das16_private_struct { struct comedi_isadma *dma; unsigned int clockbase; unsigned int ctrl_reg; - unsigned long adc_byte_count; unsigned int divisor1; unsigned int divisor2; struct timer_list timer; @@ -458,8 +457,9 @@ static void das16_interrupt(struct comedi_device *dev) struct comedi_isadma *dma = devpriv->dma; struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; unsigned long spin_flags; + unsigned int residue; + unsigned int nbytes; unsigned int nsamples; - int num_bytes, residue; spin_lock_irqsave(&dev->spinlock, spin_flags); if (!(devpriv->ctrl_reg & DAS16_CTRL_DMAE)) { @@ -475,36 +475,33 @@ static void das16_interrupt(struct comedi_device *dev) residue = comedi_isadma_disable_on_sample(desc->chan, comedi_bytes_per_sample(s)); - /* figure out how many points to read */ + /* figure out how many samples to read */ if (residue > desc->size) { dev_err(dev->class_dev, "residue > transfer size!\n"); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - num_bytes = 0; - } else - num_bytes = desc->size - residue; - - if (cmd->stop_src == TRIG_COUNT && - num_bytes >= devpriv->adc_byte_count) { - num_bytes = devpriv->adc_byte_count; - async->events |= COMEDI_CB_EOA; + async->events |= COMEDI_CB_ERROR; + nbytes = 0; + } else { + nbytes = desc->size - residue; } + nsamples = comedi_bytes_to_samples(s, nbytes); - dma->cur_dma = 1 - dma->cur_dma; - devpriv->adc_byte_count -= num_bytes; - - /* re-enable dma */ - if (!(async->events & COMEDI_CB_CANCEL_MASK)) { - struct comedi_isadma_desc *nxt_desc = &dma->desc[dma->cur_dma]; + /* restart DMA if more samples are needed */ + if (nsamples && nsamples < comedi_nsamples_left(s, nsamples + 1)) { + struct comedi_isadma_desc *nxt_desc; + dma->cur_dma = 1 - dma->cur_dma; + nxt_desc = &dma->desc[dma->cur_dma]; nxt_desc->size = nxt_desc->maxsize; comedi_isadma_program(nxt_desc); } spin_unlock_irqrestore(&dev->spinlock, spin_flags); - nsamples = comedi_bytes_to_samples(s, num_bytes); comedi_buf_write_samples(s, desc->virt_addr, nsamples); + if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) + async->events |= COMEDI_CB_EOA; + comedi_handle_events(dev, s); } @@ -688,8 +685,6 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) return -1; } - devpriv->adc_byte_count = cmd->stop_arg * comedi_bytes_per_scan(s); - if (devpriv->can_burst) outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG); -- cgit v0.10.2 From 1dc6e72903f6dbefd79ea2e9ce9c9e536e4e695b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 26 Jan 2015 16:17:20 -0700 Subject: staging: comedi: das16: fix DMA size for short transfers Currently this driver alwasy programs the DMA transfer to be the allocated size of the DMA buffer. When the async command 'stop_src' is TRIG_COUNT its possible (likely) for the last transfer to be less than the buffer size. Introduce a helper function, das16_ai_setup_dma(), to calculate the actual size of the DMA transfer based on the number of samples remaining and the number of unread samples. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 3a2a6cc..86e90d5 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -448,6 +448,28 @@ struct das16_private_struct { unsigned int timer_running:1; }; +static void das16_ai_setup_dma(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int unread_samples) +{ + struct das16_private_struct *devpriv = dev->private; + struct comedi_isadma *dma = devpriv->dma; + struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; + unsigned int max_samples = comedi_bytes_to_samples(s, desc->maxsize); + unsigned int nsamples; + + /* + * Determine dma size based on the buffer size plus the number of + * unread samples and the number of samples remaining in the command. + */ + nsamples = comedi_nsamples_left(s, max_samples + unread_samples); + if (nsamples > unread_samples) { + nsamples -= unread_samples; + desc->size = comedi_samples_to_bytes(s, nsamples); + comedi_isadma_program(desc); + } +} + static void das16_interrupt(struct comedi_device *dev) { struct das16_private_struct *devpriv = dev->private; @@ -486,13 +508,9 @@ static void das16_interrupt(struct comedi_device *dev) nsamples = comedi_bytes_to_samples(s, nbytes); /* restart DMA if more samples are needed */ - if (nsamples && nsamples < comedi_nsamples_left(s, nsamples + 1)) { - struct comedi_isadma_desc *nxt_desc; - + if (nsamples) { dma->cur_dma = 1 - dma->cur_dma; - nxt_desc = &dma->desc[dma->cur_dma]; - nxt_desc->size = nxt_desc->maxsize; - comedi_isadma_program(nxt_desc); + das16_ai_setup_dma(dev, s, nsamples); } spin_unlock_irqrestore(&dev->spinlock, spin_flags); @@ -672,7 +690,6 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) const struct das16_board *board = dev->board_ptr; struct das16_private_struct *devpriv = dev->private; struct comedi_isadma *dma = devpriv->dma; - struct comedi_isadma_desc *desc = &dma->desc[0]; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned int byte; @@ -721,8 +738,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) /* set up dma transfer */ dma->cur_dma = 0; - desc->size = desc->maxsize; - comedi_isadma_program(desc); + das16_ai_setup_dma(dev, s, 0); /* set up timer */ spin_lock_irqsave(&dev->spinlock, flags); -- cgit v0.10.2 From 5cd23c492ebce9ac4d9e5dd883d732c1ed1498c3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 26 Jan 2015 16:17:21 -0700 Subject: staging: comedi: das16: introduce das16_ai_set_mux_range() Introduce a helper function to program the mux and gain for analog input single channel (*insn_read) and multi-channel (*do_cmd) operations. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 86e90d5..2c20311 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -537,6 +537,29 @@ static void das16_timer_interrupt(unsigned long arg) spin_unlock_irqrestore(&dev->spinlock, flags); } +static void das16_ai_set_mux_range(struct comedi_device *dev, + unsigned int first_chan, + unsigned int last_chan, + unsigned int range) +{ + const struct das16_board *board = dev->board_ptr; + + /* set multiplexer */ + outb(first_chan | (last_chan << 4), dev->iobase + DAS16_MUX_REG); + + /* some boards do not have programmable gain */ + if (board->ai_pg == das16_pg_none) + return; + + /* + * Set gain (this is also burst rate register but according to + * computer boards manual, burst rate does nothing, even on + * keithley cards). + */ + outb((das16_gainlists[board->ai_pg])[range], + dev->iobase + DAS16_GAIN_REG); +} + static int das16_ai_check_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) @@ -687,14 +710,15 @@ static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns, static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct das16_board *board = dev->board_ptr; struct das16_private_struct *devpriv = dev->private; struct comedi_isadma *dma = devpriv->dma; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; + unsigned int first_chan = CR_CHAN(cmd->chanlist[0]); + unsigned int last_chan = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]); + unsigned int range = CR_RANGE(cmd->chanlist[0]); unsigned int byte; unsigned long flags; - int range; if (cmd->flags & CMDF_PRIORITY) { dev_err(dev->class_dev, @@ -705,19 +729,8 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) if (devpriv->can_burst) outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG); - /* set scan limits */ - byte = CR_CHAN(cmd->chanlist[0]); - byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4; - outb(byte, dev->iobase + DAS16_MUX_REG); - - /* set gain (this is also burst rate register but according to - * computer boards manual, burst rate does nothing, even on - * keithley cards) */ - if (board->ai_pg != das16_pg_none) { - range = CR_RANGE(cmd->chanlist[0]); - outb((das16_gainlists[board->ai_pg])[range], - dev->iobase + DAS16_GAIN_REG); - } + /* set mux and range for chanlist scan */ + das16_ai_set_mux_range(dev, first_chan, last_chan, range); /* set counter mode and counts */ cmd->convert_arg = das16_set_pacer(dev, cmd->convert_arg, cmd->flags); @@ -826,21 +839,14 @@ static int das16_ai_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - const struct das16_board *board = dev->board_ptr; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int range = CR_RANGE(insn->chanspec); unsigned int val; int ret; int i; - /* set multiplexer */ - outb(chan | (chan << 4), dev->iobase + DAS16_MUX_REG); - - /* set gain */ - if (board->ai_pg != das16_pg_none) { - outb((das16_gainlists[board->ai_pg])[range], - dev->iobase + DAS16_GAIN_REG); - } + /* set mux and range for single channel */ + das16_ai_set_mux_range(dev, chan, chan, range); for (i = 0; i < insn->n; i++) { /* trigger conversion */ -- cgit v0.10.2 From 797f88947c022dd60127621a363dc1e96118e5d4 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 26 Jan 2015 12:06:05 +0000 Subject: staging: comedi: 8253.h: reformat copyright comment Use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h index 9f4c141..55f1704 100644 --- a/drivers/staging/comedi/drivers/8253.h +++ b/drivers/staging/comedi/drivers/8253.h @@ -1,20 +1,20 @@ /* - comedi/drivers/8253.h - Header file for 8253 - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/drivers/8253.h + * Header file for 8253 + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _8253_H #define _8253_H -- cgit v0.10.2 From 6400fb716d83039017cd9b3f13600e017647e5d1 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 26 Jan 2015 12:06:06 +0000 Subject: staging: comedi: 8253.h: reformat other block comments Use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h index 55f1704..0d9aec0 100644 --- a/drivers/staging/comedi/drivers/8253.h +++ b/drivers/staging/comedi/drivers/8253.h @@ -44,9 +44,11 @@ static inline void i8253_cascade_ns_to_timer(int i8253_osc_base, unsigned int start; unsigned int ns_low, ns_high; static const unsigned int max_count = 0x10000; - /* exit early if everything is already correct (this can save time + /* + * exit early if everything is already correct (this can save time * since this function may be called repeatedly during command tests - * and execution) */ + * and execution) + */ div1 = *d1 ? *d1 : max_count; div2 = *d2 ? *d2 : max_count; divider = div1 * div2; @@ -120,7 +122,8 @@ static inline void i8253_cascade_ns_to_timer(int i8253_osc_base, } #ifndef CMDTEST -/* i8254_load programs 8254 counter chip. It should also work for the 8253. +/* + * i8254_load programs 8254 counter chip. It should also work for the 8253. * base_address is the lowest io address * for the chip (the address of counter 0). * counter_number is the counter you want to load (0,1 or 2) @@ -274,7 +277,8 @@ static inline void i8254_mm_write(void __iomem *base_address, writeb(byte, base_address + (counter_number << regshift)); } -/* Set counter mode, should work for 8253 also. +/* + * Set counter mode, should work for 8253 also. * Note: the 'mode' value is different to that for i8254_load() and comes * from the INSN_CONFIG_8254_SET_MODE command: * I8254_MODE0, I8254_MODE1, ..., I8254_MODE5 -- cgit v0.10.2 From 5cc1e33cbdad8391522a92aec78c0efb0e124e22 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 26 Jan 2015 12:06:07 +0000 Subject: staging: comedi: 8253.h: use usual style for single-line comments Use one space after the opening and one space before the closing of the comment. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/8253.h b/drivers/staging/comedi/drivers/8253.h index 0d9aec0..51b9c8d 100644 --- a/drivers/staging/comedi/drivers/8253.h +++ b/drivers/staging/comedi/drivers/8253.h @@ -116,7 +116,7 @@ static inline void i8253_cascade_ns_to_timer(int i8253_osc_base, } *nanosec = div1 * div2 * i8253_osc_base; - /* masking is done since counter maps zero to 0x10000 */ + /* masking is done since counter maps zero to 0x10000 */ *d1 = div1 & 0xffff; *d2 = div2 & 0xffff; } @@ -161,12 +161,12 @@ static inline int i8254_load(unsigned long base_address, unsigned int regshift, return -1; byte = counter_number << 6; - byte |= 0x30; /* load low then high byte */ - byte |= (mode << 1); /* set counter mode */ + byte |= 0x30; /* load low then high byte */ + byte |= (mode << 1); /* set counter mode */ outb(byte, base_address + (i8254_control_reg << regshift)); - byte = count & 0xff; /* lsb of counter value */ + byte = count & 0xff; /* lsb of counter value */ outb(byte, base_address + (counter_number << regshift)); - byte = (count >> 8) & 0xff; /* msb of counter value */ + byte = (count >> 8) & 0xff; /* msb of counter value */ outb(byte, base_address + (counter_number << regshift)); return 0; @@ -190,18 +190,18 @@ static inline int i8254_mm_load(void __iomem *base_address, return -1; byte = counter_number << 6; - byte |= 0x30; /* load low then high byte */ - byte |= (mode << 1); /* set counter mode */ + byte |= 0x30; /* load low then high byte */ + byte |= (mode << 1); /* set counter mode */ writeb(byte, base_address + (i8254_control_reg << regshift)); - byte = count & 0xff; /* lsb of counter value */ + byte = count & 0xff; /* lsb of counter value */ writeb(byte, base_address + (counter_number << regshift)); - byte = (count >> 8) & 0xff; /* msb of counter value */ + byte = (count >> 8) & 0xff; /* msb of counter value */ writeb(byte, base_address + (counter_number << regshift)); return 0; } -/* Returns 16 bit counter value, should work for 8253 also.*/ +/* Returns 16 bit counter value, should work for 8253 also. */ static inline int i8254_read(unsigned long base_address, unsigned int regshift, unsigned int counter_number) { @@ -211,13 +211,13 @@ static inline int i8254_read(unsigned long base_address, unsigned int regshift, if (counter_number > 2) return -1; - /* latch counter */ + /* latch counter */ byte = counter_number << 6; outb(byte, base_address + (i8254_control_reg << regshift)); - /* read lsb */ + /* read lsb */ ret = inb(base_address + (counter_number << regshift)); - /* read msb */ + /* read msb */ ret += inb(base_address + (counter_number << regshift)) << 8; return ret; @@ -233,13 +233,13 @@ static inline int i8254_mm_read(void __iomem *base_address, if (counter_number > 2) return -1; - /* latch counter */ + /* latch counter */ byte = counter_number << 6; writeb(byte, base_address + (i8254_control_reg << regshift)); - /* read lsb */ + /* read lsb */ ret = readb(base_address + (counter_number << regshift)); - /* read msb */ + /* read msb */ ret += readb(base_address + (counter_number << regshift)) << 8; return ret; @@ -255,9 +255,9 @@ static inline void i8254_write(unsigned long base_address, if (counter_number > 2) return; - byte = count & 0xff; /* lsb of counter value */ + byte = count & 0xff; /* lsb of counter value */ outb(byte, base_address + (counter_number << regshift)); - byte = (count >> 8) & 0xff; /* msb of counter value */ + byte = (count >> 8) & 0xff; /* msb of counter value */ outb(byte, base_address + (counter_number << regshift)); } @@ -271,9 +271,9 @@ static inline void i8254_mm_write(void __iomem *base_address, if (counter_number > 2) return; - byte = count & 0xff; /* lsb of counter value */ + byte = count & 0xff; /* lsb of counter value */ writeb(byte, base_address + (counter_number << regshift)); - byte = (count >> 8) & 0xff; /* msb of counter value */ + byte = (count >> 8) & 0xff; /* msb of counter value */ writeb(byte, base_address + (counter_number << regshift)); } @@ -297,8 +297,8 @@ static inline int i8254_set_mode(unsigned long base_address, return -1; byte = counter_number << 6; - byte |= 0x30; /* load low then high byte */ - byte |= mode; /* set counter mode and BCD|binary */ + byte |= 0x30; /* load low then high byte */ + byte |= mode; /* set counter mode and BCD|binary */ outb(byte, base_address + (i8254_control_reg << regshift)); return 0; @@ -317,8 +317,8 @@ static inline int i8254_mm_set_mode(void __iomem *base_address, return -1; byte = counter_number << 6; - byte |= 0x30; /* load low then high byte */ - byte |= mode; /* set counter mode and BCD|binary */ + byte |= 0x30; /* load low then high byte */ + byte |= mode; /* set counter mode and BCD|binary */ writeb(byte, base_address + (i8254_control_reg << regshift)); return 0; -- cgit v0.10.2 From b40369d654442dbafae06f56811ac8e9912c49b1 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 26 Jan 2015 13:25:21 +0000 Subject: staging: comedi: 8255.c: reformat copyright comment Use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 34d4d8b..ed1f065 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -1,20 +1,21 @@ /* - comedi/drivers/8255.c - Driver for 8255 - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + * comedi/drivers/8255.c + * Driver for 8255 + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ /* Driver: 8255 Description: generic 8255 support -- cgit v0.10.2 From 20f2ff887fdcb20a84b77ce8e45b2de2668c66e0 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 26 Jan 2015 13:25:22 +0000 Subject: staging: comedi: 8255.c: reformat comedi driver comment Use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index ed1f065..fafe40b 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -17,37 +17,36 @@ */ /* -Driver: 8255 -Description: generic 8255 support -Devices: [standard] 8255 (8255) -Author: ds -Status: works -Updated: Fri, 7 Jun 2002 12:56:45 -0700 - -The classic in digital I/O. The 8255 appears in Comedi as a single -digital I/O subdevice with 24 channels. The channel 0 corresponds -to the 8255's port A, bit 0; channel 23 corresponds to port C, bit -7. Direction configuration is done in blocks, with channels 0-7, -8-15, 16-19, and 20-23 making up the 4 blocks. The only 8255 mode -supported is mode 0. - -You should enable compilation this driver if you plan to use a board -that has an 8255 chip. For multifunction boards, the main driver will -configure the 8255 subdevice automatically. - -This driver also works independently with ISA and PCI cards that -directly map the 8255 registers to I/O ports, including cards with -multiple 8255 chips. To configure the driver for such a card, the -option list should be a list of the I/O port bases for each of the -8255 chips. For example, - - comedi_config /dev/comedi0 8255 0x200,0x204,0x208,0x20c - -Note that most PCI 8255 boards do NOT work with this driver, and -need a separate driver as a wrapper. For those that do work, the -I/O port base address can be found in the output of 'lspci -v'. - -*/ + * Driver: 8255 + * Description: generic 8255 support + * Devices: [standard] 8255 (8255) + * Author: ds + * Status: works + * Updated: Fri, 7 Jun 2002 12:56:45 -0700 + * + * The classic in digital I/O. The 8255 appears in Comedi as a single + * digital I/O subdevice with 24 channels. The channel 0 corresponds + * to the 8255's port A, bit 0; channel 23 corresponds to port C, bit + * 7. Direction configuration is done in blocks, with channels 0-7, + * 8-15, 16-19, and 20-23 making up the 4 blocks. The only 8255 mode + * supported is mode 0. + * + * You should enable compilation this driver if you plan to use a board + * that has an 8255 chip. For multifunction boards, the main driver will + * configure the 8255 subdevice automatically. + * + * This driver also works independently with ISA and PCI cards that + * directly map the 8255 registers to I/O ports, including cards with + * multiple 8255 chips. To configure the driver for such a card, the + * option list should be a list of the I/O port bases for each of the + * 8255 chips. For example, + * + * comedi_config /dev/comedi0 8255 0x200,0x204,0x208,0x20c + * + * Note that most PCI 8255 boards do NOT work with this driver, and + * need a separate driver as a wrapper. For those that do work, the + * I/O port base address can be found in the output of 'lspci -v'. + */ /* This file contains an exported subdevice for driving an 8255. -- cgit v0.10.2 From 3479610cfa8a402d0aa7f1db4ab276a6dbc330c6 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 26 Jan 2015 13:25:23 +0000 Subject: staging: comedi: 8255.c: document subdev_8255_init() and _mm_init() Add kerneldoc comments for the subdev_8255_init() and subdev_8255_mm_init() functions and remove the other comment about how to use this module in a comedi driver. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index fafe40b..1476157 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -48,31 +48,6 @@ * I/O port base address can be found in the output of 'lspci -v'. */ -/* - This file contains an exported subdevice for driving an 8255. - - To use this subdevice as part of another driver, you need to - set up the subdevice in the attach function of the driver by - calling: - - subdev_8255_init(device, subdevice, io_function, iobase) - - device and subdevice are pointers to the device and subdevice - structures. io_function will be called to provide the - low-level input/output to the device, i.e., actual register - access. io_function will be called with the value of iobase - as the last parameter. If the 8255 device is mapped as 4 - consecutive I/O ports, you can use NULL for io_function - and the I/O port base for iobase, and an internal function will - handle the register access. - - In addition, if the main driver handles interrupts, you can - enable commands on the subdevice by calling subdev_8255_init_irq() - instead. Then, when you get an interrupt that is likely to be - from the 8255, you should call subdev_8255_interrupt(), which - will copy the latched value to a Comedi buffer. - */ - #include #include "../comedidev.h" @@ -218,6 +193,33 @@ static int __subdev_8255_init(struct comedi_device *dev, return 0; } +/** + * subdev_8255_init - initialize DIO subdevice for driving I/O mapped 8255 + * @dev: comedi device owning subdevice + * @s: comedi subdevice to initialize + * @io: (optional) register I/O call-back function + * @regbase: offset of 8255 registers from dev->iobase, or call-back context + * + * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. + * + * If the optional I/O call-back function is provided, its prototype is of + * the following form: + * + * int my_8255_callback(struct comedi_device *dev, + * struct comedi_subdevice *s, int dir, int port, + * int data, unsigned long regbase); + * + * where 'dev', 's', and 'regbase' match the values passed to this function, + * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' + * is the direction (0 for read, 1 for write) and 'data' is the value to be + * written. It should return 0 if writing or the value read if reading. + * + * If the optional I/O call-back function is not provided, an internal + * call-back function is used which uses consecutive I/O port addresses + * starting at dev->iobase + regbase. + * + * Return: -ENOMEM if failed to allocate memory, zero on success. + */ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, int (*io)(struct comedi_device *, int, int, int, unsigned long), @@ -227,6 +229,33 @@ int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, } EXPORT_SYMBOL_GPL(subdev_8255_init); +/** + * subdev_8255_mm_init - initialize DIO subdevice for driving mmio-mapped 8255 + * @dev: comedi device owning subdevice + * @s: comedi subdevice to initialize + * @io: (optional) register I/O call-back function + * @regbase: offset of 8255 registers from dev->mmio, or call-back context + * + * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. + * + * If the optional I/O call-back function is provided, its prototype is of + * the following form: + * + * int my_8255_callback(struct comedi_device *dev, + * struct comedi_subdevice *s, int dir, int port, + * int data, unsigned long regbase); + * + * where 'dev', 's', and 'regbase' match the values passed to this function, + * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' + * is the direction (0 for read, 1 for write) and 'data' is the value to be + * written. It should return 0 if writing or the value read if reading. + * + * If the optional I/O call-back function is not provided, an internal + * call-back function is used which uses consecutive MMIO virtual addresses + * starting at dev->mmio + regbase. + * + * Return: -ENOMEM if failed to allocate memory, zero on success. + */ int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s, int (*io)(struct comedi_device *, int, int, int, unsigned long), -- cgit v0.10.2 From bf2bd4a762aad23ff501c36a5b9bbc98b4ea5724 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 26 Jan 2015 13:25:24 +0000 Subject: staging: comedi: 8255.c: reformat remaining block comments Use the usual block comment formatting style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 1476157..c2f15de 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -264,10 +264,9 @@ int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s, return __subdev_8255_init(dev, s, io, regbase, true); } EXPORT_SYMBOL_GPL(subdev_8255_mm_init); -/* - - Start of the 8255 standalone device +/* + * Start of the 8255 standalone device */ static int dev_8255_attach(struct comedi_device *dev, -- cgit v0.10.2 From 7e6fd0202b3b511a2dbc09776d8734dca140c840 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 26 Jan 2015 13:25:25 +0000 Subject: staging: comedi: 8255.h: reformat copyright comment Use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/8255.h b/drivers/staging/comedi/drivers/8255.h index 5985c8e..934b940 100644 --- a/drivers/staging/comedi/drivers/8255.h +++ b/drivers/staging/comedi/drivers/8255.h @@ -1,20 +1,20 @@ /* - module/8255.h - Header file for 8255 - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * module/8255.h + * Header file for 8255 + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _8255_H #define _8255_H -- cgit v0.10.2 From 119c964399559e4bbfda9cdd7161c499ddba1470 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 26 Jan 2015 14:28:56 +0000 Subject: staging: comedi: addi_apci_1032: add comedi driver comment Add a comedi driver comment in a form suitable for importing into Comedilib documentation. The information about the change-of-state subdevice has been pulled from other comments in the driver. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index bf14165..4911b62 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -22,6 +22,54 @@ * more details. */ +/* + * Driver: addi_apci_1032 + * Description: ADDI-DATA APCI-1032 Digital Input Board + * Author: ADDI-DATA GmbH , + * H Hartley Sweeten + * Status: untested + * Devices: [ADDI-DATA] APCI-1032 (addi_apci_1032) + * + * Configuration options: + * None; devices are configured automatically. + * + * This driver models the APCI-1032 as a 32-channel, digital input subdevice + * plus an additional digital input subdevice to handle change-of-state (COS) + * interrupts (if an interrupt handler can be set up successfully). + * + * The COS subdevice supports comedi asynchronous read commands. + * + * Change-Of-State (COS) interrupt configuration: + * + * Channels 0 to 15 are interruptible. These channels can be configured + * to generate interrupts based on AND/OR logic for the desired channels. + * + * OR logic: + * - reacts to rising or falling edges + * - interrupt is generated when any enabled channel meets the desired + * interrupt condition + * + * AND logic: + * - reacts to changes in level of the selected inputs + * - interrupt is generated when all enabled channels meet the desired + * interrupt condition + * - after an interrupt, a change in level must occur on the selected + * inputs to release the IRQ logic + * + * The COS subdevice must be configured before setting up a comedi + * asynchronous command: + * + * data[0] : INSN_CONFIG_DIGITAL_TRIG + * data[1] : trigger number (= 0) + * data[2] : configuration operation: + * - COMEDI_DIGITAL_TRIG_DISABLE = no interrupts + * - COMEDI_DIGITAL_TRIG_ENABLE_EDGES = OR (edge) interrupts + * - COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = AND (level) interrupts + * data[3] : left-shift for data[4] and data[5] + * data[4] : rising-edge/high level channels + * data[5] : falling-edge/low level channels + */ + #include #include #include @@ -62,36 +110,6 @@ static int apci1032_reset(struct comedi_device *dev) return 0; } -/* - * Change-Of-State (COS) interrupt configuration - * - * Channels 0 to 15 are interruptible. These channels can be configured - * to generate interrupts based on AND/OR logic for the desired channels. - * - * OR logic - * - reacts to rising or falling edges - * - interrupt is generated when any enabled channel - * meet the desired interrupt condition - * - * AND logic - * - reacts to changes in level of the selected inputs - * - interrupt is generated when all enabled channels - * meet the desired interrupt condition - * - after an interrupt, a change in level must occur on - * the selected inputs to release the IRQ logic - * - * The COS interrupt must be configured before it can be enabled. - * - * data[0] : INSN_CONFIG_DIGITAL_TRIG - * data[1] : trigger number (= 0) - * data[2] : configuration operation: - * COMEDI_DIGITAL_TRIG_DISABLE = no interrupts - * COMEDI_DIGITAL_TRIG_ENABLE_EDGES = OR (edge) interrupts - * COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = AND (level) interrupts - * data[3] : left-shift for data[4] and data[5] - * data[4] : rising-edge/high level channels - * data[5] : falling-edge/low level channels - */ static int apci1032_cos_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, -- cgit v0.10.2 From fd27ae76d29d59aa834bf26d45535b1ba09ab543 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 26 Jan 2015 14:20:15 -0700 Subject: staging: comedi: pcl812: fix logic error in pcl812_ai_setup_dma() commit 92afc2b229038d7b962ae69de5b07bc6c1cf51bf inroduced a logic error in the DMA size calculation. If the 'nsamples' is greater than the 'unread_samples' then DMA needs to be restarted. The current code checks it agains the 'max_samples'. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 37cc5e4..3ffb1ea 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -559,8 +559,8 @@ static void pcl812_ai_setup_dma(struct comedi_device *dev, * unread samples and the number of samples remaining in the command. */ nsamples = comedi_nsamples_left(s, max_samples + unread_samples); - if (nsamples > max_samples) { - nsamples -= max_samples; + if (nsamples > unread_samples) { + nsamples -= unread_samples; desc->size = comedi_samples_to_bytes(s, nsamples); comedi_isadma_program(desc); } -- cgit v0.10.2 From d1a6b736284cb0f618ff82abb79c2dd7fcad33dd Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 17:49:01 +0000 Subject: staging: comedi: add comedi_usb.h Add a new header that Comedi USB drivers can include instead of "comedidev.h". Currently, it just pulls in and "comedidev.h", but the plan is to migrate the USB-specific stuff from "comedidev.h" here. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_usb.h b/drivers/staging/comedi/comedi_usb.h new file mode 100644 index 0000000..a57025b --- /dev/null +++ b/drivers/staging/comedi/comedi_usb.h @@ -0,0 +1,30 @@ +/* + * comedi_usb.h + * header file for USB Comedi drivers + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _COMEDI_USB_H +#define _COMEDI_USB_H + +#include + +#include "comedidev.h" + +/* + * TODO: Move USB-specific stuff into here from "comedidev.h". + */ + +#endif /* _COMEDI_USB_H */ -- cgit v0.10.2 From 08f6b95b7a6e7c33a51e80d40f79b15160bd585e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 17:49:02 +0000 Subject: staging: comedi: comedi_usb.c: include new "comedi_usb.h" header Include the new "comedi_usb.h" header instead of and "comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_usb.c b/drivers/staging/comedi/comedi_usb.c index 0b862a6..68b75e8 100644 --- a/drivers/staging/comedi/comedi_usb.c +++ b/drivers/staging/comedi/comedi_usb.c @@ -17,9 +17,8 @@ */ #include -#include -#include "comedidev.h" +#include "comedi_usb.h" /** * comedi_to_usb_interface() - comedi_device pointer to usb_interface pointer. -- cgit v0.10.2 From 2079377a15a48601d3c498b37ad25ebeb4edacdb Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 17:49:03 +0000 Subject: staging: comedi: dt9812: include new "comedi_usb.h" header Include the new "../comedi_usb.h" header instead of and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 06c601d..e11c216 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -42,9 +42,8 @@ for my needs. #include #include #include -#include -#include "../comedidev.h" +#include "../comedi_usb.h" #define DT9812_DIAGS_BOARD_INFO_ADDR 0xFBFF #define DT9812_MAX_WRITE_CMD_PIPE_SIZE 32 -- cgit v0.10.2 From 3fdffa5d140e7b9fe37d33870b8ed99a14c9980a Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 17:49:04 +0000 Subject: staging: comedi: ni_usb6501: include new "comedi_usb.h" header Include the new "../comedi_usb.h" header instead of and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_usb6501.c b/drivers/staging/comedi/drivers/ni_usb6501.c index 3b5a1b9..5f649f8 100644 --- a/drivers/staging/comedi/drivers/ni_usb6501.c +++ b/drivers/staging/comedi/drivers/ni_usb6501.c @@ -96,9 +96,8 @@ #include #include #include -#include -#include "../comedidev.h" +#include "../comedi_usb.h" #define NI6501_TIMEOUT 1000 -- cgit v0.10.2 From dd74344b0e53cab4f4f8da40900ee4fc652bab11 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 17:49:05 +0000 Subject: staging: comedi: usbdux: include new "comedi_usb.h" header Include the new "../comedi_usb.h" header instead of and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 0683d6a..1cd7403 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -80,11 +80,10 @@ #include #include #include -#include #include #include -#include "../comedidev.h" +#include "../comedi_usb.h" #include "comedi_fc.h" -- cgit v0.10.2 From d3f839528aef38151e4b1bb12f21f49587200139 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 17:49:06 +0000 Subject: staging: comedi: usbduxfast: include new "comedi_usb.h" header Include the new "../comedi_usb.h" header instead of and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 85071da..7ce27c1 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -46,11 +46,10 @@ #include #include #include -#include #include #include #include "comedi_fc.h" -#include "../comedidev.h" +#include "../comedi_usb.h" /* * timeout for the USB-transfer -- cgit v0.10.2 From bf98d732d7eb3c89dfcf4716e6824363d559ebe5 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 17:49:07 +0000 Subject: staging: comedi: usbduxsigma: include new "comedi_usb.h" header Include the new "../comedi_usb.h" header instead of and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 17e5a81..378c449 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -45,13 +45,12 @@ #include #include #include -#include #include #include #include #include "comedi_fc.h" -#include "../comedidev.h" +#include "../comedi_usb.h" /* timeout for the USB-transfer in ms*/ #define BULK_TIMEOUT 1000 -- cgit v0.10.2 From cf7661c74e2a051132f64440fc40cd46c06b60dc Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 17:49:08 +0000 Subject: staging: comedi: vmk80xx: include new "comedi_usb.h" header Include the new "../comedi_usb.h" header instead of and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index eb76460..e371183 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -42,10 +42,9 @@ #include #include #include -#include #include -#include "../comedidev.h" +#include "../comedi_usb.h" enum { DEVICE_VMK8055, -- cgit v0.10.2 From c7d623d3695ae5c193f08d2346c936c24f56dd4c Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 17:49:09 +0000 Subject: staging: comedi: comedi_usb.h: move USB stuff out of comedidev.h Move the USB-specific stuff out of "comedidev.h" into "comedi_usb.h". Comedi USB drivers now include "comedi_usb.h" instead of "comedidev.h", which now gets pulled in indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_usb.h b/drivers/staging/comedi/comedi_usb.h index a57025b..721128b 100644 --- a/drivers/staging/comedi/comedi_usb.h +++ b/drivers/staging/comedi/comedi_usb.h @@ -23,8 +23,28 @@ #include "comedidev.h" -/* - * TODO: Move USB-specific stuff into here from "comedidev.h". +struct usb_interface *comedi_to_usb_interface(struct comedi_device *); +struct usb_device *comedi_to_usb_dev(struct comedi_device *); + +int comedi_usb_auto_config(struct usb_interface *, struct comedi_driver *, + unsigned long context); +void comedi_usb_auto_unconfig(struct usb_interface *); + +int comedi_usb_driver_register(struct comedi_driver *, struct usb_driver *); +void comedi_usb_driver_unregister(struct comedi_driver *, struct usb_driver *); + +/** + * module_comedi_usb_driver() - Helper macro for registering a comedi USB driver + * @__comedi_driver: comedi_driver struct + * @__usb_driver: usb_driver struct + * + * Helper macro for comedi USB drivers which do not do anything special + * in module init/exit. This eliminates a lot of boilerplate. Each + * module may only use this macro once, and calling it replaces + * module_init() and module_exit() */ +#define module_comedi_usb_driver(__comedi_driver, __usb_driver) \ + module_driver(__comedi_driver, comedi_usb_driver_register, \ + comedi_usb_driver_unregister, &(__usb_driver)) #endif /* _COMEDI_USB_H */ diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index e5daaeb..bc1dfc1 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -629,33 +629,4 @@ void comedi_pcmcia_driver_unregister(struct comedi_driver *, module_driver(__comedi_driver, comedi_pcmcia_driver_register, \ comedi_pcmcia_driver_unregister, &(__pcmcia_driver)) -/* comedi_usb.c - comedi USB driver specific functions */ - -struct usb_driver; -struct usb_interface; - -struct usb_interface *comedi_to_usb_interface(struct comedi_device *); -struct usb_device *comedi_to_usb_dev(struct comedi_device *); - -int comedi_usb_auto_config(struct usb_interface *, struct comedi_driver *, - unsigned long context); -void comedi_usb_auto_unconfig(struct usb_interface *); - -int comedi_usb_driver_register(struct comedi_driver *, struct usb_driver *); -void comedi_usb_driver_unregister(struct comedi_driver *, struct usb_driver *); - -/** - * module_comedi_usb_driver() - Helper macro for registering a comedi USB driver - * @__comedi_driver: comedi_driver struct - * @__usb_driver: usb_driver struct - * - * Helper macro for comedi USB drivers which do not do anything special - * in module init/exit. This eliminates a lot of boilerplate. Each - * module may only use this macro once, and calling it replaces - * module_init() and module_exit() - */ -#define module_comedi_usb_driver(__comedi_driver, __usb_driver) \ - module_driver(__comedi_driver, comedi_usb_driver_register, \ - comedi_usb_driver_unregister, &(__usb_driver)) - #endif /* _COMEDIDEV_H */ -- cgit v0.10.2 From 42b8ce6f55facfa101462e694d33fc6bca471138 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 18:16:51 +0000 Subject: staging: comedi: comedi_compat32.c: fix COMEDI_CMD copy back `do_cmd_ioctl()` in "comedi_fops.c" handles the `COMEDI_CMD` ioctl. This returns `-EAGAIN` if it has copied a modified `struct comedi_cmd` back to user-space. (This occurs when the low-level Comedi driver's `do_cmdtest()` handler returns non-zero to indicate a problem with the contents of the `struct comedi_cmd`, or when the `struct comedi_cmd` has the `CMDF_BOGUS` flag set.) `compat_cmd()` in "comedi_compat32.c" handles the 32-bit compatible version of the `COMEDI_CMD` ioctl. Currently, it never copies a 32-bit compatible version of `struct comedi_cmd` back to user-space, which is at odds with the way the regular `COMEDI_CMD` ioctl is handled. To fix it, change `compat_cmd()` to copy a 32-bit compatible version of the `struct comedi_cmd` back to user-space when the main ioctl handler returns `-EAGAIN`. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Cc: Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 5a4c74f..03a2d07 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -262,7 +262,7 @@ static int compat_cmd(struct file *file, unsigned long arg) { struct comedi_cmd __user *cmd; struct comedi32_cmd_struct __user *cmd32; - int rc; + int rc, err; cmd32 = compat_ptr(arg); cmd = compat_alloc_user_space(sizeof(*cmd)); @@ -271,7 +271,15 @@ static int compat_cmd(struct file *file, unsigned long arg) if (rc) return rc; - return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); + rc = translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd); + if (rc == -EAGAIN) { + /* Special case: copy cmd back to user. */ + err = put_compat_cmd(cmd32, cmd); + if (err) + rc = err; + } + + return rc; } /* Handle 32-bit COMEDI_CMDTEST ioctl. */ -- cgit v0.10.2 From 357535e25539bf801a1bd1e788dc1c13912fcf74 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 18:16:52 +0000 Subject: staging: comedi: comedi_compat32.h: reformat copyright comment Use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_compat32.h b/drivers/staging/comedi/comedi_compat32.h index 2d0a6fc..5ce77f3 100644 --- a/drivers/staging/comedi/comedi_compat32.h +++ b/drivers/staging/comedi/comedi_compat32.h @@ -1,23 +1,23 @@ /* - comedi/comedi_compat32.h - 32-bit ioctl compatibility for 64-bit comedi kernel module. - - Author: Ian Abbott, MEV Ltd. - Copyright (C) 2007 MEV Ltd. - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2007 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/comedi_compat32.h + * 32-bit ioctl compatibility for 64-bit comedi kernel module. + * + * Author: Ian Abbott, MEV Ltd. + * Copyright (C) 2007 MEV Ltd. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2007 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _COMEDI_COMPAT32_H #define _COMEDI_COMPAT32_H -- cgit v0.10.2 From 0a87c0eb131d38e378b7afd62bc1b8dc4378e2f3 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 18:26:55 +0000 Subject: staging: comedi: comedi_compat32.c: reformat copyright comment Use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 03a2d07..097fd4d 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -1,23 +1,23 @@ /* - comedi/comedi_compat32.c - 32-bit ioctl compatibility for 64-bit comedi kernel module. - - Author: Ian Abbott, MEV Ltd. - Copyright (C) 2007 MEV Ltd. - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2007 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/comedi_compat32.c + * 32-bit ioctl compatibility for 64-bit comedi kernel module. + * + * Author: Ian Abbott, MEV Ltd. + * Copyright (C) 2007 MEV Ltd. + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2007 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #include #include -- cgit v0.10.2 From 79b09aac000a8cd1facf3ce23958d2a911d88f33 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 18:16:54 +0000 Subject: staging: comedi: comedi_compat32.c: reformat other block comments Use the usual block comment style. Combine some consecutive comments into block comments. Also remove part of a comment referring to `ptr_to_compat()` not being implemented until kernel version 2.6.11 as it's irrelevant. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 097fd4d..acbacff 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -27,11 +27,15 @@ #define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct) #define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct) -/* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR. - * It's too late to change it now, but it only affects the command number. */ +/* + * N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR. + * It's too late to change it now, but it only affects the command number. + */ #define COMEDI32_CMD _IOR(CIO, 9, struct comedi32_cmd_struct) -/* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR. - * It's too late to change it now, but it only affects the command number. */ +/* + * N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR. + * It's too late to change it now, but it only affects the command number. + */ #define COMEDI32_CMDTEST _IOR(CIO, 10, struct comedi32_cmd_struct) #define COMEDI32_INSNLIST _IOR(CIO, 11, struct comedi32_insnlist_struct) #define COMEDI32_INSN _IOR(CIO, 12, struct comedi32_insn_struct) @@ -215,10 +219,12 @@ static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, int err; unsigned int temp; - /* Copy back most of cmd structure. */ - /* Assume the pointer values are already valid. */ - /* (Could use ptr_to_compat() to set them, but that wasn't implemented - * until kernel version 2.6.11.) */ + /* + * Copy back most of cmd structure. + * + * Assume the pointer values are already valid. + * (Could use ptr_to_compat() to set them.) + */ if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd)) || !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) return -EFAULT; @@ -403,8 +409,11 @@ static int compat_insn(struct file *file, unsigned long arg) return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn); } -/* Process untranslated ioctl. */ -/* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ +/* + * Process untranslated ioctl. + * + * Returns -ENOIOCTLCMD for unrecognised ioctl codes. + */ static inline int raw_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -454,8 +463,11 @@ static inline int raw_ioctl(struct file *file, unsigned int cmd, return rc; } -/* compat_ioctl file operation. */ -/* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ +/* + * compat_ioctl file operation. + * + * Returns -ENOIOCTLCMD for unrecognised ioctl codes. + */ long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return raw_ioctl(file, cmd, arg); -- cgit v0.10.2 From 0ec14885de68bfeafe9b57f72a7b1ed1c9395bba Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 18:16:55 +0000 Subject: staging: comedi: comedi_compat32.c: align some comments Align some comments attached to members of the 32-bit compatibility structure definitions. These comments describe the original pointer types that are being represented by a `compat_uptr_t`. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index acbacff..0eab6c6 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -43,7 +43,7 @@ struct comedi32_chaninfo_struct { unsigned int subdev; compat_uptr_t maxdata_list; /* 32-bit 'unsigned int *' */ - compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */ + compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */ compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */ unsigned int unused[4]; }; @@ -66,16 +66,16 @@ struct comedi32_cmd_struct { unsigned int scan_end_arg; unsigned int stop_src; unsigned int stop_arg; - compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */ + compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */ unsigned int chanlist_len; - compat_uptr_t data; /* 32-bit 'short *' */ + compat_uptr_t data; /* 32-bit 'short *' */ unsigned int data_len; }; struct comedi32_insn_struct { unsigned int insn; unsigned int n; - compat_uptr_t data; /* 32-bit 'unsigned int *' */ + compat_uptr_t data; /* 32-bit 'unsigned int *' */ unsigned int subdev; unsigned int chanspec; unsigned int unused[3]; @@ -83,7 +83,7 @@ struct comedi32_insn_struct { struct comedi32_insnlist_struct { unsigned int n_insns; - compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */ + compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */ }; /* Handle translated ioctl. */ -- cgit v0.10.2 From 023e89c00b6d914d39b2e2cc48706a198e3a1d7a Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 27 Jan 2015 18:16:56 +0000 Subject: staging: comedi: comedi_compat32.c: absorb raw_ioctl() `comedi_compat_ioctl()` just calls static inline function `raw_ioctl()` with the same parameters (although the former returns a `long` and the latter returns an `int`). Since `raw_ioctl()` is not called from anywhere else, just absorb its body into `comedi_compat_ioctl()`. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c index 0eab6c6..2584824 100644 --- a/drivers/staging/comedi/comedi_compat32.c +++ b/drivers/staging/comedi/comedi_compat32.c @@ -410,12 +410,11 @@ static int compat_insn(struct file *file, unsigned long arg) } /* - * Process untranslated ioctl. + * compat_ioctl file operation. * * Returns -ENOIOCTLCMD for unrecognised ioctl codes. */ -static inline int raw_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) +long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int rc; @@ -462,13 +461,3 @@ static inline int raw_ioctl(struct file *file, unsigned int cmd, } return rc; } - -/* - * compat_ioctl file operation. - * - * Returns -ENOIOCTLCMD for unrecognised ioctl codes. - */ -long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - return raw_ioctl(file, cmd, arg); -} -- cgit v0.10.2 From 462125b4ad255eafcd114e17bdc924d755da1567 Mon Sep 17 00:00:00 2001 From: Mauro Stettler Date: Sun, 25 Jan 2015 20:26:17 +0900 Subject: staging: flexfb: Remove initialization to 0 (the initial post had a typo in the short summary, reposting) This fixes some of the code style issues in the flexfb driver by removing unnecessary initializations of static variables to 0 or to NULL. Signed-off-by: Mauro Stettler Cc: Greg Kroah-Hartman Cc: Thomas Petazzoni Cc: Noralf Tronnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/flexfb.c b/drivers/staging/fbtft/flexfb.c index 45574a0..4eec888 100644 --- a/drivers/staging/fbtft/flexfb.c +++ b/drivers/staging/fbtft/flexfb.c @@ -31,24 +31,24 @@ #define DRVNAME "flexfb" -static char *chip = NULL; +static char *chip; module_param(chip, charp, 0); MODULE_PARM_DESC(chip, "LCD controller"); -static unsigned int width = 0; +static unsigned int width; module_param(width, uint, 0); MODULE_PARM_DESC(width, "Display width"); -static unsigned int height = 0; +static unsigned int height; module_param(height, uint, 0); MODULE_PARM_DESC(height, "Display height"); static int init[512]; -static int init_num = 0; +static int init_num; module_param_array(init, int, &init_num, 0); MODULE_PARM_DESC(init, "Init sequence"); -static unsigned int setaddrwin = 0; +static unsigned int setaddrwin; module_param(setaddrwin, uint, 0); MODULE_PARM_DESC(setaddrwin, "Which set_addr_win() implementation to use"); @@ -60,17 +60,17 @@ static unsigned int regwidth = 8; module_param(regwidth, uint, 0); MODULE_PARM_DESC(regwidth, "Width of controller register (default: 8)"); -static bool nobacklight = false; +static bool nobacklight; module_param(nobacklight, bool, 0); MODULE_PARM_DESC(nobacklight, "Turn off backlight functionality."); -static bool latched = false; +static bool latched; module_param(latched, bool, 0); MODULE_PARM_DESC(latched, "Use with latched 16-bit databus"); -static int *initp = NULL; -static int initp_num = 0; +static int *initp; +static int initp_num; /* default init sequences */ static int st7735r_init[] = { \ -- cgit v0.10.2 From 1167ff91da290cefc6e985c741dcab2a58c62452 Mon Sep 17 00:00:00 2001 From: Mariam Mohamed Fawzy Date: Mon, 26 Jan 2015 11:24:36 +0200 Subject: staging: vt6655: fix that open brace { should be on the previous line This patch fixes the following checkpatch.pl error: fix that open brace { should be on the previous line Signed-off-by: Mariam Mohamed Fawzy Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index 47801ca..1cdcf49 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -68,8 +68,8 @@ /*--------------------- Static Variables --------------------------*/ -static const unsigned short cwRXBCNTSFOff[MAX_RATE] = -{17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3}; +static const unsigned short cwRXBCNTSFOff[MAX_RATE] = { + 17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3}; /*--------------------- Static Functions --------------------------*/ -- cgit v0.10.2 From 2be90fef97ada3df61736435dc9ef6c3e432a747 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Mon, 26 Jan 2015 02:15:02 -0800 Subject: drivers/staging: use current->state helpers Call __set_current_state() instead of assigning the new state directly. These interfaces also aid CONFIG_DEBUG_ATOMIC_SLEEP environments, keeping track of who changed the state. Signed-off-by: Davidlohr Bueso Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index bffc161..92e2352 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -174,7 +174,7 @@ struct me_private_data { static inline void sleep(unsigned sec) { - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(sec * HZ); } diff --git a/drivers/staging/dgnc/dgnc_utils.c b/drivers/staging/dgnc/dgnc_utils.c index 61efc13..80b5133 100644 --- a/drivers/staging/dgnc/dgnc_utils.c +++ b/drivers/staging/dgnc/dgnc_utils.c @@ -12,7 +12,7 @@ */ int dgnc_ms_sleep(ulong ms) { - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((ms * HZ) / 1000); return signal_pending(current); } diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 9c68ccf..6ed35b6 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -780,7 +780,7 @@ static void long_sleep(int ms) if (in_interrupt()) { mdelay(ms); } else { - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((ms * HZ + 999) / 1000); } } diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c index 507fc9a..a031570 100644 --- a/drivers/staging/speakup/selection.c +++ b/drivers/staging/speakup/selection.c @@ -157,7 +157,7 @@ static void __speakup_paste_selection(struct work_struct *work) pasted += count; } remove_wait_queue(&vc->paste_wait, &wait); - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); tty_buffer_unlock_exclusive(&vc->port); tty_ldisc_deref(ld); diff --git a/drivers/staging/unisys/include/timskmod.h b/drivers/staging/unisys/include/timskmod.h index cff7983..4019a0d 100644 --- a/drivers/staging/unisys/include/timskmod.h +++ b/drivers/staging/unisys/include/timskmod.h @@ -133,7 +133,7 @@ * x - the number of seconds to sleep. */ #define SLEEP(x) \ - do { current->state = TASK_INTERRUPTIBLE; \ + do { __set_current_state(TASK_INTERRUPTIBLE); \ schedule_timeout((x)*HZ); \ } while (0) @@ -141,7 +141,7 @@ * x - the number of jiffies to sleep. */ #define SLEEPJIFFIES(x) \ - do { current->state = TASK_INTERRUPTIBLE; \ + do { __set_current_state(TASK_INTERRUPTIBLE); \ schedule_timeout(x); \ } while (0) -- cgit v0.10.2 From 6bcab6c76d79922565cf52e417a49b9d281fca8a Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Tue, 27 Jan 2015 22:33:03 +0200 Subject: staging: fbtft: fix space required after that ';' This patch fixes the following checkpatch.pl error: fix space required after that ';' Signed-off-by: Heba Aamer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c index 678ab8e..387190d 100644 --- a/drivers/staging/fbtft/fb_pcd8544.c +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -117,10 +117,10 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); - for (x=0;x<84;x++) { - for (y=0;y<6;y++) { + for (x=0; x<84; x++) { + for (y=0; y<6; y++) { *buf = 0x00; - for (i=0;i<8;i++) { + for (i=0; i<8; i++) { *buf |= (vmem16[(y*8+i)*84+x] ? 1 : 0) << i; } buf++; -- cgit v0.10.2 From 8dba63c856744d28a0731e8ef2d3ca6ddacab599 Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Tue, 27 Jan 2015 22:35:30 +0200 Subject: staging: fbtft: fix spaces required around that '=' This patch fixes the following checkpatch.pl error: fix spaces required around that '=' Signed-off-by: Heba Aamer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c index 387190d..ed0922d 100644 --- a/drivers/staging/fbtft/fb_pcd8544.c +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -117,10 +117,10 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); - for (x=0; x<84; x++) { - for (y=0; y<6; y++) { + for (x = 0; x<84; x++) { + for (y = 0; y<6; y++) { *buf = 0x00; - for (i=0; i<8; i++) { + for (i = 0; i<8; i++) { *buf |= (vmem16[(y*8+i)*84+x] ? 1 : 0) << i; } buf++; -- cgit v0.10.2 From e82fb2b1b4556ab36c40666c7edd9e010c3b0889 Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Tue, 27 Jan 2015 22:37:24 +0200 Subject: staging: fbtft: fix spaces required around that '<' This patch fixes the following checkpatch.pl error: fix spaces required around that '<' Signed-off-by: Heba Aamer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c index ed0922d..dd72bed 100644 --- a/drivers/staging/fbtft/fb_pcd8544.c +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -117,10 +117,10 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__); - for (x = 0; x<84; x++) { - for (y = 0; y<6; y++) { + for (x = 0; x < 84; x++) { + for (y = 0; y < 6; y++) { *buf = 0x00; - for (i = 0; i<8; i++) { + for (i = 0; i < 8; i++) { *buf |= (vmem16[(y*8+i)*84+x] ? 1 : 0) << i; } buf++; -- cgit v0.10.2 From 8ccf155386e670a3c6620510a4a3cb00fa76cd76 Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Tue, 27 Jan 2015 22:39:56 +0200 Subject: staging: fbtft: fix Macros with complex values should be enclosed in parentheses This patch fixes the following checkpatch.pl error: fix Macros with complex values should be enclosed in parentheses Signed-off-by: Heba Aamer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c index dd72bed..d20d432 100644 --- a/drivers/staging/fbtft/fb_pcd8544.c +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -33,7 +33,7 @@ #define DRVNAME "fb_pcd8544" #define WIDTH 84 #define HEIGHT 48 -#define TXBUFLEN 84*6 +#define TXBUFLEN (84*6) #define DEFAULT_GAMMA "40" /* gamma is used to control contrast in this driver */ static unsigned tc = 0; -- cgit v0.10.2 From 9b37a8a71719e324db763ca9dc47c7d804218afe Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Tue, 27 Jan 2015 22:42:59 +0200 Subject: staging: fbtft: fix do not initialise statics to 0 or NULL This patch fixes the following checkpatch.pl error: fix do not initialise statics to 0 or NULL Signed-off-by: Heba Aamer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c index d20d432..0510547 100644 --- a/drivers/staging/fbtft/fb_pcd8544.c +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -36,7 +36,7 @@ #define TXBUFLEN (84*6) #define DEFAULT_GAMMA "40" /* gamma is used to control contrast in this driver */ -static unsigned tc = 0; +static unsigned tc; module_param(tc, uint, 0); MODULE_PARM_DESC(tc, "TC[1:0] Temperature coefficient: 0-3 (default: 0)"); -- cgit v0.10.2 From b5480f7e927045c3cd483e935fb667f3c99251ae Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Tue, 27 Jan 2015 22:46:25 +0200 Subject: staging: fbtft: fix trailing whitespace This patch fixes the following checkpatch.pl error: fix trailing whitespace Signed-off-by: Heba Aamer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/fb_pcd8544.c b/drivers/staging/fbtft/fb_pcd8544.c index 0510547..8b9ebfb 100644 --- a/drivers/staging/fbtft/fb_pcd8544.c +++ b/drivers/staging/fbtft/fb_pcd8544.c @@ -59,14 +59,14 @@ static int init_display(struct fbtft_par *par) */ /* H=1 Temperature control */ - write_reg(par, 0x04 | (tc & 0x3)); /* + write_reg(par, 0x04 | (tc & 0x3)); /* 2:1 1 1:x TC1 - Temperature Coefficient: 0x10 0:x TC0 */ /* H=1 Bias system */ - write_reg(par, 0x10 | (bs & 0x7)); /* + write_reg(par, 0x10 | (bs & 0x7)); /* 4:1 1 3:0 0 2:x BS2 - Bias System @@ -82,7 +82,7 @@ static int init_display(struct fbtft_par *par) */ /* H=0 Display control */ - write_reg(par, 0x08 | 4); /* + write_reg(par, 0x08 | 4); /* 3:1 1 2:1 D - DE: 10=normal mode 1:0 0 -- cgit v0.10.2 From 6a2bada4ed7913888434725ce1eab55c29e61b24 Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Wed, 28 Jan 2015 15:29:05 +0200 Subject: staging: fbtft: remove redundant .owner This patch fixes the following coccicheck warning: No need to set .owner here. The core will do it. Signed-off-by: Heba Aamer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/fbtft/flexfb.c b/drivers/staging/fbtft/flexfb.c index 4eec888..90832c3 100644 --- a/drivers/staging/fbtft/flexfb.c +++ b/drivers/staging/fbtft/flexfb.c @@ -559,7 +559,6 @@ static const struct platform_device_id flexfb_platform_ids[] = { static struct platform_driver flexfb_platform_driver = { .driver = { .name = DRVNAME, - .owner = THIS_MODULE, }, .id_table = flexfb_platform_ids, .probe = flexfb_probe_pdev, -- cgit v0.10.2 From a0a23bbce7818c90c3d3370af966fefce07a8c9b Mon Sep 17 00:00:00 2001 From: John Stultz Date: Mon, 26 Jan 2015 12:07:32 -0800 Subject: staging: Remove the Android logger driver With the relase of Lollipop, Android no longer requires the logger driver. There are three patches which the android dev's still need before they drop logger on all their devices: [PATCH v4 1/5] pstores: use scnprintf [PATCH v2 2/5] pstore: remove superfluous memory size check [PATCH 3/5] pstore: handle zero-sized prz in series [PATCH v4 4/5] pstore: add pmsg [PATCH 5/5] pstore: selinux: add security in-core xattr support for pstore and debugfs But these seem to have been acked and are hopefully queued for upstream. So this patch removes the logger driver from staging. Cc: Rom Lemarchand , Cc: Mark Salyzyn Cc: Kees Cook Cc: Android Kernel Team Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 2ac0b61..8feb904 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -14,23 +14,6 @@ config ASHMEM It is, in theory, a good memory allocator for low-memory devices, because it can discard shared memory units when under memory pressure. -config ANDROID_LOGGER - tristate "Android log driver" - default n - ---help--- - This adds support for system-wide logging using four log buffers. - - These are: - - 1: main - 2: events - 3: radio - 4: system - - Log reading and writing is performed via normal Linux reads and - optimized writes. This optimization avoids logging having too - much overhead in the system. - config ANDROID_TIMED_OUTPUT bool "Timed output class driver" default y diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c deleted file mode 100644 index 59ea1a7..0000000 --- a/drivers/staging/android/logger.c +++ /dev/null @@ -1,807 +0,0 @@ -/* - * drivers/misc/logger.c - * - * A Logging Subsystem - * - * Copyright (C) 2007-2008 Google, Inc. - * - * Robert Love - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) "logger: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "logger.h" - -#include - -/** - * struct logger_log - represents a specific log, such as 'main' or 'radio' - * @buffer: The actual ring buffer - * @misc: The "misc" device representing the log - * @wq: The wait queue for @readers - * @readers: This log's readers - * @mutex: The mutex that protects the @buffer - * @w_off: The current write head offset - * @head: The head, or location that readers start reading at. - * @size: The size of the log - * @logs: The list of log channels - * - * This structure lives from module insertion until module removal, so it does - * not need additional reference counting. The structure is protected by the - * mutex 'mutex'. - */ -struct logger_log { - unsigned char *buffer; - struct miscdevice misc; - wait_queue_head_t wq; - struct list_head readers; - struct mutex mutex; - size_t w_off; - size_t head; - size_t size; - struct list_head logs; -}; - -static LIST_HEAD(log_list); - -/** - * struct logger_reader - a logging device open for reading - * @log: The associated log - * @list: The associated entry in @logger_log's list - * @r_off: The current read head offset. - * @r_all: Reader can read all entries - * @r_ver: Reader ABI version - * - * This object lives from open to release, so we don't need additional - * reference counting. The structure is protected by log->mutex. - */ -struct logger_reader { - struct logger_log *log; - struct list_head list; - size_t r_off; - bool r_all; - int r_ver; -}; - -/* logger_offset - returns index 'n' into the log via (optimized) modulus */ -static size_t logger_offset(struct logger_log *log, size_t n) -{ - return n & (log->size - 1); -} - -/* - * file_get_log - Given a file structure, return the associated log - * - * This isn't aesthetic. We have several goals: - * - * 1) Need to quickly obtain the associated log during an I/O operation - * 2) Readers need to maintain state (logger_reader) - * 3) Writers need to be very fast (open() should be a near no-op) - * - * In the reader case, we can trivially go file->logger_reader->logger_log. - * For a writer, we don't want to maintain a logger_reader, so we just go - * file->logger_log. Thus what file->private_data points at depends on whether - * or not the file was opened for reading. This function hides that dirtiness. - */ -static inline struct logger_log *file_get_log(struct file *file) -{ - if (file->f_mode & FMODE_READ) { - struct logger_reader *reader = file->private_data; - - return reader->log; - } - return file->private_data; -} - -/* - * get_entry_header - returns a pointer to the logger_entry header within - * 'log' starting at offset 'off'. A temporary logger_entry 'scratch' must - * be provided. Typically the return value will be a pointer within - * 'logger->buf'. However, a pointer to 'scratch' may be returned if - * the log entry spans the end and beginning of the circular buffer. - */ -static struct logger_entry *get_entry_header(struct logger_log *log, - size_t off, - struct logger_entry *scratch) -{ - size_t len = min(sizeof(struct logger_entry), log->size - off); - - if (len != sizeof(struct logger_entry)) { - memcpy(((void *)scratch), log->buffer + off, len); - memcpy(((void *)scratch) + len, log->buffer, - sizeof(struct logger_entry) - len); - return scratch; - } - - return (struct logger_entry *) (log->buffer + off); -} - -/* - * get_entry_msg_len - Grabs the length of the message of the entry - * starting from from 'off'. - * - * An entry length is 2 bytes (16 bits) in host endian order. - * In the log, the length does not include the size of the log entry structure. - * This function returns the size including the log entry structure. - * - * Caller needs to hold log->mutex. - */ -static __u32 get_entry_msg_len(struct logger_log *log, size_t off) -{ - struct logger_entry scratch; - struct logger_entry *entry; - - entry = get_entry_header(log, off, &scratch); - return entry->len; -} - -static size_t get_user_hdr_len(int ver) -{ - if (ver < 2) - return sizeof(struct user_logger_entry_compat); - return sizeof(struct logger_entry); -} - -static ssize_t copy_header_to_user(int ver, struct logger_entry *entry, - char __user *buf) -{ - void *hdr; - size_t hdr_len; - struct user_logger_entry_compat v1; - - if (ver < 2) { - v1.len = entry->len; - v1.__pad = 0; - v1.pid = entry->pid; - v1.tid = entry->tid; - v1.sec = entry->sec; - v1.nsec = entry->nsec; - hdr = &v1; - hdr_len = sizeof(struct user_logger_entry_compat); - } else { - hdr = entry; - hdr_len = sizeof(struct logger_entry); - } - - return copy_to_user(buf, hdr, hdr_len); -} - -/* - * do_read_log_to_user - reads exactly 'count' bytes from 'log' into the - * user-space buffer 'buf'. Returns 'count' on success. - * - * Caller must hold log->mutex. - */ -static ssize_t do_read_log_to_user(struct logger_log *log, - struct logger_reader *reader, - char __user *buf, - size_t count) -{ - struct logger_entry scratch; - struct logger_entry *entry; - size_t len; - size_t msg_start; - - /* - * First, copy the header to userspace, using the version of - * the header requested - */ - entry = get_entry_header(log, reader->r_off, &scratch); - if (copy_header_to_user(reader->r_ver, entry, buf)) - return -EFAULT; - - count -= get_user_hdr_len(reader->r_ver); - buf += get_user_hdr_len(reader->r_ver); - msg_start = logger_offset(log, - reader->r_off + sizeof(struct logger_entry)); - - /* - * We read from the msg in two disjoint operations. First, we read from - * the current msg head offset up to 'count' bytes or to the end of - * the log, whichever comes first. - */ - len = min(count, log->size - msg_start); - if (copy_to_user(buf, log->buffer + msg_start, len)) - return -EFAULT; - - /* - * Second, we read any remaining bytes, starting back at the head of - * the log. - */ - if (count != len) - if (copy_to_user(buf + len, log->buffer, count - len)) - return -EFAULT; - - reader->r_off = logger_offset(log, reader->r_off + - sizeof(struct logger_entry) + count); - - return count + get_user_hdr_len(reader->r_ver); -} - -/* - * get_next_entry_by_uid - Starting at 'off', returns an offset into - * 'log->buffer' which contains the first entry readable by 'euid' - */ -static size_t get_next_entry_by_uid(struct logger_log *log, - size_t off, kuid_t euid) -{ - while (off != log->w_off) { - struct logger_entry *entry; - struct logger_entry scratch; - size_t next_len; - - entry = get_entry_header(log, off, &scratch); - - if (uid_eq(entry->euid, euid)) - return off; - - next_len = sizeof(struct logger_entry) + entry->len; - off = logger_offset(log, off + next_len); - } - - return off; -} - -/* - * logger_read - our log's read() method - * - * Behavior: - * - * - O_NONBLOCK works - * - If there are no log entries to read, blocks until log is written to - * - Atomically reads exactly one log entry - * - * Will set errno to EINVAL if read - * buffer is insufficient to hold next entry. - */ -static ssize_t logger_read(struct file *file, char __user *buf, - size_t count, loff_t *pos) -{ - struct logger_reader *reader = file->private_data; - struct logger_log *log = reader->log; - ssize_t ret; - DEFINE_WAIT(wait); - -start: - while (1) { - mutex_lock(&log->mutex); - - prepare_to_wait(&log->wq, &wait, TASK_INTERRUPTIBLE); - - ret = (log->w_off == reader->r_off); - mutex_unlock(&log->mutex); - if (!ret) - break; - - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - break; - } - - if (signal_pending(current)) { - ret = -EINTR; - break; - } - - schedule(); - } - - finish_wait(&log->wq, &wait); - if (ret) - return ret; - - mutex_lock(&log->mutex); - - if (!reader->r_all) - reader->r_off = get_next_entry_by_uid(log, - reader->r_off, current_euid()); - - /* is there still something to read or did we race? */ - if (unlikely(log->w_off == reader->r_off)) { - mutex_unlock(&log->mutex); - goto start; - } - - /* get the size of the next entry */ - ret = get_user_hdr_len(reader->r_ver) + - get_entry_msg_len(log, reader->r_off); - if (count < ret) { - ret = -EINVAL; - goto out; - } - - /* get exactly one entry from the log */ - ret = do_read_log_to_user(log, reader, buf, ret); - -out: - mutex_unlock(&log->mutex); - - return ret; -} - -/* - * get_next_entry - return the offset of the first valid entry at least 'len' - * bytes after 'off'. - * - * Caller must hold log->mutex. - */ -static size_t get_next_entry(struct logger_log *log, size_t off, size_t len) -{ - size_t count = 0; - - do { - size_t nr = sizeof(struct logger_entry) + - get_entry_msg_len(log, off); - off = logger_offset(log, off + nr); - count += nr; - } while (count < len); - - return off; -} - -/* - * is_between - is a < c < b, accounting for wrapping of a, b, and c - * positions in the buffer - * - * That is, if ab, check for c outside (not between) a and b - * - * |------- a xxxxxxxx b --------| - * c^ - * - * |xxxxx b --------- a xxxxxxxxx| - * c^ - * or c^ - */ -static inline int is_between(size_t a, size_t b, size_t c) -{ - if (a < b) { - /* is c between a and b? */ - if (a < c && c <= b) - return 1; - } else { - /* is c outside of b through a? */ - if (c <= b || a < c) - return 1; - } - - return 0; -} - -/* - * fix_up_readers - walk the list of all readers and "fix up" any who were - * lapped by the writer; also do the same for the default "start head". - * We do this by "pulling forward" the readers and start head to the first - * entry after the new write head. - * - * The caller needs to hold log->mutex. - */ -static void fix_up_readers(struct logger_log *log, size_t len) -{ - size_t old = log->w_off; - size_t new = logger_offset(log, old + len); - struct logger_reader *reader; - - if (is_between(old, new, log->head)) - log->head = get_next_entry(log, log->head, len); - - list_for_each_entry(reader, &log->readers, list) - if (is_between(old, new, reader->r_off)) - reader->r_off = get_next_entry(log, reader->r_off, len); -} - -/* - * logger_write_iter - our write method, implementing support for write(), - * writev(), and aio_write(). Writes are our fast path, and we try to optimize - * them above all else. - */ -static ssize_t logger_write_iter(struct kiocb *iocb, struct iov_iter *from) -{ - struct logger_log *log = file_get_log(iocb->ki_filp); - struct logger_entry header; - struct timespec now; - size_t len, count, w_off; - - count = min_t(size_t, iocb->ki_nbytes, LOGGER_ENTRY_MAX_PAYLOAD); - - now = current_kernel_time(); - - header.pid = current->tgid; - header.tid = current->pid; - header.sec = now.tv_sec; - header.nsec = now.tv_nsec; - header.euid = current_euid(); - header.len = count; - header.hdr_size = sizeof(struct logger_entry); - - /* null writes succeed, return zero */ - if (unlikely(!header.len)) - return 0; - - mutex_lock(&log->mutex); - - /* - * Fix up any readers, pulling them forward to the first readable - * entry after (what will be) the new write offset. We do this now - * because if we partially fail, we can end up with clobbered log - * entries that encroach on readable buffer. - */ - fix_up_readers(log, sizeof(struct logger_entry) + header.len); - - len = min(sizeof(header), log->size - log->w_off); - memcpy(log->buffer + log->w_off, &header, len); - memcpy(log->buffer, (char *)&header + len, sizeof(header) - len); - - /* Work with a copy until we are ready to commit the whole entry */ - w_off = logger_offset(log, log->w_off + sizeof(struct logger_entry)); - - len = min(count, log->size - w_off); - - if (copy_from_iter(log->buffer + w_off, len, from) != len) { - /* - * Note that by not updating log->w_off, this abandons the - * portion of the new entry that *was* successfully - * copied, just above. This is intentional to avoid - * message corruption from missing fragments. - */ - mutex_unlock(&log->mutex); - return -EFAULT; - } - - if (copy_from_iter(log->buffer, count - len, from) != count - len) { - mutex_unlock(&log->mutex); - return -EFAULT; - } - - log->w_off = logger_offset(log, w_off + count); - mutex_unlock(&log->mutex); - - /* wake up any blocked readers */ - wake_up_interruptible(&log->wq); - - return len; -} - -static struct logger_log *get_log_from_minor(int minor) -{ - struct logger_log *log; - - list_for_each_entry(log, &log_list, logs) - if (log->misc.minor == minor) - return log; - return NULL; -} - -/* - * logger_open - the log's open() file operation - * - * Note how near a no-op this is in the write-only case. Keep it that way! - */ -static int logger_open(struct inode *inode, struct file *file) -{ - struct logger_log *log; - int ret; - - ret = nonseekable_open(inode, file); - if (ret) - return ret; - - log = get_log_from_minor(MINOR(inode->i_rdev)); - if (!log) - return -ENODEV; - - if (file->f_mode & FMODE_READ) { - struct logger_reader *reader; - - reader = kmalloc(sizeof(struct logger_reader), GFP_KERNEL); - if (!reader) - return -ENOMEM; - - reader->log = log; - reader->r_ver = 1; - reader->r_all = in_egroup_p(inode->i_gid) || - capable(CAP_SYSLOG); - - INIT_LIST_HEAD(&reader->list); - - mutex_lock(&log->mutex); - reader->r_off = log->head; - list_add_tail(&reader->list, &log->readers); - mutex_unlock(&log->mutex); - - file->private_data = reader; - } else { - file->private_data = log; - } - - return 0; -} - -/* - * logger_release - the log's release file operation - * - * Note this is a total no-op in the write-only case. Keep it that way! - */ -static int logger_release(struct inode *ignored, struct file *file) -{ - if (file->f_mode & FMODE_READ) { - struct logger_reader *reader = file->private_data; - struct logger_log *log = reader->log; - - mutex_lock(&log->mutex); - list_del(&reader->list); - mutex_unlock(&log->mutex); - - kfree(reader); - } - - return 0; -} - -/* - * logger_poll - the log's poll file operation, for poll/select/epoll - * - * Note we always return POLLOUT, because you can always write() to the log. - * Note also that, strictly speaking, a return value of POLLIN does not - * guarantee that the log is readable without blocking, as there is a small - * chance that the writer can lap the reader in the interim between poll() - * returning and the read() request. - */ -static unsigned int logger_poll(struct file *file, poll_table *wait) -{ - struct logger_reader *reader; - struct logger_log *log; - unsigned int ret = POLLOUT | POLLWRNORM; - - if (!(file->f_mode & FMODE_READ)) - return ret; - - reader = file->private_data; - log = reader->log; - - poll_wait(file, &log->wq, wait); - - mutex_lock(&log->mutex); - if (!reader->r_all) - reader->r_off = get_next_entry_by_uid(log, - reader->r_off, current_euid()); - - if (log->w_off != reader->r_off) - ret |= POLLIN | POLLRDNORM; - mutex_unlock(&log->mutex); - - return ret; -} - -static long logger_set_version(struct logger_reader *reader, void __user *arg) -{ - int version; - - if (copy_from_user(&version, arg, sizeof(int))) - return -EFAULT; - - if ((version < 1) || (version > 2)) - return -EINVAL; - - reader->r_ver = version; - return 0; -} - -static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct logger_log *log = file_get_log(file); - struct logger_reader *reader; - long ret = -EINVAL; - void __user *argp = (void __user *)arg; - - mutex_lock(&log->mutex); - - switch (cmd) { - case LOGGER_GET_LOG_BUF_SIZE: - ret = log->size; - break; - case LOGGER_GET_LOG_LEN: - if (!(file->f_mode & FMODE_READ)) { - ret = -EBADF; - break; - } - reader = file->private_data; - if (log->w_off >= reader->r_off) - ret = log->w_off - reader->r_off; - else - ret = (log->size - reader->r_off) + log->w_off; - break; - case LOGGER_GET_NEXT_ENTRY_LEN: - if (!(file->f_mode & FMODE_READ)) { - ret = -EBADF; - break; - } - reader = file->private_data; - - if (!reader->r_all) - reader->r_off = get_next_entry_by_uid(log, - reader->r_off, current_euid()); - - if (log->w_off != reader->r_off) - ret = get_user_hdr_len(reader->r_ver) + - get_entry_msg_len(log, reader->r_off); - else - ret = 0; - break; - case LOGGER_FLUSH_LOG: - if (!(file->f_mode & FMODE_WRITE)) { - ret = -EBADF; - break; - } - if (!(in_egroup_p(file_inode(file)->i_gid) || - capable(CAP_SYSLOG))) { - ret = -EPERM; - break; - } - list_for_each_entry(reader, &log->readers, list) - reader->r_off = log->w_off; - log->head = log->w_off; - ret = 0; - break; - case LOGGER_GET_VERSION: - if (!(file->f_mode & FMODE_READ)) { - ret = -EBADF; - break; - } - reader = file->private_data; - ret = reader->r_ver; - break; - case LOGGER_SET_VERSION: - if (!(file->f_mode & FMODE_READ)) { - ret = -EBADF; - break; - } - reader = file->private_data; - ret = logger_set_version(reader, argp); - break; - } - - mutex_unlock(&log->mutex); - - return ret; -} - -static const struct file_operations logger_fops = { - .owner = THIS_MODULE, - .read = logger_read, - .write_iter = logger_write_iter, - .poll = logger_poll, - .unlocked_ioctl = logger_ioctl, - .compat_ioctl = logger_ioctl, - .open = logger_open, - .release = logger_release, -}; - -/* - * Log size must must be a power of two, and greater than - * (LOGGER_ENTRY_MAX_PAYLOAD + sizeof(struct logger_entry)). - */ -static int __init create_log(char *log_name, int size) -{ - int ret = 0; - struct logger_log *log; - unsigned char *buffer; - - buffer = vmalloc(size); - if (buffer == NULL) - return -ENOMEM; - - log = kzalloc(sizeof(struct logger_log), GFP_KERNEL); - if (log == NULL) { - ret = -ENOMEM; - goto out_free_buffer; - } - log->buffer = buffer; - - log->misc.minor = MISC_DYNAMIC_MINOR; - log->misc.name = kstrdup(log_name, GFP_KERNEL); - if (log->misc.name == NULL) { - ret = -ENOMEM; - goto out_free_log; - } - - log->misc.fops = &logger_fops; - log->misc.parent = NULL; - - init_waitqueue_head(&log->wq); - INIT_LIST_HEAD(&log->readers); - mutex_init(&log->mutex); - log->w_off = 0; - log->head = 0; - log->size = size; - - INIT_LIST_HEAD(&log->logs); - list_add_tail(&log->logs, &log_list); - - /* finally, initialize the misc device for this log */ - ret = misc_register(&log->misc); - if (unlikely(ret)) { - pr_err("failed to register misc device for log '%s'!\n", - log->misc.name); - goto out_free_misc_name; - } - - pr_info("created %luK log '%s'\n", - (unsigned long)log->size >> 10, log->misc.name); - - return 0; - -out_free_misc_name: - kfree(log->misc.name); - -out_free_log: - kfree(log); - -out_free_buffer: - vfree(buffer); - return ret; -} - -static int __init logger_init(void) -{ - int ret; - - ret = create_log(LOGGER_LOG_MAIN, 256*1024); - if (unlikely(ret)) - goto out; - - ret = create_log(LOGGER_LOG_EVENTS, 256*1024); - if (unlikely(ret)) - goto out; - - ret = create_log(LOGGER_LOG_RADIO, 256*1024); - if (unlikely(ret)) - goto out; - - ret = create_log(LOGGER_LOG_SYSTEM, 256*1024); - if (unlikely(ret)) - goto out; - -out: - return ret; -} - -static void __exit logger_exit(void) -{ - struct logger_log *current_log, *next_log; - - list_for_each_entry_safe(current_log, next_log, &log_list, logs) { - /* we have to delete all the entry inside log_list */ - misc_deregister(¤t_log->misc); - vfree(current_log->buffer); - kfree(current_log->misc.name); - list_del(¤t_log->logs); - kfree(current_log); - } -} - -device_initcall(logger_init); -module_exit(logger_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Robert Love, "); -MODULE_DESCRIPTION("Android Logger"); diff --git a/drivers/staging/android/logger.h b/drivers/staging/android/logger.h deleted file mode 100644 index 70af7d8..0000000 --- a/drivers/staging/android/logger.h +++ /dev/null @@ -1,89 +0,0 @@ -/* include/linux/logger.h - * - * Copyright (C) 2007-2008 Google, Inc. - * Author: Robert Love - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef _LINUX_LOGGER_H -#define _LINUX_LOGGER_H - -#include -#include - -/** - * struct user_logger_entry_compat - defines a single entry that is given to a logger - * @len: The length of the payload - * @__pad: Two bytes of padding that appear to be required - * @pid: The generating process' process ID - * @tid: The generating process' thread ID - * @sec: The number of seconds that have elapsed since the Epoch - * @nsec: The number of nanoseconds that have elapsed since @sec - * @msg: The message that is to be logged - * - * The userspace structure for version 1 of the logger_entry ABI. - * This structure is returned to userspace unless the caller requests - * an upgrade to a newer ABI version. - */ -struct user_logger_entry_compat { - __u16 len; - __u16 __pad; - __s32 pid; - __s32 tid; - __s32 sec; - __s32 nsec; - char msg[0]; -}; - -/** - * struct logger_entry - defines a single entry that is given to a logger - * @len: The length of the payload - * @hdr_size: sizeof(struct logger_entry_v2) - * @pid: The generating process' process ID - * @tid: The generating process' thread ID - * @sec: The number of seconds that have elapsed since the Epoch - * @nsec: The number of nanoseconds that have elapsed since @sec - * @euid: Effective UID of logger - * @msg: The message that is to be logged - * - * The structure for version 2 of the logger_entry ABI. - * This structure is returned to userspace if ioctl(LOGGER_SET_VERSION) - * is called with version >= 2 - */ -struct logger_entry { - __u16 len; - __u16 hdr_size; - __s32 pid; - __s32 tid; - __s32 sec; - __s32 nsec; - kuid_t euid; - char msg[0]; -}; - -#define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */ -#define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */ -#define LOGGER_LOG_SYSTEM "log_system" /* system/framework messages */ -#define LOGGER_LOG_MAIN "log_main" /* everything else */ - -#define LOGGER_ENTRY_MAX_PAYLOAD 4076 - -#define __LOGGERIO 0xAE - -#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */ -#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */ -#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */ -#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */ -#define LOGGER_GET_VERSION _IO(__LOGGERIO, 5) /* abi version */ -#define LOGGER_SET_VERSION _IO(__LOGGERIO, 6) /* abi version */ - -#endif /* _LINUX_LOGGER_H */ -- cgit v0.10.2 From 71e365ed0ca893cae8d72cbd4b476a9589003098 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 27 Jan 2015 07:22:21 -0800 Subject: staging: Remove logger and alarm-dev from android Makefile My previous patches deleting logger and alarm-dev from staging missed the android Makefile. This patch cleans up the Makefile to remove the now non-existent files. Cc: Rom Lemarchand , Cc: Mark Salyzyn , Cc: Kees Cook , Cc: Android Kernel Team , Cc: Valentin Rothberg , Cc: Greg Hackmann , Cc: Elliott Hughes , Cc: Todd Poynor , Reported-by: Paul Bolle Signed-off-by: John Stultz Acked-by: Kees Cook Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index 479b2b8..c7b6c99 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -3,10 +3,8 @@ ccflags-y += -I$(src) # needed for trace events obj-y += ion/ obj-$(CONFIG_ASHMEM) += ashmem.o -obj-$(CONFIG_ANDROID_LOGGER) += logger.o obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o -obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o obj-$(CONFIG_SYNC) += sync.o sync_debug.o obj-$(CONFIG_SW_SYNC) += sw_sync.o -- cgit v0.10.2 From 1664f6a5b0c85a006126c398988d06a0059a50a4 Mon Sep 17 00:00:00 2001 From: Phani Movva Date: Tue, 6 Jan 2015 17:47:35 -0300 Subject: iio: adc: Cosmic Circuits 10001 ADC driver This commit adds support for Cosmic Circuits 10001 10-bit ADC device. Reviewed-by: Andrew Bresticker Signed-off-by: Phani Movva Signed-off-by: Naidu Tellapati [ezequiel: code style cleaning] Signed-off-by: Ezequiel Garcia Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 311829a..202daf8 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -135,6 +135,17 @@ config AXP288_ADC device. Depending on platform configuration, this general purpose ADC can be used for sampling sensors such as thermal resistors. +config CC10001_ADC + tristate "Cosmic Circuits 10001 ADC driver" + depends on HAS_IOMEM || HAVE_CLK || REGULATOR + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Cosmic Circuits 10001 ADC. + + This driver can also be built as a module. If so, the module will be + called cc10001_adc. + config EXYNOS_ADC tristate "Exynos ADC driver support" depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST) diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index b0f62f7..0315af6 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o obj-$(CONFIG_AD799X) += ad799x.o obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_AXP288_ADC) += axp288_adc.o +obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_MAX1027) += max1027.o diff --git a/drivers/iio/adc/cc10001_adc.c b/drivers/iio/adc/cc10001_adc.c new file mode 100644 index 0000000..51e2a83 --- /dev/null +++ b/drivers/iio/adc/cc10001_adc.c @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2014-2015 Imagination Technologies Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* Registers */ +#define CC10001_ADC_CONFIG 0x00 +#define CC10001_ADC_START_CONV BIT(4) +#define CC10001_ADC_MODE_SINGLE_CONV BIT(5) + +#define CC10001_ADC_DDATA_OUT 0x04 +#define CC10001_ADC_EOC 0x08 +#define CC10001_ADC_EOC_SET BIT(0) + +#define CC10001_ADC_CHSEL_SAMPLED 0x0c +#define CC10001_ADC_POWER_UP 0x10 +#define CC10001_ADC_POWER_UP_SET BIT(0) +#define CC10001_ADC_DEBUG 0x14 +#define CC10001_ADC_DATA_COUNT 0x20 + +#define CC10001_ADC_DATA_MASK GENMASK(9, 0) +#define CC10001_ADC_NUM_CHANNELS 8 +#define CC10001_ADC_CH_MASK GENMASK(2, 0) + +#define CC10001_INVALID_SAMPLED 0xffff +#define CC10001_MAX_POLL_COUNT 20 + +/* + * As per device specification, wait six clock cycles after power-up to + * activate START. Since adding two more clock cycles delay does not + * impact the performance too much, we are adding two additional cycles delay + * intentionally here. + */ +#define CC10001_WAIT_CYCLES 8 + +struct cc10001_adc_device { + void __iomem *reg_base; + struct clk *adc_clk; + struct regulator *reg; + u16 *buf; + + struct mutex lock; + unsigned long channel_map; + unsigned int start_delay_ns; + unsigned int eoc_delay_ns; +}; + +static inline void cc10001_adc_write_reg(struct cc10001_adc_device *adc_dev, + u32 reg, u32 val) +{ + writel(val, adc_dev->reg_base + reg); +} + +static inline u32 cc10001_adc_read_reg(struct cc10001_adc_device *adc_dev, + u32 reg) +{ + return readl(adc_dev->reg_base + reg); +} + +static void cc10001_adc_start(struct cc10001_adc_device *adc_dev, + unsigned int channel) +{ + u32 val; + + /* Channel selection and mode of operation */ + val = (channel & CC10001_ADC_CH_MASK) | CC10001_ADC_MODE_SINGLE_CONV; + cc10001_adc_write_reg(adc_dev, CC10001_ADC_CONFIG, val); + + val = cc10001_adc_read_reg(adc_dev, CC10001_ADC_CONFIG); + val = val | CC10001_ADC_START_CONV; + cc10001_adc_write_reg(adc_dev, CC10001_ADC_CONFIG, val); +} + +static u16 cc10001_adc_poll_done(struct iio_dev *indio_dev, + unsigned int channel, + unsigned int delay) +{ + struct cc10001_adc_device *adc_dev = iio_priv(indio_dev); + unsigned int poll_count = 0; + + while (!(cc10001_adc_read_reg(adc_dev, CC10001_ADC_EOC) & + CC10001_ADC_EOC_SET)) { + + ndelay(delay); + if (poll_count++ == CC10001_MAX_POLL_COUNT) + return CC10001_INVALID_SAMPLED; + } + + poll_count = 0; + while ((cc10001_adc_read_reg(adc_dev, CC10001_ADC_CHSEL_SAMPLED) & + CC10001_ADC_CH_MASK) != channel) { + + ndelay(delay); + if (poll_count++ == CC10001_MAX_POLL_COUNT) + return CC10001_INVALID_SAMPLED; + } + + /* Read the 10 bit output register */ + return cc10001_adc_read_reg(adc_dev, CC10001_ADC_DDATA_OUT) & + CC10001_ADC_DATA_MASK; +} + +static irqreturn_t cc10001_adc_trigger_h(int irq, void *p) +{ + struct cc10001_adc_device *adc_dev; + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev; + unsigned int delay_ns; + unsigned int channel; + bool sample_invalid; + u16 *data; + int i; + + indio_dev = pf->indio_dev; + adc_dev = iio_priv(indio_dev); + data = adc_dev->buf; + + mutex_lock(&adc_dev->lock); + + cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP, + CC10001_ADC_POWER_UP_SET); + + /* Wait for 8 (6+2) clock cycles before activating START */ + ndelay(adc_dev->start_delay_ns); + + /* Calculate delay step for eoc and sampled data */ + delay_ns = adc_dev->eoc_delay_ns / CC10001_MAX_POLL_COUNT; + + i = 0; + sample_invalid = false; + for_each_set_bit(channel, indio_dev->active_scan_mask, + indio_dev->masklength) { + + cc10001_adc_start(adc_dev, channel); + + data[i] = cc10001_adc_poll_done(indio_dev, channel, delay_ns); + if (data[i] == CC10001_INVALID_SAMPLED) { + dev_warn(&indio_dev->dev, + "invalid sample on channel %d\n", channel); + sample_invalid = true; + goto done; + } + i++; + } + +done: + cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP, 0); + + mutex_unlock(&adc_dev->lock); + + if (!sample_invalid) + iio_push_to_buffers_with_timestamp(indio_dev, data, + iio_get_time_ns()); + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static u16 cc10001_adc_read_raw_voltage(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + struct cc10001_adc_device *adc_dev = iio_priv(indio_dev); + unsigned int delay_ns; + u16 val; + + cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP, + CC10001_ADC_POWER_UP_SET); + + /* Wait for 8 (6+2) clock cycles before activating START */ + ndelay(adc_dev->start_delay_ns); + + /* Calculate delay step for eoc and sampled data */ + delay_ns = adc_dev->eoc_delay_ns / CC10001_MAX_POLL_COUNT; + + cc10001_adc_start(adc_dev, chan->channel); + + val = cc10001_adc_poll_done(indio_dev, chan->channel, delay_ns); + + cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP, 0); + + return val; +} + +static int cc10001_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct cc10001_adc_device *adc_dev = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (iio_buffer_enabled(indio_dev)) + return -EBUSY; + mutex_lock(&adc_dev->lock); + *val = cc10001_adc_read_raw_voltage(indio_dev, chan); + mutex_unlock(&adc_dev->lock); + + if (*val == CC10001_INVALID_SAMPLED) + return -EIO; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + ret = regulator_get_voltage(adc_dev->reg); + if (ret) + return ret; + + *val = ret / 1000; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + + default: + return -EINVAL; + } +} + +static int cc10001_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct cc10001_adc_device *adc_dev = iio_priv(indio_dev); + + kfree(adc_dev->buf); + adc_dev->buf = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); + if (!adc_dev->buf) + return -ENOMEM; + + return 0; +} + +static const struct iio_info cc10001_adc_info = { + .driver_module = THIS_MODULE, + .read_raw = &cc10001_adc_read_raw, + .update_scan_mode = &cc10001_update_scan_mode, +}; + +static int cc10001_adc_channel_init(struct iio_dev *indio_dev) +{ + struct cc10001_adc_device *adc_dev = iio_priv(indio_dev); + struct iio_chan_spec *chan_array, *timestamp; + unsigned int bit, idx = 0; + + indio_dev->num_channels = bitmap_weight(&adc_dev->channel_map, + CC10001_ADC_NUM_CHANNELS); + + chan_array = devm_kcalloc(&indio_dev->dev, indio_dev->num_channels + 1, + sizeof(struct iio_chan_spec), + GFP_KERNEL); + if (!chan_array) + return -ENOMEM; + + for_each_set_bit(bit, &adc_dev->channel_map, CC10001_ADC_NUM_CHANNELS) { + struct iio_chan_spec *chan = &chan_array[idx]; + + chan->type = IIO_VOLTAGE; + chan->indexed = 1; + chan->channel = bit; + chan->scan_index = idx; + chan->scan_type.sign = 'u'; + chan->scan_type.realbits = 10; + chan->scan_type.storagebits = 16; + chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); + chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); + idx++; + } + + timestamp = &chan_array[idx]; + timestamp->type = IIO_TIMESTAMP; + timestamp->channel = -1; + timestamp->scan_index = idx; + timestamp->scan_type.sign = 's'; + timestamp->scan_type.realbits = 64; + timestamp->scan_type.storagebits = 64; + + indio_dev->channels = chan_array; + + return 0; +} + +static int cc10001_adc_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct cc10001_adc_device *adc_dev; + unsigned long adc_clk_rate; + struct resource *res; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev)); + if (indio_dev == NULL) + return -ENOMEM; + + adc_dev = iio_priv(indio_dev); + + adc_dev->channel_map = GENMASK(CC10001_ADC_NUM_CHANNELS - 1, 0); + if (!of_property_read_u32(node, "adc-reserved-channels", &ret)) + adc_dev->channel_map &= ~ret; + + adc_dev->reg = devm_regulator_get(&pdev->dev, "vref"); + if (IS_ERR(adc_dev->reg)) + return PTR_ERR(adc_dev->reg); + + ret = regulator_enable(adc_dev->reg); + if (ret) + return ret; + + indio_dev->dev.parent = &pdev->dev; + indio_dev->name = dev_name(&pdev->dev); + indio_dev->info = &cc10001_adc_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + adc_dev->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(adc_dev->reg_base)) { + ret = PTR_ERR(adc_dev->reg_base); + goto err_disable_reg; + } + + adc_dev->adc_clk = devm_clk_get(&pdev->dev, "adc"); + if (IS_ERR(adc_dev->adc_clk)) { + dev_err(&pdev->dev, "failed to get the clock\n"); + ret = PTR_ERR(adc_dev->adc_clk); + goto err_disable_reg; + } + + ret = clk_prepare_enable(adc_dev->adc_clk); + if (ret) { + dev_err(&pdev->dev, "failed to enable the clock\n"); + goto err_disable_reg; + } + + adc_clk_rate = clk_get_rate(adc_dev->adc_clk); + if (!adc_clk_rate) { + ret = -EINVAL; + dev_err(&pdev->dev, "null clock rate!\n"); + goto err_disable_clk; + } + + adc_dev->eoc_delay_ns = NSEC_PER_SEC / adc_clk_rate; + adc_dev->start_delay_ns = adc_dev->eoc_delay_ns * CC10001_WAIT_CYCLES; + + /* Setup the ADC channels available on the device */ + ret = cc10001_adc_channel_init(indio_dev); + if (ret < 0) + goto err_disable_clk; + + mutex_init(&adc_dev->lock); + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + &cc10001_adc_trigger_h, NULL); + if (ret < 0) + goto err_disable_clk; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto err_cleanup_buffer; + + platform_set_drvdata(pdev, indio_dev); + + return 0; + +err_cleanup_buffer: + iio_triggered_buffer_cleanup(indio_dev); +err_disable_clk: + clk_disable_unprepare(adc_dev->adc_clk); +err_disable_reg: + regulator_disable(adc_dev->reg); + return ret; +} + +static int cc10001_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct cc10001_adc_device *adc_dev = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + clk_disable_unprepare(adc_dev->adc_clk); + regulator_disable(adc_dev->reg); + + return 0; +} + +static const struct of_device_id cc10001_adc_dt_ids[] = { + { .compatible = "cosmic,10001-adc", }, + { } +}; +MODULE_DEVICE_TABLE(of, cc10001_adc_dt_ids); + +static struct platform_driver cc10001_adc_driver = { + .driver = { + .name = "cc10001-adc", + .of_match_table = cc10001_adc_dt_ids, + }, + .probe = cc10001_adc_probe, + .remove = cc10001_adc_remove, +}; +module_platform_driver(cc10001_adc_driver); + +MODULE_AUTHOR("Phani Movva "); +MODULE_DESCRIPTION("Cosmic Circuits ADC driver"); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 50dd64d57eee8aed1a86e875ce77d078e44fad00 Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Wed, 28 Jan 2015 15:05:50 +0100 Subject: iio: common: ssp_sensors: Add sensorhub driver Sensorhub is MCU dedicated to collect data and manage several sensors. Sensorhub is a spi device which provides a layer for IIO devices. It provides some data parsing and common mechanism for sensorhub sensors. Adds common sensorhub library for sensorhub driver and iio drivers which uses sensorhub MCU to communicate with sensors. Signed-off-by: Karol Wrona Acked-by: Kyungmin Park Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig index 0b6e97d1..790f106 100644 --- a/drivers/iio/common/Kconfig +++ b/drivers/iio/common/Kconfig @@ -3,4 +3,5 @@ # source "drivers/iio/common/hid-sensors/Kconfig" +source "drivers/iio/common/ssp_sensors/Kconfig" source "drivers/iio/common/st_sensors/Kconfig" diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile index 3112df0..b1e4d9c 100644 --- a/drivers/iio/common/Makefile +++ b/drivers/iio/common/Makefile @@ -8,4 +8,5 @@ # When adding new entries keep the list in alphabetical order obj-y += hid-sensors/ +obj-y += ssp_sensors/ obj-y += st_sensors/ diff --git a/drivers/iio/common/ssp_sensors/Kconfig b/drivers/iio/common/ssp_sensors/Kconfig new file mode 100644 index 0000000..759b975 --- /dev/null +++ b/drivers/iio/common/ssp_sensors/Kconfig @@ -0,0 +1,16 @@ +# +# SSP sensor drivers and commons configuration +# +menu "SSP Sensor Common" + +config IIO_SSP_SENSORHUB + tristate "Samsung Sensorhub driver" + depends on SPI + select MFD_CORE + help + SSP driver for sensorhub. + If you say yes here you get ssp support for sensorhub. + To compile this driver as a module, choose M here: the + module will be called sensorhub. + +endmenu diff --git a/drivers/iio/common/ssp_sensors/Makefile b/drivers/iio/common/ssp_sensors/Makefile new file mode 100644 index 0000000..07d3d6a --- /dev/null +++ b/drivers/iio/common/ssp_sensors/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for SSP sensor drivers and commons. +# + +sensorhub-objs := ssp_dev.o ssp_spi.o +obj-$(CONFIG_IIO_SSP_SENSORHUB) += sensorhub.o diff --git a/drivers/iio/common/ssp_sensors/ssp.h b/drivers/iio/common/ssp_sensors/ssp.h new file mode 100644 index 0000000..b910e91 --- /dev/null +++ b/drivers/iio/common/ssp_sensors/ssp.h @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __SSP_SENSORHUB_H__ +#define __SSP_SENSORHUB_H__ + +#include +#include +#include +#include +#include + +#define SSP_DEVICE_ID 0x55 + +#ifdef SSP_DBG +#define ssp_dbg(format, ...) pr_info("[SSP] "format, ##__VA_ARGS__) +#else +#define ssp_dbg(format, ...) +#endif + +#define SSP_SW_RESET_TIME 3000 +/* Sensor polling in ms */ +#define SSP_DEFAULT_POLLING_DELAY 200 +#define SSP_DEFAULT_RETRIES 3 +#define SSP_DATA_PACKET_SIZE 960 +#define SSP_HEADER_BUFFER_SIZE 4 + +enum { + SSP_KERNEL_BINARY = 0, + SSP_KERNEL_CRASHED_BINARY, +}; + +enum { + SSP_INITIALIZATION_STATE = 0, + SSP_NO_SENSOR_STATE, + SSP_ADD_SENSOR_STATE, + SSP_RUNNING_SENSOR_STATE, +}; + +/* Firmware download STATE */ +enum { + SSP_FW_DL_STATE_FAIL = -1, + SSP_FW_DL_STATE_NONE = 0, + SSP_FW_DL_STATE_NEED_TO_SCHEDULE, + SSP_FW_DL_STATE_SCHEDULED, + SSP_FW_DL_STATE_DOWNLOADING, + SSP_FW_DL_STATE_SYNC, + SSP_FW_DL_STATE_DONE, +}; + +#define SSP_INVALID_REVISION 99999 +#define SSP_INVALID_REVISION2 0xffffff + +/* AP -> SSP Instruction */ +#define SSP_MSG2SSP_INST_BYPASS_SENSOR_ADD 0xa1 +#define SSP_MSG2SSP_INST_BYPASS_SENSOR_RM 0xa2 +#define SSP_MSG2SSP_INST_REMOVE_ALL 0xa3 +#define SSP_MSG2SSP_INST_CHANGE_DELAY 0xa4 +#define SSP_MSG2SSP_INST_LIBRARY_ADD 0xb1 +#define SSP_MSG2SSP_INST_LIBRARY_REMOVE 0xb2 +#define SSP_MSG2SSP_INST_LIB_NOTI 0xb4 +#define SSP_MSG2SSP_INST_LIB_DATA 0xc1 + +#define SSP_MSG2SSP_AP_MCU_SET_GYRO_CAL 0xcd +#define SSP_MSG2SSP_AP_MCU_SET_ACCEL_CAL 0xce +#define SSP_MSG2SSP_AP_STATUS_SHUTDOWN 0xd0 +#define SSP_MSG2SSP_AP_STATUS_WAKEUP 0xd1 +#define SSP_MSG2SSP_AP_STATUS_SLEEP 0xd2 +#define SSP_MSG2SSP_AP_STATUS_RESUME 0xd3 +#define SSP_MSG2SSP_AP_STATUS_SUSPEND 0xd4 +#define SSP_MSG2SSP_AP_STATUS_RESET 0xd5 +#define SSP_MSG2SSP_AP_STATUS_POW_CONNECTED 0xd6 +#define SSP_MSG2SSP_AP_STATUS_POW_DISCONNECTED 0xd7 +#define SSP_MSG2SSP_AP_TEMPHUMIDITY_CAL_DONE 0xda +#define SSP_MSG2SSP_AP_MCU_SET_DUMPMODE 0xdb +#define SSP_MSG2SSP_AP_MCU_DUMP_CHECK 0xdc +#define SSP_MSG2SSP_AP_MCU_BATCH_FLUSH 0xdd +#define SSP_MSG2SSP_AP_MCU_BATCH_COUNT 0xdf + +#define SSP_MSG2SSP_AP_WHOAMI 0x0f +#define SSP_MSG2SSP_AP_FIRMWARE_REV 0xf0 +#define SSP_MSG2SSP_AP_SENSOR_FORMATION 0xf1 +#define SSP_MSG2SSP_AP_SENSOR_PROXTHRESHOLD 0xf2 +#define SSP_MSG2SSP_AP_SENSOR_BARCODE_EMUL 0xf3 +#define SSP_MSG2SSP_AP_SENSOR_SCANNING 0xf4 +#define SSP_MSG2SSP_AP_SET_MAGNETIC_HWOFFSET 0xf5 +#define SSP_MSG2SSP_AP_GET_MAGNETIC_HWOFFSET 0xf6 +#define SSP_MSG2SSP_AP_SENSOR_GESTURE_CURRENT 0xf7 +#define SSP_MSG2SSP_AP_GET_THERM 0xf8 +#define SSP_MSG2SSP_AP_GET_BIG_DATA 0xf9 +#define SSP_MSG2SSP_AP_SET_BIG_DATA 0xfa +#define SSP_MSG2SSP_AP_START_BIG_DATA 0xfb +#define SSP_MSG2SSP_AP_SET_MAGNETIC_STATIC_MATRIX 0xfd +#define SSP_MSG2SSP_AP_SENSOR_TILT 0xea +#define SSP_MSG2SSP_AP_MCU_SET_TIME 0xfe +#define SSP_MSG2SSP_AP_MCU_GET_TIME 0xff + +#define SSP_MSG2SSP_AP_FUSEROM 0x01 + +/* voice data */ +#define SSP_TYPE_WAKE_UP_VOICE_SERVICE 0x01 +#define SSP_TYPE_WAKE_UP_VOICE_SOUND_SOURCE_AM 0x01 +#define SSP_TYPE_WAKE_UP_VOICE_SOUND_SOURCE_GRAMMER 0x02 + +/* Factory Test */ +#define SSP_ACCELEROMETER_FACTORY 0x80 +#define SSP_GYROSCOPE_FACTORY 0x81 +#define SSP_GEOMAGNETIC_FACTORY 0x82 +#define SSP_PRESSURE_FACTORY 0x85 +#define SSP_GESTURE_FACTORY 0x86 +#define SSP_TEMPHUMIDITY_CRC_FACTORY 0x88 +#define SSP_GYROSCOPE_TEMP_FACTORY 0x8a +#define SSP_GYROSCOPE_DPS_FACTORY 0x8b +#define SSP_MCU_FACTORY 0x8c +#define SSP_MCU_SLEEP_FACTORY 0x8d + +/* SSP -> AP ACK about write CMD */ +#define SSP_MSG_ACK 0x80 /* ACK from SSP to AP */ +#define SSP_MSG_NAK 0x70 /* NAK from SSP to AP */ + +struct ssp_sensorhub_info { + char *fw_name; + char *fw_crashed_name; + unsigned int fw_rev; + const u8 * const mag_table; + const unsigned int mag_length; +}; + +/* ssp_msg options bit */ +#define SSP_RW 0 +#define SSP_INDEX 3 + +#define SSP_AP2HUB_READ 0 +#define SSP_AP2HUB_WRITE 1 +#define SSP_HUB2AP_WRITE 2 +#define SSP_AP2HUB_READY 3 +#define SSP_AP2HUB_RETURN 4 + +/** + * struct ssp_data - ssp platformdata structure + * @spi: spi device + * @sensorhub_info: info about sensorhub board specific features + * @wdt_timer: watchdog timer + * @work_wdt: watchdog work + * @work_firmware: firmware upgrade work queue + * @work_refresh: refresh work queue for reset request from MCU + * @shut_down: shut down flag + * @mcu_dump_mode: mcu dump mode for debug + * @time_syncing: time syncing indication flag + * @timestamp: previous time in ns calculated for time syncing + * @check_status: status table for each sensor + * @com_fail_cnt: communication fail count + * @reset_cnt: reset count + * @timeout_cnt: timeout count + * @available_sensors: available sensors seen by sensorhub (bit array) + * @cur_firm_rev: cached current firmware revision + * @last_resume_state: last AP resume/suspend state used to handle the PM + * state of ssp + * @last_ap_state: (obsolete) sleep notification for MCU + * @sensor_enable: sensor enable mask + * @delay_buf: data acquisition intervals table + * @batch_latency_buf: yet unknown but existing in communication protocol + * @batch_opt_buf: yet unknown but existing in communication protocol + * @accel_position: yet unknown but existing in communication protocol + * @mag_position: yet unknown but existing in communication protocol + * @fw_dl_state: firmware download state + * @comm_lock: lock protecting the handshake + * @pending_lock: lock protecting pending list and completion + * @mcu_reset_gpio: mcu reset line + * @ap_mcu_gpio: ap to mcu gpio line + * @mcu_ap_gpio: mcu to ap gpio line + * @pending_list: pending list for messages queued to be sent/read + * @sensor_devs: registered IIO devices table + * @enable_refcount: enable reference count for wdt (watchdog timer) + * @header_buffer: cache aligned buffer for packet header + */ +struct ssp_data { + struct spi_device *spi; + struct ssp_sensorhub_info *sensorhub_info; + struct timer_list wdt_timer; + struct work_struct work_wdt; + struct delayed_work work_refresh; + + bool shut_down; + bool mcu_dump_mode; + bool time_syncing; + int64_t timestamp; + + int check_status[SSP_SENSOR_MAX]; + + unsigned int com_fail_cnt; + unsigned int reset_cnt; + unsigned int timeout_cnt; + + unsigned int available_sensors; + unsigned int cur_firm_rev; + + char last_resume_state; + char last_ap_state; + + unsigned int sensor_enable; + u32 delay_buf[SSP_SENSOR_MAX]; + s32 batch_latency_buf[SSP_SENSOR_MAX]; + s8 batch_opt_buf[SSP_SENSOR_MAX]; + + int accel_position; + int mag_position; + int fw_dl_state; + + struct mutex comm_lock; + struct mutex pending_lock; + + int mcu_reset_gpio; + int ap_mcu_gpio; + int mcu_ap_gpio; + + struct list_head pending_list; + + struct iio_dev *sensor_devs[SSP_SENSOR_MAX]; + atomic_t enable_refcount; + + __le16 header_buffer[SSP_HEADER_BUFFER_SIZE / sizeof(__le16)] + ____cacheline_aligned; +}; + +void ssp_clean_pending_list(struct ssp_data *data); + +int ssp_command(struct ssp_data *data, char command, int arg); + +int ssp_send_instruction(struct ssp_data *data, u8 inst, u8 sensor_type, + u8 *send_buf, u8 length); + +int ssp_irq_msg(struct ssp_data *data); + +int ssp_get_chipid(struct ssp_data *data); + +int ssp_set_magnetic_matrix(struct ssp_data *data); + +unsigned int ssp_get_sensor_scanning_info(struct ssp_data *data); + +unsigned int ssp_get_firmware_rev(struct ssp_data *data); + +int ssp_queue_ssp_refresh_task(struct ssp_data *data, unsigned int delay); + +#endif /* __SSP_SENSORHUB_H__ */ diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c new file mode 100644 index 0000000..52d7043 --- /dev/null +++ b/drivers/iio/common/ssp_sensors/ssp_dev.c @@ -0,0 +1,712 @@ +/* + * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ssp.h" + +#define SSP_WDT_TIME 10000 +#define SSP_LIMIT_RESET_CNT 20 +#define SSP_LIMIT_TIMEOUT_CNT 3 + +/* It is possible that it is max clk rate for version 1.0 of bootcode */ +#define SSP_BOOT_SPI_HZ 400000 + +/* + * These fields can look enigmatic but this structure is used mainly to flat + * some values and depends on command type. + */ +struct ssp_instruction { + __le32 a; + __le32 b; + u8 c; +} __attribute__((__packed__)); + +static const u8 ssp_magnitude_table[] = {110, 85, 171, 71, 203, 195, 0, 67, + 208, 56, 175, 244, 206, 213, 0, 92, 250, 0, 55, 48, 189, 252, 171, + 243, 13, 45, 250}; + +static const struct ssp_sensorhub_info ssp_rinato_info = { + .fw_name = "ssp_B2.fw", + .fw_crashed_name = "ssp_crashed.fw", + .fw_rev = 14052300, + .mag_table = ssp_magnitude_table, + .mag_length = ARRAY_SIZE(ssp_magnitude_table), +}; + +static const struct ssp_sensorhub_info ssp_thermostat_info = { + .fw_name = "thermostat_B2.fw", + .fw_crashed_name = "ssp_crashed.fw", + .fw_rev = 14080600, + .mag_table = ssp_magnitude_table, + .mag_length = ARRAY_SIZE(ssp_magnitude_table), +}; + +static const struct mfd_cell sensorhub_sensor_devs[] = { + { + .name = "ssp-accelerometer", + }, + { + .name = "ssp-gyroscope", + }, +}; + +static void ssp_toggle_mcu_reset_gpio(struct ssp_data *data) +{ + gpio_set_value(data->mcu_reset_gpio, 0); + usleep_range(1000, 1200); + gpio_set_value(data->mcu_reset_gpio, 1); + msleep(50); +} + +static void ssp_sync_available_sensors(struct ssp_data *data) +{ + int i, ret; + + for (i = 0; i < SSP_SENSOR_MAX; ++i) { + if (data->available_sensors & BIT(i)) { + ret = ssp_enable_sensor(data, i, data->delay_buf[i]); + if (ret < 0) { + dev_err(&data->spi->dev, + "Sync sensor nr: %d fail\n", i); + continue; + } + } + } + + ret = ssp_command(data, SSP_MSG2SSP_AP_MCU_SET_DUMPMODE, + data->mcu_dump_mode); + if (ret < 0) + dev_err(&data->spi->dev, + "SSP_MSG2SSP_AP_MCU_SET_DUMPMODE failed\n"); +} + +static void ssp_enable_mcu(struct ssp_data *data, bool enable) +{ + dev_info(&data->spi->dev, "current shutdown = %d, old = %d\n", enable, + data->shut_down); + + if (enable && data->shut_down) { + data->shut_down = false; + enable_irq(data->spi->irq); + enable_irq_wake(data->spi->irq); + } else if (!enable && !data->shut_down) { + data->shut_down = true; + disable_irq(data->spi->irq); + disable_irq_wake(data->spi->irq); + } else { + dev_warn(&data->spi->dev, "current shutdown = %d, old = %d\n", + enable, data->shut_down); + } +} + +/* + * This function is the first one which communicates with the mcu so it is + * possible that the first attempt will fail + */ +static int ssp_check_fwbl(struct ssp_data *data) +{ + int retries = 0; + + while (retries++ < 5) { + data->cur_firm_rev = ssp_get_firmware_rev(data); + if (data->cur_firm_rev == SSP_INVALID_REVISION || + data->cur_firm_rev == SSP_INVALID_REVISION2) { + dev_warn(&data->spi->dev, + "Invalid revision, trying %d time\n", retries); + } else { + break; + } + } + + if (data->cur_firm_rev == SSP_INVALID_REVISION || + data->cur_firm_rev == SSP_INVALID_REVISION2) { + dev_err(&data->spi->dev, "SSP_INVALID_REVISION\n"); + return SSP_FW_DL_STATE_NEED_TO_SCHEDULE; + } + + dev_info(&data->spi->dev, + "MCU Firm Rev : Old = %8u, New = %8u\n", + data->cur_firm_rev, + data->sensorhub_info->fw_rev); + + if (data->cur_firm_rev != data->sensorhub_info->fw_rev) + return SSP_FW_DL_STATE_NEED_TO_SCHEDULE; + + return SSP_FW_DL_STATE_NONE; +} + +static void ssp_reset_mcu(struct ssp_data *data) +{ + ssp_enable_mcu(data, false); + ssp_clean_pending_list(data); + ssp_toggle_mcu_reset_gpio(data); + ssp_enable_mcu(data, true); +} + +static void ssp_wdt_work_func(struct work_struct *work) +{ + struct ssp_data *data = container_of(work, struct ssp_data, work_wdt); + + dev_err(&data->spi->dev, "%s - Sensor state: 0x%x, RC: %u, CC: %u\n", + __func__, data->available_sensors, data->reset_cnt, + data->com_fail_cnt); + + ssp_reset_mcu(data); + data->com_fail_cnt = 0; + data->timeout_cnt = 0; +} + +static void ssp_wdt_timer_func(unsigned long ptr) +{ + struct ssp_data *data = (struct ssp_data *)ptr; + + switch (data->fw_dl_state) { + case SSP_FW_DL_STATE_FAIL: + case SSP_FW_DL_STATE_DOWNLOADING: + case SSP_FW_DL_STATE_SYNC: + goto _mod; + } + + if (data->timeout_cnt > SSP_LIMIT_TIMEOUT_CNT || + data->com_fail_cnt > SSP_LIMIT_RESET_CNT) + queue_work(system_power_efficient_wq, &data->work_wdt); +_mod: + mod_timer(&data->wdt_timer, jiffies + msecs_to_jiffies(SSP_WDT_TIME)); +} + +static void ssp_enable_wdt_timer(struct ssp_data *data) +{ + mod_timer(&data->wdt_timer, jiffies + msecs_to_jiffies(SSP_WDT_TIME)); +} + +static void ssp_disable_wdt_timer(struct ssp_data *data) +{ + del_timer_sync(&data->wdt_timer); + cancel_work_sync(&data->work_wdt); +} + +/** + * ssp_get_sensor_delay() - gets sensor data acquisition period + * @data: sensorhub structure + * @type: SSP sensor type + * + * Returns acquisition period in ms + */ +u32 ssp_get_sensor_delay(struct ssp_data *data, enum ssp_sensor_type type) +{ + return data->delay_buf[type]; +} +EXPORT_SYMBOL(ssp_get_sensor_delay); + +/** + * ssp_enable_sensor() - enables data acquisition for sensor + * @data: sensorhub structure + * @type: SSP sensor type + * @delay: delay in ms + * + * Returns 0 or negative value in case of error + */ +int ssp_enable_sensor(struct ssp_data *data, enum ssp_sensor_type type, + u32 delay) +{ + int ret; + struct ssp_instruction to_send; + + to_send.a = cpu_to_le32(delay); + to_send.b = cpu_to_le32(data->batch_latency_buf[type]); + to_send.c = data->batch_opt_buf[type]; + + switch (data->check_status[type]) { + case SSP_INITIALIZATION_STATE: + /* do calibration step, now just enable */ + case SSP_ADD_SENSOR_STATE: + ret = ssp_send_instruction(data, + SSP_MSG2SSP_INST_BYPASS_SENSOR_ADD, + type, + (u8 *)&to_send, sizeof(to_send)); + if (ret < 0) { + dev_err(&data->spi->dev, "Enabling sensor failed\n"); + data->check_status[type] = SSP_NO_SENSOR_STATE; + goto derror; + } + + data->sensor_enable |= BIT(type); + data->check_status[type] = SSP_RUNNING_SENSOR_STATE; + break; + case SSP_RUNNING_SENSOR_STATE: + ret = ssp_send_instruction(data, + SSP_MSG2SSP_INST_CHANGE_DELAY, type, + (u8 *)&to_send, sizeof(to_send)); + if (ret < 0) { + dev_err(&data->spi->dev, + "Changing sensor delay failed\n"); + goto derror; + } + break; + default: + data->check_status[type] = SSP_ADD_SENSOR_STATE; + break; + } + + data->delay_buf[type] = delay; + + if (atomic_inc_return(&data->enable_refcount) == 1) + ssp_enable_wdt_timer(data); + + return 0; + +derror: + return ret; +} +EXPORT_SYMBOL(ssp_enable_sensor); + +/** + * ssp_change_delay() - changes data acquisition for sensor + * @data: sensorhub structure + * @type: SSP sensor type + * @delay: delay in ms + * + * Returns 0 or negative value in case of error + */ +int ssp_change_delay(struct ssp_data *data, enum ssp_sensor_type type, + u32 delay) +{ + int ret; + struct ssp_instruction to_send; + + to_send.a = cpu_to_le32(delay); + to_send.b = cpu_to_le32(data->batch_latency_buf[type]); + to_send.c = data->batch_opt_buf[type]; + + ret = ssp_send_instruction(data, SSP_MSG2SSP_INST_CHANGE_DELAY, type, + (u8 *)&to_send, sizeof(to_send)); + if (ret < 0) { + dev_err(&data->spi->dev, "Changing sensor delay failed\n"); + return ret; + } + + data->delay_buf[type] = delay; + + return 0; +} +EXPORT_SYMBOL(ssp_change_delay); + +/** + * ssp_disable_sensor() - disables sensor + * + * @data: sensorhub structure + * @type: SSP sensor type + * + * Returns 0 or negative value in case of error + */ +int ssp_disable_sensor(struct ssp_data *data, enum ssp_sensor_type type) +{ + int ret; + __le32 command; + + if (data->sensor_enable & BIT(type)) { + command = cpu_to_le32(data->delay_buf[type]); + + ret = ssp_send_instruction(data, + SSP_MSG2SSP_INST_BYPASS_SENSOR_RM, + type, (u8 *)&command, + sizeof(command)); + if (ret < 0) { + dev_err(&data->spi->dev, "Remove sensor fail\n"); + return ret; + } + + data->sensor_enable &= ~BIT(type); + } + + data->check_status[type] = SSP_ADD_SENSOR_STATE; + + if (atomic_dec_and_test(&data->enable_refcount)) + ssp_disable_wdt_timer(data); + + return 0; +} +EXPORT_SYMBOL(ssp_disable_sensor); + +static irqreturn_t ssp_irq_thread_fn(int irq, void *dev_id) +{ + struct ssp_data *data = dev_id; + + /* + * This wrapper is done to preserve error path for ssp_irq_msg, also + * it is defined in different file. + */ + ssp_irq_msg(data); + + return IRQ_HANDLED; +} + +static int ssp_initialize_mcu(struct ssp_data *data) +{ + int ret; + + ssp_clean_pending_list(data); + + ret = ssp_get_chipid(data); + if (ret != SSP_DEVICE_ID) { + dev_err(&data->spi->dev, "%s - MCU %s ret = %d\n", __func__, + ret < 0 ? "is not working" : "identification failed", + ret); + return ret < 0 ? ret : -ENODEV; + } + + dev_info(&data->spi->dev, "MCU device ID = %d\n", ret); + + /* + * needs clarification, for now do not want to export all transfer + * methods to sensors' drivers + */ + ret = ssp_set_magnetic_matrix(data); + if (ret < 0) { + dev_err(&data->spi->dev, + "%s - ssp_set_magnetic_matrix failed\n", __func__); + return ret; + } + + data->available_sensors = ssp_get_sensor_scanning_info(data); + if (data->available_sensors == 0) { + dev_err(&data->spi->dev, + "%s - ssp_get_sensor_scanning_info failed\n", __func__); + return -EIO; + } + + data->cur_firm_rev = ssp_get_firmware_rev(data); + dev_info(&data->spi->dev, "MCU Firm Rev : New = %8u\n", + data->cur_firm_rev); + + return ssp_command(data, SSP_MSG2SSP_AP_MCU_DUMP_CHECK, 0); +} + +/* + * sensorhub can request its reinitialization as some brutal and rare error + * handling. It can be requested from the MCU. + */ +static void ssp_refresh_task(struct work_struct *work) +{ + struct ssp_data *data = container_of((struct delayed_work *)work, + struct ssp_data, work_refresh); + + dev_info(&data->spi->dev, "refreshing\n"); + + data->reset_cnt++; + + if (ssp_initialize_mcu(data) >= 0) { + ssp_sync_available_sensors(data); + if (data->last_ap_state != 0) + ssp_command(data, data->last_ap_state, 0); + + if (data->last_resume_state != 0) + ssp_command(data, data->last_resume_state, 0); + + data->timeout_cnt = 0; + data->com_fail_cnt = 0; + } +} + +int ssp_queue_ssp_refresh_task(struct ssp_data *data, unsigned int delay) +{ + cancel_delayed_work_sync(&data->work_refresh); + + return queue_delayed_work(system_power_efficient_wq, + &data->work_refresh, + msecs_to_jiffies(delay)); +} + +#ifdef CONFIG_OF +static struct of_device_id ssp_of_match[] = { + { + .compatible = "samsung,sensorhub-rinato", + .data = &ssp_rinato_info, + }, { + .compatible = "samsung,sensorhub-thermostat", + .data = &ssp_thermostat_info, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, ssp_of_match); + +static struct ssp_data *ssp_parse_dt(struct device *dev) +{ + int ret; + struct ssp_data *data; + struct device_node *node = dev->of_node; + const struct of_device_id *match; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return NULL; + + data->mcu_ap_gpio = of_get_named_gpio(node, "mcu-ap-gpios", 0); + if (data->mcu_ap_gpio < 0) + goto err_free_pd; + + data->ap_mcu_gpio = of_get_named_gpio(node, "ap-mcu-gpios", 0); + if (data->ap_mcu_gpio < 0) + goto err_free_pd; + + data->mcu_reset_gpio = of_get_named_gpio(node, "mcu-reset-gpios", 0); + if (data->mcu_reset_gpio < 0) + goto err_free_pd; + + ret = devm_gpio_request_one(dev, data->ap_mcu_gpio, GPIOF_OUT_INIT_HIGH, + "ap-mcu-gpios"); + if (ret) + goto err_free_pd; + + ret = devm_gpio_request_one(dev, data->mcu_reset_gpio, + GPIOF_OUT_INIT_HIGH, "mcu-reset-gpios"); + if (ret) + goto err_ap_mcu; + + match = of_match_node(ssp_of_match, node); + if (!match) + goto err_mcu_reset_gpio; + + data->sensorhub_info = (struct ssp_sensorhub_info *)match->data; + + dev_set_drvdata(dev, data); + + return data; + +err_mcu_reset_gpio: + devm_gpio_free(dev, data->mcu_reset_gpio); +err_ap_mcu: + devm_gpio_free(dev, data->ap_mcu_gpio); +err_free_pd: + devm_kfree(dev, data); + return NULL; +} +#else +static struct ssp_data *ssp_parse_dt(struct device *pdev) +{ + return NULL; +} +#endif + +/** + * ssp_register_consumer() - registers iio consumer in ssp framework + * + * @indio_dev: consumer iio device + * @type: ssp sensor type + */ +void ssp_register_consumer(struct iio_dev *indio_dev, enum ssp_sensor_type type) +{ + struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent); + + data->sensor_devs[type] = indio_dev; +} +EXPORT_SYMBOL(ssp_register_consumer); + +static int ssp_probe(struct spi_device *spi) +{ + int ret, i; + struct ssp_data *data; + + data = ssp_parse_dt(&spi->dev); + if (!data) { + dev_err(&spi->dev, "Failed to find platform data\n"); + return -ENODEV; + } + + ret = mfd_add_devices(&spi->dev, -1, sensorhub_sensor_devs, + ARRAY_SIZE(sensorhub_sensor_devs), NULL, 0, NULL); + if (ret < 0) { + dev_err(&spi->dev, "mfd add devices fail\n"); + return ret; + } + + spi->mode = SPI_MODE_1; + ret = spi_setup(spi); + if (ret < 0) { + dev_err(&spi->dev, "Failed to setup spi\n"); + return ret; + } + + data->fw_dl_state = SSP_FW_DL_STATE_NONE; + data->spi = spi; + spi_set_drvdata(spi, data); + + mutex_init(&data->comm_lock); + + for (i = 0; i < SSP_SENSOR_MAX; ++i) { + data->delay_buf[i] = SSP_DEFAULT_POLLING_DELAY; + data->batch_latency_buf[i] = 0; + data->batch_opt_buf[i] = 0; + data->check_status[i] = SSP_INITIALIZATION_STATE; + } + + data->delay_buf[SSP_BIO_HRM_LIB] = 100; + + data->time_syncing = true; + + mutex_init(&data->pending_lock); + INIT_LIST_HEAD(&data->pending_list); + + atomic_set(&data->enable_refcount, 0); + + INIT_WORK(&data->work_wdt, ssp_wdt_work_func); + INIT_DELAYED_WORK(&data->work_refresh, ssp_refresh_task); + + setup_timer(&data->wdt_timer, ssp_wdt_timer_func, (unsigned long)data); + + ret = request_threaded_irq(data->spi->irq, NULL, + ssp_irq_thread_fn, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "SSP_Int", data); + if (ret < 0) { + dev_err(&spi->dev, "Irq request fail\n"); + goto err_setup_irq; + } + + /* Let's start with enabled one so irq balance could be ok */ + data->shut_down = false; + + /* just to avoid unbalanced irq set wake up */ + enable_irq_wake(data->spi->irq); + + data->fw_dl_state = ssp_check_fwbl(data); + if (data->fw_dl_state == SSP_FW_DL_STATE_NONE) { + ret = ssp_initialize_mcu(data); + if (ret < 0) { + dev_err(&spi->dev, "Initialize_mcu failed\n"); + goto err_read_reg; + } + } else { + dev_err(&spi->dev, "Firmware version not supported\n"); + ret = -EPERM; + goto err_read_reg; + } + + return 0; + +err_read_reg: + free_irq(data->spi->irq, data); +err_setup_irq: + mutex_destroy(&data->pending_lock); + mutex_destroy(&data->comm_lock); + + dev_err(&spi->dev, "Probe failed!\n"); + + return ret; +} + +static int ssp_remove(struct spi_device *spi) +{ + struct ssp_data *data = spi_get_drvdata(spi); + + if (ssp_command(data, SSP_MSG2SSP_AP_STATUS_SHUTDOWN, 0) < 0) + dev_err(&data->spi->dev, + "SSP_MSG2SSP_AP_STATUS_SHUTDOWN failed\n"); + + ssp_enable_mcu(data, false); + ssp_disable_wdt_timer(data); + + ssp_clean_pending_list(data); + + free_irq(data->spi->irq, data); + + del_timer_sync(&data->wdt_timer); + cancel_work_sync(&data->work_wdt); + + mutex_destroy(&data->comm_lock); + mutex_destroy(&data->pending_lock); + + mfd_remove_devices(&spi->dev); + + return 0; +} + +static int ssp_suspend(struct device *dev) +{ + int ret; + struct ssp_data *data = spi_get_drvdata(to_spi_device(dev)); + + data->last_resume_state = SSP_MSG2SSP_AP_STATUS_SUSPEND; + + if (atomic_read(&data->enable_refcount) > 0) + ssp_disable_wdt_timer(data); + + ret = ssp_command(data, SSP_MSG2SSP_AP_STATUS_SUSPEND, 0); + if (ret < 0) { + dev_err(&data->spi->dev, + "%s SSP_MSG2SSP_AP_STATUS_SUSPEND failed\n", __func__); + + ssp_enable_wdt_timer(data); + return ret; + } + + data->time_syncing = false; + disable_irq(data->spi->irq); + + return 0; +} + +static int ssp_resume(struct device *dev) +{ + int ret; + struct ssp_data *data = spi_get_drvdata(to_spi_device(dev)); + + enable_irq(data->spi->irq); + + if (atomic_read(&data->enable_refcount) > 0) + ssp_enable_wdt_timer(data); + + ret = ssp_command(data, SSP_MSG2SSP_AP_STATUS_RESUME, 0); + if (ret < 0) { + dev_err(&data->spi->dev, + "%s SSP_MSG2SSP_AP_STATUS_RESUME failed\n", __func__); + ssp_disable_wdt_timer(data); + return ret; + } + + /* timesyncing is set by MCU */ + data->last_resume_state = SSP_MSG2SSP_AP_STATUS_RESUME; + + return 0; +} + +static const struct dev_pm_ops ssp_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(ssp_suspend, ssp_resume) +}; + +static struct spi_driver ssp_driver = { + .probe = ssp_probe, + .remove = ssp_remove, + .driver = { + .pm = &ssp_pm_ops, + .bus = &spi_bus_type, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ssp_of_match), + .name = "sensorhub" + }, +}; + +module_spi_driver(ssp_driver); + +MODULE_DESCRIPTION("ssp sensorhub driver"); +MODULE_AUTHOR("Samsung Electronics"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/common/ssp_sensors/ssp_spi.c b/drivers/iio/common/ssp_sensors/ssp_spi.c new file mode 100644 index 0000000..704284a --- /dev/null +++ b/drivers/iio/common/ssp_sensors/ssp_spi.c @@ -0,0 +1,608 @@ +/* + * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "ssp.h" + +#define SSP_DEV (&data->spi->dev) +#define SSP_GET_MESSAGE_TYPE(data) (data & (3 << SSP_RW)) + +/* + * SSP -> AP Instruction + * They tell what packet type can be expected. In the future there will + * be less of them. BYPASS means common sensor packets with accel, gyro, + * hrm etc. data. LIBRARY and META are mock-up's for now. + */ +#define SSP_MSG2AP_INST_BYPASS_DATA 0x37 +#define SSP_MSG2AP_INST_LIBRARY_DATA 0x01 +#define SSP_MSG2AP_INST_DEBUG_DATA 0x03 +#define SSP_MSG2AP_INST_BIG_DATA 0x04 +#define SSP_MSG2AP_INST_META_DATA 0x05 +#define SSP_MSG2AP_INST_TIME_SYNC 0x06 +#define SSP_MSG2AP_INST_RESET 0x07 + +#define SSP_UNIMPLEMENTED -1 + +struct ssp_msg_header { + u8 cmd; + __le16 length; + __le16 options; + __le32 data; +} __attribute__((__packed__)); + +struct ssp_msg { + u16 length; + u16 options; + struct list_head list; + struct completion *done; + struct ssp_msg_header *h; + char *buffer; +}; + +static const int ssp_offset_map[SSP_SENSOR_MAX] = { + [SSP_ACCELEROMETER_SENSOR] = SSP_ACCELEROMETER_SIZE + + SSP_TIME_SIZE, + [SSP_GYROSCOPE_SENSOR] = SSP_GYROSCOPE_SIZE + + SSP_TIME_SIZE, + [SSP_GEOMAGNETIC_UNCALIB_SENSOR] = SSP_UNIMPLEMENTED, + [SSP_GEOMAGNETIC_RAW] = SSP_UNIMPLEMENTED, + [SSP_GEOMAGNETIC_SENSOR] = SSP_UNIMPLEMENTED, + [SSP_PRESSURE_SENSOR] = SSP_UNIMPLEMENTED, + [SSP_GESTURE_SENSOR] = SSP_UNIMPLEMENTED, + [SSP_PROXIMITY_SENSOR] = SSP_UNIMPLEMENTED, + [SSP_TEMPERATURE_HUMIDITY_SENSOR] = SSP_UNIMPLEMENTED, + [SSP_LIGHT_SENSOR] = SSP_UNIMPLEMENTED, + [SSP_PROXIMITY_RAW] = SSP_UNIMPLEMENTED, + [SSP_ORIENTATION_SENSOR] = SSP_UNIMPLEMENTED, + [SSP_STEP_DETECTOR] = SSP_UNIMPLEMENTED, + [SSP_SIG_MOTION_SENSOR] = SSP_UNIMPLEMENTED, + [SSP_GYRO_UNCALIB_SENSOR] = SSP_UNIMPLEMENTED, + [SSP_GAME_ROTATION_VECTOR] = SSP_UNIMPLEMENTED, + [SSP_ROTATION_VECTOR] = SSP_UNIMPLEMENTED, + [SSP_STEP_COUNTER] = SSP_UNIMPLEMENTED, + [SSP_BIO_HRM_RAW] = SSP_BIO_HRM_RAW_SIZE + + SSP_TIME_SIZE, + [SSP_BIO_HRM_RAW_FAC] = SSP_BIO_HRM_RAW_FAC_SIZE + + SSP_TIME_SIZE, + [SSP_BIO_HRM_LIB] = SSP_BIO_HRM_LIB_SIZE + + SSP_TIME_SIZE, +}; + +#define SSP_HEADER_SIZE (sizeof(struct ssp_msg_header)) +#define SSP_HEADER_SIZE_ALIGNED (ALIGN(SSP_HEADER_SIZE, 4)) + +static struct ssp_msg *ssp_create_msg(u8 cmd, u16 len, u16 opt, u32 data) +{ + struct ssp_msg_header h; + struct ssp_msg *msg; + + msg = kzalloc(sizeof(*msg), GFP_KERNEL); + if (!msg) + return NULL; + + h.cmd = cmd; + h.length = cpu_to_le16(len); + h.options = cpu_to_le16(opt); + h.data = cpu_to_le32(data); + + msg->buffer = kzalloc(SSP_HEADER_SIZE_ALIGNED + len, + GFP_KERNEL | GFP_DMA); + if (!msg->buffer) { + kfree(msg); + return NULL; + } + + msg->length = len; + msg->options = opt; + + memcpy(msg->buffer, &h, SSP_HEADER_SIZE); + + return msg; +} + +/* + * It is a bit heavy to do it this way but often the function is used to compose + * the message from smaller chunks which are placed on the stack. Often the + * chunks are small so memcpy should be optimalized. + */ +static inline void ssp_fill_buffer(struct ssp_msg *m, unsigned int offset, + const void *src, unsigned int len) +{ + memcpy(&m->buffer[SSP_HEADER_SIZE_ALIGNED + offset], src, len); +} + +static inline void ssp_get_buffer(struct ssp_msg *m, unsigned int offset, + void *dest, unsigned int len) +{ + memcpy(dest, &m->buffer[SSP_HEADER_SIZE_ALIGNED + offset], len); +} + +#define SSP_GET_BUFFER_AT_INDEX(m, index) \ + (m->buffer[SSP_HEADER_SIZE_ALIGNED + index]) +#define SSP_SET_BUFFER_AT_INDEX(m, index, val) \ + (m->buffer[SSP_HEADER_SIZE_ALIGNED + index] = val) + +static void ssp_clean_msg(struct ssp_msg *m) +{ + kfree(m->buffer); + kfree(m); +} + +static int ssp_print_mcu_debug(char *data_frame, int *data_index, + int received_len) +{ + int length = data_frame[(*data_index)++]; + + if (length > received_len - *data_index || length <= 0) { + ssp_dbg("[SSP]: MSG From MCU-invalid debug length(%d/%d)\n", + length, received_len); + return length ? length : -EPROTO; + } + + ssp_dbg("[SSP]: MSG From MCU - %s\n", &data_frame[*data_index]); + + *data_index += length; + + return 0; +} + +/* + * It was designed that way - additional lines to some kind of handshake, + * please do not ask why - only the firmware guy can know it. + */ +static int ssp_check_lines(struct ssp_data *data, bool state) +{ + int delay_cnt = 0; + + gpio_set_value_cansleep(data->ap_mcu_gpio, state); + + while (gpio_get_value_cansleep(data->mcu_ap_gpio) != state) { + usleep_range(3000, 3500); + + if (data->shut_down || delay_cnt++ > 500) { + dev_err(SSP_DEV, "%s:timeout, hw ack wait fail %d\n", + __func__, state); + + if (!state) + gpio_set_value_cansleep(data->ap_mcu_gpio, 1); + + return -ETIMEDOUT; + } + } + + return 0; +} + +static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg, + struct completion *done, int timeout) +{ + int status; + /* + * check if this is a short one way message or the whole transfer has + * second part after an interrupt + */ + const bool use_no_irq = msg->length == 0; + + if (data->shut_down) + return -EPERM; + + msg->done = done; + + mutex_lock(&data->comm_lock); + + status = ssp_check_lines(data, false); + if (status < 0) + goto _error_locked; + + status = spi_write(data->spi, msg->buffer, SSP_HEADER_SIZE); + if (status < 0) { + gpio_set_value_cansleep(data->ap_mcu_gpio, 1); + dev_err(SSP_DEV, "%s spi_write fail\n", __func__); + goto _error_locked; + } + + if (!use_no_irq) { + mutex_lock(&data->pending_lock); + list_add_tail(&msg->list, &data->pending_list); + mutex_unlock(&data->pending_lock); + } + + status = ssp_check_lines(data, true); + if (status < 0) { + if (!use_no_irq) { + mutex_lock(&data->pending_lock); + list_del(&msg->list); + mutex_unlock(&data->pending_lock); + } + goto _error_locked; + } + + mutex_unlock(&data->comm_lock); + + if (!use_no_irq && done) + if (wait_for_completion_timeout(done, + msecs_to_jiffies(timeout)) == + 0) { + mutex_lock(&data->pending_lock); + list_del(&msg->list); + mutex_unlock(&data->pending_lock); + + data->timeout_cnt++; + return -ETIMEDOUT; + } + + return 0; + +_error_locked: + mutex_unlock(&data->comm_lock); + data->timeout_cnt++; + return status; +} + +static inline int ssp_spi_sync_command(struct ssp_data *data, + struct ssp_msg *msg) +{ + return ssp_do_transfer(data, msg, NULL, 0); +} + +static int ssp_spi_sync(struct ssp_data *data, struct ssp_msg *msg, + int timeout) +{ + DECLARE_COMPLETION_ONSTACK(done); + + if (WARN_ON(!msg->length)) + return -EPERM; + + return ssp_do_transfer(data, msg, &done, timeout); +} + +static int ssp_handle_big_data(struct ssp_data *data, char *dataframe, int *idx) +{ + /* mock-up, it will be changed with adding another sensor types */ + *idx += 8; + return 0; +} + +static int ssp_parse_dataframe(struct ssp_data *data, char *dataframe, int len) +{ + int idx, sd; + struct timespec ts; + struct ssp_sensor_data *spd; + struct iio_dev **indio_devs = data->sensor_devs; + + getnstimeofday(&ts); + + for (idx = 0; idx < len;) { + switch (dataframe[idx++]) { + case SSP_MSG2AP_INST_BYPASS_DATA: + sd = dataframe[idx++]; + if (sd < 0 || sd >= SSP_SENSOR_MAX) { + dev_err(SSP_DEV, + "Mcu data frame1 error %d\n", sd); + return -EPROTO; + } + + if (indio_devs[sd]) { + spd = iio_priv(indio_devs[sd]); + if (spd->process_data) + spd->process_data(indio_devs[sd], + &dataframe[idx], + data->timestamp); + } else { + dev_err(SSP_DEV, "no client for frame\n"); + } + + idx += ssp_offset_map[sd]; + break; + case SSP_MSG2AP_INST_DEBUG_DATA: + sd = ssp_print_mcu_debug(dataframe, &idx, len); + if (sd) { + dev_err(SSP_DEV, + "Mcu data frame3 error %d\n", sd); + return sd; + } + break; + case SSP_MSG2AP_INST_LIBRARY_DATA: + idx += len; + break; + case SSP_MSG2AP_INST_BIG_DATA: + ssp_handle_big_data(data, dataframe, &idx); + break; + case SSP_MSG2AP_INST_TIME_SYNC: + data->time_syncing = true; + break; + case SSP_MSG2AP_INST_RESET: + ssp_queue_ssp_refresh_task(data, 0); + break; + } + } + + if (data->time_syncing) + data->timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec; + + return 0; +} + +/* threaded irq */ +int ssp_irq_msg(struct ssp_data *data) +{ + bool found = false; + char *buffer; + u8 msg_type; + int ret; + u16 length, msg_options; + struct ssp_msg *msg, *n; + + ret = spi_read(data->spi, data->header_buffer, SSP_HEADER_BUFFER_SIZE); + if (ret < 0) { + dev_err(SSP_DEV, "header read fail\n"); + return ret; + } + + length = le16_to_cpu(data->header_buffer[1]); + msg_options = le16_to_cpu(data->header_buffer[0]); + + if (length == 0) { + dev_err(SSP_DEV, "length received from mcu is 0\n"); + return -EINVAL; + } + + msg_type = SSP_GET_MESSAGE_TYPE(msg_options); + + switch (msg_type) { + case SSP_AP2HUB_READ: + case SSP_AP2HUB_WRITE: + /* + * this is a small list, a few elements - the packets can be + * received with no order + */ + mutex_lock(&data->pending_lock); + list_for_each_entry_safe(msg, n, &data->pending_list, list) { + if (msg->options == msg_options) { + list_del(&msg->list); + found = true; + break; + } + } + + if (!found) { + /* + * here can be implemented dead messages handling + * but the slave should not send such ones - it is to + * check but let's handle this + */ + buffer = kmalloc(length, GFP_KERNEL | GFP_DMA); + if (!buffer) { + ret = -ENOMEM; + goto _unlock; + } + + /* got dead packet so it is always an error */ + ret = spi_read(data->spi, buffer, length); + if (ret >= 0) + ret = -EPROTO; + + kfree(buffer); + + dev_err(SSP_DEV, "No match error %x\n", + msg_options); + + goto _unlock; + } + + if (msg_type == SSP_AP2HUB_READ) + ret = spi_read(data->spi, + &msg->buffer[SSP_HEADER_SIZE_ALIGNED], + msg->length); + + if (msg_type == SSP_AP2HUB_WRITE) { + ret = spi_write(data->spi, + &msg->buffer[SSP_HEADER_SIZE_ALIGNED], + msg->length); + if (msg_options & SSP_AP2HUB_RETURN) { + msg->options = + SSP_AP2HUB_READ | SSP_AP2HUB_RETURN; + msg->length = 1; + + list_add_tail(&msg->list, &data->pending_list); + goto _unlock; + } + } + + if (msg->done) + if (!completion_done(msg->done)) + complete(msg->done); +_unlock: + mutex_unlock(&data->pending_lock); + break; + case SSP_HUB2AP_WRITE: + buffer = kzalloc(length, GFP_KERNEL | GFP_DMA); + if (!buffer) + return -ENOMEM; + + ret = spi_read(data->spi, buffer, length); + if (ret < 0) { + dev_err(SSP_DEV, "spi read fail\n"); + kfree(buffer); + break; + } + + ret = ssp_parse_dataframe(data, buffer, length); + + kfree(buffer); + break; + + default: + dev_err(SSP_DEV, "unknown msg type\n"); + return -EPROTO; + } + + return ret; +} + +void ssp_clean_pending_list(struct ssp_data *data) +{ + struct ssp_msg *msg, *n; + + mutex_lock(&data->pending_lock); + list_for_each_entry_safe(msg, n, &data->pending_list, list) { + list_del(&msg->list); + + if (msg->done) + if (!completion_done(msg->done)) + complete(msg->done); + } + mutex_unlock(&data->pending_lock); +} + +int ssp_command(struct ssp_data *data, char command, int arg) +{ + int ret; + struct ssp_msg *msg; + + msg = ssp_create_msg(command, 0, SSP_AP2HUB_WRITE, arg); + if (!msg) + return -ENOMEM; + + ssp_dbg("%s - command 0x%x %d\n", __func__, command, arg); + + ret = ssp_spi_sync_command(data, msg); + ssp_clean_msg(msg); + + return ret; +} + +int ssp_send_instruction(struct ssp_data *data, u8 inst, u8 sensor_type, + u8 *send_buf, u8 length) +{ + int ret; + struct ssp_msg *msg; + + if (data->fw_dl_state == SSP_FW_DL_STATE_DOWNLOADING) { + dev_err(SSP_DEV, "%s - Skip Inst! DL state = %d\n", + __func__, data->fw_dl_state); + return -EBUSY; + } else if (!(data->available_sensors & BIT(sensor_type)) && + (inst <= SSP_MSG2SSP_INST_CHANGE_DELAY)) { + dev_err(SSP_DEV, "%s - Bypass Inst Skip! - %u\n", + __func__, sensor_type); + return -EIO; /* just fail */ + } + + msg = ssp_create_msg(inst, length + 2, SSP_AP2HUB_WRITE, 0); + if (!msg) + return -ENOMEM; + + ssp_fill_buffer(msg, 0, &sensor_type, 1); + ssp_fill_buffer(msg, 1, send_buf, length); + + ssp_dbg("%s - Inst = 0x%x, Sensor Type = 0x%x, data = %u\n", + __func__, inst, sensor_type, send_buf[1]); + + ret = ssp_spi_sync(data, msg, 1000); + ssp_clean_msg(msg); + + return ret; +} + +int ssp_get_chipid(struct ssp_data *data) +{ + int ret; + char buffer; + struct ssp_msg *msg; + + msg = ssp_create_msg(SSP_MSG2SSP_AP_WHOAMI, 1, SSP_AP2HUB_READ, 0); + if (!msg) + return -ENOMEM; + + ret = ssp_spi_sync(data, msg, 1000); + + buffer = SSP_GET_BUFFER_AT_INDEX(msg, 0); + + ssp_clean_msg(msg); + + return ret < 0 ? ret : buffer; +} + +int ssp_set_magnetic_matrix(struct ssp_data *data) +{ + int ret; + struct ssp_msg *msg; + + msg = ssp_create_msg(SSP_MSG2SSP_AP_SET_MAGNETIC_STATIC_MATRIX, + data->sensorhub_info->mag_length, SSP_AP2HUB_WRITE, + 0); + if (!msg) + return -ENOMEM; + + ssp_fill_buffer(msg, 0, data->sensorhub_info->mag_table, + data->sensorhub_info->mag_length); + + ret = ssp_spi_sync(data, msg, 1000); + ssp_clean_msg(msg); + + return ret; +} + +unsigned int ssp_get_sensor_scanning_info(struct ssp_data *data) +{ + int ret; + __le32 result; + u32 cpu_result = 0; + + struct ssp_msg *msg = ssp_create_msg(SSP_MSG2SSP_AP_SENSOR_SCANNING, 4, + SSP_AP2HUB_READ, 0); + if (!msg) + return 0; + + ret = ssp_spi_sync(data, msg, 1000); + if (ret < 0) { + dev_err(SSP_DEV, "%s - spi read fail %d\n", __func__, ret); + goto _exit; + } + + ssp_get_buffer(msg, 0, &result, 4); + cpu_result = le32_to_cpu(result); + + dev_info(SSP_DEV, "%s state: 0x%08x\n", __func__, cpu_result); + +_exit: + ssp_clean_msg(msg); + return cpu_result; +} + +unsigned int ssp_get_firmware_rev(struct ssp_data *data) +{ + int ret; + __le32 result; + + struct ssp_msg *msg = ssp_create_msg(SSP_MSG2SSP_AP_FIRMWARE_REV, 4, + SSP_AP2HUB_READ, 0); + if (!msg) + return SSP_INVALID_REVISION; + + ret = ssp_spi_sync(data, msg, 1000); + if (ret < 0) { + dev_err(SSP_DEV, "%s - transfer fail %d\n", __func__, ret); + ret = SSP_INVALID_REVISION; + goto _exit; + } + + ssp_get_buffer(msg, 0, &result, 4); + ret = le32_to_cpu(result); + +_exit: + ssp_clean_msg(msg); + return ret; +} diff --git a/include/linux/iio/common/ssp_sensors.h b/include/linux/iio/common/ssp_sensors.h new file mode 100644 index 0000000..f4d1b0e --- /dev/null +++ b/include/linux/iio/common/ssp_sensors.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef _SSP_SENSORS_H_ +#define _SSP_SENSORS_H_ + +#include + +#define SSP_TIME_SIZE 4 +#define SSP_ACCELEROMETER_SIZE 6 +#define SSP_GYROSCOPE_SIZE 6 +#define SSP_BIO_HRM_RAW_SIZE 8 +#define SSP_BIO_HRM_RAW_FAC_SIZE 36 +#define SSP_BIO_HRM_LIB_SIZE 8 + +/** + * enum ssp_sensor_type - SSP sensor type + */ +enum ssp_sensor_type { + SSP_ACCELEROMETER_SENSOR = 0, + SSP_GYROSCOPE_SENSOR, + SSP_GEOMAGNETIC_UNCALIB_SENSOR, + SSP_GEOMAGNETIC_RAW, + SSP_GEOMAGNETIC_SENSOR, + SSP_PRESSURE_SENSOR, + SSP_GESTURE_SENSOR, + SSP_PROXIMITY_SENSOR, + SSP_TEMPERATURE_HUMIDITY_SENSOR, + SSP_LIGHT_SENSOR, + SSP_PROXIMITY_RAW, + SSP_ORIENTATION_SENSOR, + SSP_STEP_DETECTOR, + SSP_SIG_MOTION_SENSOR, + SSP_GYRO_UNCALIB_SENSOR, + SSP_GAME_ROTATION_VECTOR, + SSP_ROTATION_VECTOR, + SSP_STEP_COUNTER, + SSP_BIO_HRM_RAW, + SSP_BIO_HRM_RAW_FAC, + SSP_BIO_HRM_LIB, + SSP_SENSOR_MAX, +}; + +struct ssp_data; + +/** + * struct ssp_sensor_data - Sensor object + * @process_data: Callback to feed sensor data. + * @type: Used sensor type. + * @buffer: Received data buffer. + */ +struct ssp_sensor_data { + int (*process_data)(struct iio_dev *indio_dev, void *buf, + int64_t timestamp); + enum ssp_sensor_type type; + u8 *buffer; +}; + +void ssp_register_consumer(struct iio_dev *indio_dev, + enum ssp_sensor_type type); + +int ssp_enable_sensor(struct ssp_data *data, enum ssp_sensor_type type, + u32 delay); + +int ssp_disable_sensor(struct ssp_data *data, enum ssp_sensor_type type); + +u32 ssp_get_sensor_delay(struct ssp_data *data, enum ssp_sensor_type); + +int ssp_change_delay(struct ssp_data *data, enum ssp_sensor_type type, + u32 delay); +#endif /* _SSP_SENSORS_H_ */ -- cgit v0.10.2 From f04df4ebee932376a630e0a3be1703a2f678c60d Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Wed, 28 Jan 2015 15:05:51 +0100 Subject: iio: sensorhub: Add sensorhub bindings Add sensorhub bindings for sensorhub on Galaxy Gear 2. Signed-off-by: Karol Wrona Acked-by: Kyungmin Park Signed-off-by: Jonathan Cameron diff --git a/Documentation/devicetree/bindings/iio/sensorhub.txt b/Documentation/devicetree/bindings/iio/sensorhub.txt new file mode 100644 index 0000000..8d57571 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/sensorhub.txt @@ -0,0 +1,25 @@ +Samsung Sensorhub driver + +Sensorhub is a MCU which manages several sensors and also plays the role +of a virtual sensor device. + +Required properties: +- compatible: "samsung,sensorhub-rinato" or "samsung,sensorhub-thermostat" +- spi-max-frequency: max SPI clock frequency +- interrupt-parent: interrupt parent +- interrupts: communication interrupt +- ap-mcu-gpios: [out] ap to sensorhub line - used during communication +- mcu-ap-gpios: [in] sensorhub to ap - used during communication +- mcu-reset-gpios: [out] sensorhub reset + +Example: + + shub_spi: shub { + compatible = "samsung,sensorhub-rinato"; + spi-max-frequency = <5000000>; + interrupt-parent = <&gpx0>; + interrupts = <2 0>; + ap-mcu-gpios = <&gpx0 0 0>; + mcu-ap-gpios = <&gpx0 4 0>; + mcu-reset-gpios = <&gpx0 5 0>; + }; -- cgit v0.10.2 From 7e3a8b446b5afa53cf8d3287da286105684137ff Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Wed, 28 Jan 2015 15:05:52 +0100 Subject: iio: common: ssp_sensors: Add sensorhub iio commons This patch adds common library for sensorhub iio drivers. Signed-off-by: Karol Wrona Acked-by: Kyungmin Park Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/common/ssp_sensors/Kconfig b/drivers/iio/common/ssp_sensors/Kconfig index 759b975..0ea4faf 100644 --- a/drivers/iio/common/ssp_sensors/Kconfig +++ b/drivers/iio/common/ssp_sensors/Kconfig @@ -3,6 +3,16 @@ # menu "SSP Sensor Common" +config IIO_SSP_SENSORS_COMMONS + tristate "Commons for all SSP Sensor IIO drivers" + depends on IIO_SSP_SENSORHUB + select IIO_BUFFER + select IIO_KFIFO_BUF + help + Say yes here to build commons for SSP sensors. + To compile this as a module, choose M here: the module + will be called ssp_iio. + config IIO_SSP_SENSORHUB tristate "Samsung Sensorhub driver" depends on SPI diff --git a/drivers/iio/common/ssp_sensors/Makefile b/drivers/iio/common/ssp_sensors/Makefile index 07d3d6a..1e0389e 100644 --- a/drivers/iio/common/ssp_sensors/Makefile +++ b/drivers/iio/common/ssp_sensors/Makefile @@ -4,3 +4,5 @@ sensorhub-objs := ssp_dev.o ssp_spi.o obj-$(CONFIG_IIO_SSP_SENSORHUB) += sensorhub.o + +obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_iio.o diff --git a/drivers/iio/common/ssp_sensors/ssp_iio.c b/drivers/iio/common/ssp_sensors/ssp_iio.c new file mode 100644 index 0000000..a3ae165 --- /dev/null +++ b/drivers/iio/common/ssp_sensors/ssp_iio.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include "ssp_iio_sensor.h" + +/** + * ssp_common_buffer_postenable() - generic postenable callback for ssp buffer + * + * @indio_dev: iio device + * + * Returns 0 or negative value in case of error + */ +int ssp_common_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ssp_sensor_data *spd = iio_priv(indio_dev); + struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent); + + /* the allocation is made in post because scan size is known in this + * moment + * */ + spd->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL | GFP_DMA); + if (!spd->buffer) + return -ENOMEM; + + return ssp_enable_sensor(data, spd->type, + ssp_get_sensor_delay(data, spd->type)); +} +EXPORT_SYMBOL(ssp_common_buffer_postenable); + +/** + * ssp_common_buffer_postdisable() - generic postdisable callback for ssp buffer + * + * @indio_dev: iio device + * + * Returns 0 or negative value in case of error + */ +int ssp_common_buffer_postdisable(struct iio_dev *indio_dev) +{ + int ret; + struct ssp_sensor_data *spd = iio_priv(indio_dev); + struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent); + + ret = ssp_disable_sensor(data, spd->type); + if (ret < 0) + return ret; + + kfree(spd->buffer); + + return ret; +} +EXPORT_SYMBOL(ssp_common_buffer_postdisable); + +/** + * ssp_common_process_data() - Common process data callback for ssp sensors + * + * @indio_dev: iio device + * @buf: source buffer + * @len: sensor data length + * @timestamp: system timestamp + * + * Returns 0 or negative value in case of error + */ +int ssp_common_process_data(struct iio_dev *indio_dev, void *buf, + unsigned int len, int64_t timestamp) +{ + __le32 time; + int64_t calculated_time; + struct ssp_sensor_data *spd = iio_priv(indio_dev); + + if (indio_dev->scan_bytes == 0) + return 0; + + /* + * it always sends full set of samples, remember about available masks + */ + memcpy(spd->buffer, buf, len); + + if (indio_dev->scan_timestamp) { + memcpy(&time, &((char *)buf)[len], SSP_TIME_SIZE); + calculated_time = + timestamp + (int64_t)le32_to_cpu(time) * 1000000; + } + + return iio_push_to_buffers_with_timestamp(indio_dev, spd->buffer, + calculated_time); +} +EXPORT_SYMBOL(ssp_common_process_data); + +MODULE_AUTHOR("Karol Wrona "); +MODULE_DESCRIPTION("Samsung sensorhub commons"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/common/ssp_sensors/ssp_iio_sensor.h b/drivers/iio/common/ssp_sensors/ssp_iio_sensor.h new file mode 100644 index 0000000..dda267c --- /dev/null +++ b/drivers/iio/common/ssp_sensors/ssp_iio_sensor.h @@ -0,0 +1,70 @@ +#ifndef __SSP_IIO_SENSOR_H__ +#define __SSP_IIO_SENSOR_H__ + +#define SSP_CHANNEL_AG(_type, _mod, _index) \ +{ \ + .type = _type,\ + .modified = 1,\ + .channel2 = _mod,\ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ + .scan_index = _index,\ + .scan_type = {\ + .sign = 's',\ + .realbits = 16,\ + .storagebits = 16,\ + .shift = 0,\ + .endianness = IIO_LE,\ + },\ +} + +/* It is defined here as it is a mixed timestamp */ +#define SSP_CHAN_TIMESTAMP(_si) { \ + .type = IIO_TIMESTAMP, \ + .channel = -1, \ + .scan_index = _si, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 64, \ + .storagebits = 64, \ + }, \ +} + +#define SSP_MS_PER_S 1000 +#define SSP_INVERTED_SCALING_FACTOR 1000000ULL + +#define SSP_FACTOR_WITH_MS \ + (SSP_INVERTED_SCALING_FACTOR * SSP_MS_PER_S) + +int ssp_common_buffer_postenable(struct iio_dev *indio_dev); + +int ssp_common_buffer_postdisable(struct iio_dev *indio_dev); + +int ssp_common_process_data(struct iio_dev *indio_dev, void *buf, + unsigned int len, int64_t timestamp); + +/* Converts time in ms to frequency */ +static inline void ssp_convert_to_freq(u32 time, int *integer_part, + int *fractional) +{ + if (time == 0) { + *fractional = 0; + *integer_part = 0; + return; + } + + *integer_part = SSP_FACTOR_WITH_MS / time; + *fractional = do_div(*integer_part, SSP_INVERTED_SCALING_FACTOR); +} + +/* Converts frequency to time in ms */ +static inline int ssp_convert_to_time(int integer_part, int fractional) +{ + u64 value; + + value = integer_part * SSP_INVERTED_SCALING_FACTOR + fractional; + if (value == 0) + return 0; + + return div_u64(SSP_FACTOR_WITH_MS, value); +} +#endif /* __SSP_IIO_SENSOR_H__ */ -- cgit v0.10.2 From 3755a1d3a95ef8143466e7c753ead32bd8f6d94a Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Wed, 28 Jan 2015 15:05:53 +0100 Subject: iio: common: ssp_sensors: Add sensorhub accelerometer sensor This patch adds accelerometer iio driver which uses sensorhub as data provider. Signed-off-by: Karol Wrona Acked-by: Kyungmin Park Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 8105316..101a86d 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -13,6 +13,8 @@ obj-$(CONFIG_MMA8452) += mma8452.o obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o obj-$(CONFIG_MMA9551) += mma9551.o +obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_accel_sensor.o + obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o st_accel-y := st_accel_core.o st_accel-$(CONFIG_IIO_BUFFER) += st_accel_buffer.o diff --git a/drivers/iio/accel/ssp_accel_sensor.c b/drivers/iio/accel/ssp_accel_sensor.c new file mode 100644 index 0000000..4ae05fc --- /dev/null +++ b/drivers/iio/accel/ssp_accel_sensor.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include "../common/ssp_sensors/ssp_iio_sensor.h" + +#define SSP_CHANNEL_COUNT 3 + +#define SSP_ACCEL_NAME "ssp-accelerometer" +static const char ssp_accel_device_name[] = SSP_ACCEL_NAME; + +enum ssp_accel_3d_channel { + SSP_CHANNEL_SCAN_INDEX_X, + SSP_CHANNEL_SCAN_INDEX_Y, + SSP_CHANNEL_SCAN_INDEX_Z, + SSP_CHANNEL_SCAN_INDEX_TIME, +}; + +static int ssp_accel_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + u32 t; + struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + t = ssp_get_sensor_delay(data, SSP_ACCELEROMETER_SENSOR); + ssp_convert_to_freq(t, val, val2); + return IIO_VAL_INT_PLUS_MICRO; + default: + break; + } + + return -EINVAL; +} + +static int ssp_accel_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + int ret; + struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + ret = ssp_convert_to_time(val, val2); + ret = ssp_change_delay(data, SSP_ACCELEROMETER_SENSOR, ret); + if (ret < 0) + dev_err(&indio_dev->dev, "accel sensor enable fail\n"); + + return ret; + default: + break; + } + + return -EINVAL; +} + +static struct iio_info ssp_accel_iio_info = { + .read_raw = &ssp_accel_read_raw, + .write_raw = &ssp_accel_write_raw, +}; + +static const unsigned long ssp_accel_scan_mask[] = { 0x7, 0, }; + +static const struct iio_chan_spec ssp_acc_channels[] = { + SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_X, SSP_CHANNEL_SCAN_INDEX_X), + SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_Y, SSP_CHANNEL_SCAN_INDEX_Y), + SSP_CHANNEL_AG(IIO_ACCEL, IIO_MOD_Z, SSP_CHANNEL_SCAN_INDEX_Z), + SSP_CHAN_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME), +}; + +static int ssp_process_accel_data(struct iio_dev *indio_dev, void *buf, + int64_t timestamp) +{ + return ssp_common_process_data(indio_dev, buf, SSP_ACCELEROMETER_SIZE, + timestamp); +} + +static const struct iio_buffer_setup_ops ssp_accel_buffer_ops = { + .postenable = &ssp_common_buffer_postenable, + .postdisable = &ssp_common_buffer_postdisable, +}; + +static int ssp_accel_probe(struct platform_device *pdev) +{ + int ret; + struct iio_dev *indio_dev; + struct ssp_sensor_data *spd; + struct iio_buffer *buffer; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*spd)); + if (!indio_dev) + return -ENOMEM; + + spd = iio_priv(indio_dev); + + spd->process_data = ssp_process_accel_data; + spd->type = SSP_ACCELEROMETER_SENSOR; + + indio_dev->name = ssp_accel_device_name; + indio_dev->dev.parent = &pdev->dev; + indio_dev->dev.of_node = pdev->dev.of_node; + indio_dev->info = &ssp_accel_iio_info; + indio_dev->modes = INDIO_BUFFER_SOFTWARE; + indio_dev->channels = ssp_acc_channels; + indio_dev->num_channels = ARRAY_SIZE(ssp_acc_channels); + indio_dev->available_scan_masks = ssp_accel_scan_mask; + + buffer = devm_iio_kfifo_allocate(&pdev->dev); + if (!buffer) + return -ENOMEM; + + iio_device_attach_buffer(indio_dev, buffer); + + indio_dev->setup_ops = &ssp_accel_buffer_ops; + + platform_set_drvdata(pdev, indio_dev); + + ret = iio_device_register(indio_dev); + if (ret < 0) + return ret; + + /* ssp registering should be done after all iio setup */ + ssp_register_consumer(indio_dev, SSP_ACCELEROMETER_SENSOR); + + return 0; +} + +static int ssp_accel_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + + iio_device_unregister(indio_dev); + + return 0; +} + +static struct platform_driver ssp_accel_driver = { + .driver = { + .name = SSP_ACCEL_NAME, + }, + .probe = ssp_accel_probe, + .remove = ssp_accel_remove, +}; + +module_platform_driver(ssp_accel_driver); + +MODULE_AUTHOR("Karol Wrona "); +MODULE_DESCRIPTION("Samsung sensorhub accelerometers driver"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From a9afcaa69fc23679f22cf613e7113a60e115e03a Mon Sep 17 00:00:00 2001 From: Karol Wrona Date: Wed, 28 Jan 2015 15:05:54 +0100 Subject: iio: common: ssp_sensors: Add sensorhub gyroscope sensor This patch adds gyroscope iio driver which uses sensorhub as data provider. Signed-off-by: Karol Wrona Acked-by: Kyungmin Park Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile index 36a3877..f46341b 100644 --- a/drivers/iio/gyro/Makefile +++ b/drivers/iio/gyro/Makefile @@ -16,6 +16,8 @@ itg3200-y := itg3200_core.o itg3200-$(CONFIG_IIO_BUFFER) += itg3200_buffer.o obj-$(CONFIG_ITG3200) += itg3200.o +obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_gyro_sensor.o + obj-$(CONFIG_IIO_ST_GYRO_3AXIS) += st_gyro.o st_gyro-y := st_gyro_core.o st_gyro-$(CONFIG_IIO_BUFFER) += st_gyro_buffer.o diff --git a/drivers/iio/gyro/ssp_gyro_sensor.c b/drivers/iio/gyro/ssp_gyro_sensor.c new file mode 100644 index 0000000..0a8afdd --- /dev/null +++ b/drivers/iio/gyro/ssp_gyro_sensor.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include "../common/ssp_sensors/ssp_iio_sensor.h" + +#define SSP_CHANNEL_COUNT 3 + +#define SSP_GYROSCOPE_NAME "ssp-gyroscope" +static const char ssp_gyro_name[] = SSP_GYROSCOPE_NAME; + +enum ssp_gyro_3d_channel { + SSP_CHANNEL_SCAN_INDEX_X, + SSP_CHANNEL_SCAN_INDEX_Y, + SSP_CHANNEL_SCAN_INDEX_Z, + SSP_CHANNEL_SCAN_INDEX_TIME, +}; + +static int ssp_gyro_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + u32 t; + struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + t = ssp_get_sensor_delay(data, SSP_GYROSCOPE_SENSOR); + ssp_convert_to_freq(t, val, val2); + return IIO_VAL_INT_PLUS_MICRO; + default: + break; + } + + return -EINVAL; +} + +static int ssp_gyro_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + int ret; + struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + ret = ssp_convert_to_time(val, val2); + ret = ssp_change_delay(data, SSP_GYROSCOPE_SENSOR, ret); + if (ret < 0) + dev_err(&indio_dev->dev, "gyro sensor enable fail\n"); + + return ret; + default: + break; + } + + return -EINVAL; +} + +static struct iio_info ssp_gyro_iio_info = { + .read_raw = &ssp_gyro_read_raw, + .write_raw = &ssp_gyro_write_raw, +}; + +static const unsigned long ssp_gyro_scan_mask[] = { 0x07, 0, }; + +static const struct iio_chan_spec ssp_gyro_channels[] = { + SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_X, SSP_CHANNEL_SCAN_INDEX_X), + SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_Y, SSP_CHANNEL_SCAN_INDEX_Y), + SSP_CHANNEL_AG(IIO_ANGL_VEL, IIO_MOD_Z, SSP_CHANNEL_SCAN_INDEX_Z), + SSP_CHAN_TIMESTAMP(SSP_CHANNEL_SCAN_INDEX_TIME), +}; + +static int ssp_process_gyro_data(struct iio_dev *indio_dev, void *buf, + int64_t timestamp) +{ + return ssp_common_process_data(indio_dev, buf, SSP_GYROSCOPE_SIZE, + timestamp); +} + +static const struct iio_buffer_setup_ops ssp_gyro_buffer_ops = { + .postenable = &ssp_common_buffer_postenable, + .postdisable = &ssp_common_buffer_postdisable, +}; + +static int ssp_gyro_probe(struct platform_device *pdev) +{ + int ret; + struct iio_dev *indio_dev; + struct ssp_sensor_data *spd; + struct iio_buffer *buffer; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*spd)); + if (!indio_dev) + return -ENOMEM; + + spd = iio_priv(indio_dev); + + spd->process_data = ssp_process_gyro_data; + spd->type = SSP_GYROSCOPE_SENSOR; + + indio_dev->name = ssp_gyro_name; + indio_dev->dev.parent = &pdev->dev; + indio_dev->info = &ssp_gyro_iio_info; + indio_dev->modes = INDIO_BUFFER_SOFTWARE; + indio_dev->channels = ssp_gyro_channels; + indio_dev->num_channels = ARRAY_SIZE(ssp_gyro_channels); + indio_dev->available_scan_masks = ssp_gyro_scan_mask; + + buffer = devm_iio_kfifo_allocate(&pdev->dev); + if (!buffer) + return -ENOMEM; + + iio_device_attach_buffer(indio_dev, buffer); + + indio_dev->setup_ops = &ssp_gyro_buffer_ops; + + platform_set_drvdata(pdev, indio_dev); + + ret = iio_device_register(indio_dev); + if (ret < 0) + return ret; + + /* ssp registering should be done after all iio setup */ + ssp_register_consumer(indio_dev, SSP_GYROSCOPE_SENSOR); + + return 0; +} + +static int ssp_gyro_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + + iio_device_unregister(indio_dev); + + return 0; +} + +static struct platform_driver ssp_gyro_driver = { + .driver = { + .name = SSP_GYROSCOPE_NAME, + }, + .probe = ssp_gyro_probe, + .remove = ssp_gyro_remove, +}; + +module_platform_driver(ssp_gyro_driver); + +MODULE_AUTHOR("Karol Wrona "); +MODULE_DESCRIPTION("Samsung sensorhub gyroscopes driver"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 2f0ecb7c6563d711bec15268d56adf1c630e77d1 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Tue, 27 Jan 2015 20:41:52 +0200 Subject: iio: core: Introduce IIO_CHAN_INFO_DEBOUNCE_COUNT and _TIME The pedometer needs to filter out false steps that might be generated by tapping the foot, sitting, etc. To do that it computes the number of steps that occur in a given time and decides the user is moving only if this value is over a threshold. E.g.: the user starts moving only if he takes 4 steps in 3 seconds. This filter is applied only when the user starts moving. A device that has such pedometer functionality is Freescale's MMA9553L: http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf. To export this feature, this patch introduces IIO_CHAN_INFO_DEBOUNCE_COUNT and IIO_CHAN_INFO_DEBOUNCE_TIME. For the pedometer, in_steps_debounce_count will specify the number of steps that need to occur in in_steps_debounce_time seconds so that the pedometer decides the user is moving. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index c03a140..b4ea9c5 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1193,3 +1193,18 @@ Description: This attribute is used to read the current speed value of the user (which is the norm or magnitude of the velocity vector). Units after application of scale are m/s. + +What: /sys/.../iio:deviceX/in_steps_debounce_count +KernelVersion: 3.20 +Contact: linux-iio@vger.kernel.org +Description: + Specifies the number of steps that must occur within + in_steps_filter_debounce_time for the pedometer to decide the + consumer is making steps. + +What: /sys/.../iio:deviceX/in_steps_debounce_time +KernelVersion: 3.20 +Contact: linux-iio@vger.kernel.org +Description: + Specifies number of seconds in which we compute the steps + that occur in order to decide if the consumer is making steps. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 4ee6fdf..aaba9d3 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -126,6 +126,8 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_ENABLE] = "en", [IIO_CHAN_INFO_CALIBHEIGHT] = "calibheight", [IIO_CHAN_INFO_CALIBWEIGHT] = "calibweight", + [IIO_CHAN_INFO_DEBOUNCE_COUNT] = "debounce_count", + [IIO_CHAN_INFO_DEBOUNCE_TIME] = "debounce_time", }; /** diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 51f1643..80d8550 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -41,6 +41,8 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_ENABLE, IIO_CHAN_INFO_CALIBHEIGHT, IIO_CHAN_INFO_CALIBWEIGHT, + IIO_CHAN_INFO_DEBOUNCE_COUNT, + IIO_CHAN_INFO_DEBOUNCE_TIME, }; enum iio_shared_by { -- cgit v0.10.2 From 81110933a94279afce73beecae568e704cf2b9b6 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Tue, 27 Jan 2015 20:41:53 +0200 Subject: iio: Documentation: Fix calibheight unit Change calibheight unit from centimeters to meters to follow iio guidelines of using SI units. Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index b4ea9c5..588620e 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -347,7 +347,7 @@ What: /sys/bus/iio/devices/iio:deviceX/in_steps_calibheight KernelVersion: 3.19 Contact: linux-iio@vger.kernel.org Description: - Height of the user (in centimeters) used by some pedometers + Height of the user (in meters) used by some pedometers to compute the stride length, distance, speed and activity type. -- cgit v0.10.2 From 40cb761306d6c19d80fe85f9ae52615932f76b71 Mon Sep 17 00:00:00 2001 From: Irina Tirdea Date: Thu, 29 Jan 2015 18:45:10 +0000 Subject: iio: add driver for Freescale MMA9553 Add support for Freescale MMA9553L Intelligent Pedometer Platform. The following functionalities are supported: - step counter (counts the number of steps using a HW register) - step detector (generates an iio event at every step the user takes) - activity recognition (rest, walking, jogging, running) - speed - calories - distance To get accurate pedometer results, the user's height, weight and gender need to be configured. The specifications can be downloaded from: http://www.freescale.com/files/sensors/doc/ref_manual/MMA955xLSWRM.pdf http://www.freescale.com/files/sensors/doc/ref_manual/MMA9553LSWRM.pdf Signed-off-by: Irina Tirdea Signed-off-by: Jonathan Cameron diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 588620e..9a70c31 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -343,7 +343,30 @@ Description: production inaccuracies). If shared across all channels, _calibscale is used. -What: /sys/bus/iio/devices/iio:deviceX/in_steps_calibheight +What: /sys/bus/iio/devices/iio:deviceX/in_activity_calibgender +What: /sys/bus/iio/devices/iio:deviceX/in_energy_calibgender +What: /sys/bus/iio/devices/iio:deviceX/in_distance_calibgender +What: /sys/bus/iio/devices/iio:deviceX/in_velocity_calibgender +KernelVersion: 3.20 +Contact: linux-iio@vger.kernel.org +Description: + Gender of the user (e.g.: male, female) used by some pedometers + to compute the stride length, distance, speed and activity + type. + +What: /sys/bus/iio/devices/iio:deviceX/in_activity_calibgender_available +What: /sys/bus/iio/devices/iio:deviceX/in_energy_calibgender_available +What: /sys/bus/iio/devices/iio:deviceX/in_distance_calibgender_available +What: /sys/bus/iio/devices/iio:deviceX/in_velocity_calibgender_available +KernelVersion: 3.20 +Contact: linux-iio@vger.kernel.org +Description: + Lists all available gender values (e.g.: male, female). + +What: /sys/bus/iio/devices/iio:deviceX/in_activity_calibheight +What: /sys/bus/iio/devices/iio:deviceX/in_energy_calibheight +What: /sys/bus/iio/devices/iio:deviceX/in_distance_calibheight +What: /sys/bus/iio/devices/iio:deviceX/in_velocity_calibheight KernelVersion: 3.19 Contact: linux-iio@vger.kernel.org Description: @@ -818,6 +841,14 @@ What: /sys/.../events/in_tempY_roc_falling_period What: /sys/.../events/in_accel_x&y&z_mag_falling_period What: /sys/.../events/in_intensity0_thresh_period What: /sys/.../events/in_proximity0_thresh_period +What: /sys/.../events/in_activity_still_thresh_rising_period +What: /sys/.../events/in_activity_still_thresh_falling_period +What: /sys/.../events/in_activity_walking_thresh_rising_period +What: /sys/.../events/in_activity_walking_thresh_falling_period +What: /sys/.../events/in_activity_jogging_thresh_rising_period +What: /sys/.../events/in_activity_jogging_thresh_falling_period +What: /sys/.../events/in_activity_running_thresh_rising_period +What: /sys/.../events/in_activity_running_thresh_falling_period KernelVersion: 2.6.37 Contact: linux-iio@vger.kernel.org Description: @@ -1142,6 +1173,12 @@ Description: This attribute is used to get/set the integration time in seconds. +What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_integration_time +KernelVersion: 3.20 +Contact: linux-iio@vger.kernel.org +Description: + Number of seconds in which to compute speed. + What: /sys/bus/iio/devices/iio:deviceX/in_rot_quaternion_raw KernelVersion: 3.15 Contact: linux-iio@vger.kernel.org @@ -1170,13 +1207,17 @@ Description: present, output should be considered as processed with the unit in milliamps. +What: /sys/.../iio:deviceX/in_energy_en +What: /sys/.../iio:deviceX/in_distance_en +What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_en What: /sys/.../iio:deviceX/in_steps_en KernelVersion: 3.19 Contact: linux-iio@vger.kernel.org Description: - Activates the step counter. After activation, the number of steps - taken by the user will be counted in hardware and exported through - in_steps_input. + Activates a device feature that runs in firmware/hardware. + E.g. for steps: the pedometer saves power while not used; + when activated, it will count the steps taken by the user in + firmware and export them through in_steps_input. What: /sys/.../iio:deviceX/in_steps_input KernelVersion: 3.19 diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index c53047d..7c9a9a9 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -126,4 +126,14 @@ config MMA9551 To compile this driver as a module, choose M here: the module will be called mma9551. +config MMA9553 + tristate "Freescale MMA9553L Intelligent Pedometer Platform Driver" + depends on I2C + select MMA9551_CORE + help + Say yes here to build support for the Freescale MMA9553L + Intelligent Pedometer Platform Driver. + + To compile this driver as a module, choose M here: the module + will be called mma9553. endmenu diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index 101a86d..99d89e4 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_MMA8452) += mma8452.o obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o obj-$(CONFIG_MMA9551) += mma9551.o +obj-$(CONFIG_MMA9553) += mma9553.o obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_accel_sensor.o diff --git a/drivers/iio/accel/mma9551_core.c b/drivers/iio/accel/mma9551_core.c index 7f1a73e..7f55a6d 100644 --- a/drivers/iio/accel/mma9551_core.c +++ b/drivers/iio/accel/mma9551_core.c @@ -53,6 +53,11 @@ #define MMA9551_AFE_Y_ACCEL_REG 0x02 #define MMA9551_AFE_Z_ACCEL_REG 0x04 +/* Reset/Suspend/Clear application */ +#define MMA9551_RSC_RESET 0x00 +#define MMA9551_RSC_OFFSET(mask) (3 - (ffs(mask) - 1) / 8) +#define MMA9551_RSC_VAL(mask) (mask >> (((ffs(mask) - 1) / 8) * 8)) + /* * A response is composed of: * - control registers: MB0-3 @@ -275,6 +280,64 @@ int mma9551_read_status_byte(struct i2c_client *client, u8 app_id, EXPORT_SYMBOL(mma9551_read_status_byte); /** + * mma9551_read_config_word() - read 1 config word + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @val: Pointer to store value read + * + * Read one configuration word from the device using MMA955xL command format. + * Commands to the MMA955xL platform consist of a write followed by one or + * more reads. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_read_config_word(struct i2c_client *client, u8 app_id, + u16 reg, u16 *val) +{ + int ret; + __be16 v; + + ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, + reg, NULL, 0, (u8 *)&v, 2); + *val = be16_to_cpu(v); + + return ret; +} +EXPORT_SYMBOL(mma9551_read_config_word); + +/** + * mma9551_write_config_word() - write 1 config word + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @val: Value to write + * + * Write one configuration word from the device using MMA955xL command format. + * Commands to the MMA955xL platform consist of a write followed by one or + * more reads. + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_write_config_word(struct i2c_client *client, u8 app_id, + u16 reg, u16 val) +{ + __be16 v = cpu_to_be16(val); + + return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg, + (u8 *) &v, 2, NULL, 0); +} +EXPORT_SYMBOL(mma9551_write_config_word); + +/** * mma9551_read_status_word() - read 1 status word * @client: I2C client * @app_id: Application ID @@ -306,6 +369,107 @@ int mma9551_read_status_word(struct i2c_client *client, u8 app_id, EXPORT_SYMBOL(mma9551_read_status_word); /** + * mma9551_read_config_words() - read multiple config words + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @len: Length of array to read in bytes + * @val: Array of words to read + * + * Read multiple configuration registers (word-sized registers). + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_read_config_words(struct i2c_client *client, u8 app_id, + u16 reg, u8 len, u16 *buf) +{ + int ret, i; + int len_words = len / sizeof(u16); + __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS]; + + ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG, + reg, NULL, 0, (u8 *) be_buf, len); + if (ret < 0) + return ret; + + for (i = 0; i < len_words; i++) + buf[i] = be16_to_cpu(be_buf[i]); + + return 0; +} +EXPORT_SYMBOL(mma9551_read_config_words); + +/** + * mma9551_read_status_words() - read multiple status words + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @len: Length of array to read in bytes + * @val: Array of words to read + * + * Read multiple status registers (word-sized registers). + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_read_status_words(struct i2c_client *client, u8 app_id, + u16 reg, u8 len, u16 *buf) +{ + int ret, i; + int len_words = len / sizeof(u16); + __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS]; + + ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS, + reg, NULL, 0, (u8 *) be_buf, len); + if (ret < 0) + return ret; + + for (i = 0; i < len_words; i++) + buf[i] = be16_to_cpu(be_buf[i]); + + return 0; +} +EXPORT_SYMBOL(mma9551_read_status_words); + +/** + * mma9551_write_config_words() - write multiple config words + * @client: I2C client + * @app_id: Application ID + * @reg: Application register + * @len: Length of array to write in bytes + * @val: Array of words to write + * + * Write multiple configuration registers (word-sized registers). + * + * Locking note: This function must be called with the device lock held. + * Locking is not handled inside the function. Callers should ensure they + * serialize access to the HW. + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_write_config_words(struct i2c_client *client, u8 app_id, + u16 reg, u8 len, u16 *buf) +{ + int i; + int len_words = len / sizeof(u16); + __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS]; + + for (i = 0; i < len_words; i++) + be_buf[i] = cpu_to_be16(buf[i]); + + return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, + reg, (u8 *) be_buf, len, NULL, 0); +} +EXPORT_SYMBOL(mma9551_write_config_words); + +/** * mma9551_update_config_bits() - update bits in register * @client: I2C client * @app_id: Application ID @@ -609,6 +773,25 @@ int mma9551_read_accel_scale(int *val, int *val2) } EXPORT_SYMBOL(mma9551_read_accel_scale); +/** + * mma9551_app_reset() - reset application + * @client: I2C client + * @app_mask: Application to reset + * + * Reset the given application (using the Reset/Suspend/Clear + * Control Application) + * + * Returns: 0 on success, negative value on failure. + */ +int mma9551_app_reset(struct i2c_client *client, u32 app_mask) +{ + return mma9551_write_config_byte(client, MMA9551_APPID_RCS, + MMA9551_RSC_RESET + + MMA9551_RSC_OFFSET(app_mask), + MMA9551_RSC_VAL(app_mask)); +} +EXPORT_SYMBOL(mma9551_app_reset); + MODULE_AUTHOR("Irina Tirdea "); MODULE_AUTHOR("Vlad Dogaru "); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/accel/mma9551_core.h b/drivers/iio/accel/mma9551_core.h index e6efd027..edaa56b 100644 --- a/drivers/iio/accel/mma9551_core.h +++ b/drivers/iio/accel/mma9551_core.h @@ -21,9 +21,13 @@ #define MMA9551_APPID_AFE 0x06 #define MMA9551_APPID_TILT 0x0B #define MMA9551_APPID_SLEEP_WAKE 0x12 -#define MMA9551_APPID_RESET 0x17 +#define MMA9551_APPID_PEDOMETER 0x15 +#define MMA9551_APPID_RCS 0x17 #define MMA9551_APPID_NONE 0xff +/* Reset/Suspend/Clear application app masks */ +#define MMA9551_RSC_PED BIT(21) + #define MMA9551_AUTO_SUSPEND_DELAY_MS 2000 enum mma9551_gpio_pin { @@ -48,8 +52,18 @@ int mma9551_write_config_byte(struct i2c_client *client, u8 app_id, u16 reg, u8 val); int mma9551_read_status_byte(struct i2c_client *client, u8 app_id, u16 reg, u8 *val); +int mma9551_read_config_word(struct i2c_client *client, u8 app_id, + u16 reg, u16 *val); +int mma9551_write_config_word(struct i2c_client *client, u8 app_id, + u16 reg, u16 val); int mma9551_read_status_word(struct i2c_client *client, u8 app_id, u16 reg, u16 *val); +int mma9551_read_config_words(struct i2c_client *client, u8 app_id, + u16 reg, u8 len, u16 *buf); +int mma9551_read_status_words(struct i2c_client *client, u8 app_id, + u16 reg, u8 len, u16 *buf); +int mma9551_write_config_words(struct i2c_client *client, u8 app_id, + u16 reg, u8 len, u16 *buf); int mma9551_update_config_bits(struct i2c_client *client, u8 app_id, u16 reg, u8 mask, u8 val); int mma9551_gpio_config(struct i2c_client *client, enum mma9551_gpio_pin pin, @@ -62,5 +76,6 @@ int mma9551_read_accel_chan(struct i2c_client *client, const struct iio_chan_spec *chan, int *val, int *val2); int mma9551_read_accel_scale(int *val, int *val2); +int mma9551_app_reset(struct i2c_client *client, u32 app_mask); #endif /* _MMA9551_CORE_H_ */ diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c new file mode 100644 index 0000000..d23ebf1 --- /dev/null +++ b/drivers/iio/accel/mma9553.c @@ -0,0 +1,1334 @@ +/* + * Freescale MMA9553L Intelligent Pedometer driver + * Copyright (c) 2014, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mma9551_core.h" + +#define MMA9553_DRV_NAME "mma9553" +#define MMA9553_IRQ_NAME "mma9553_event" +#define MMA9553_GPIO_NAME "mma9553_int" + +/* Pedometer configuration registers (R/W) */ +#define MMA9553_REG_CONF_SLEEPMIN 0x00 +#define MMA9553_REG_CONF_SLEEPMAX 0x02 +#define MMA9553_REG_CONF_SLEEPTHD 0x04 +#define MMA9553_MASK_CONF_WORD GENMASK(15, 0) + +#define MMA9553_REG_CONF_CONF_STEPLEN 0x06 +#define MMA9553_MASK_CONF_CONFIG BIT(15) +#define MMA9553_MASK_CONF_ACT_DBCNTM BIT(14) +#define MMA9553_MASK_CONF_SLP_DBCNTM BIT(13) +#define MMA9553_MASK_CONF_STEPLEN GENMASK(7, 0) + +#define MMA9553_REG_CONF_HEIGHT_WEIGHT 0x08 +#define MMA9553_MASK_CONF_HEIGHT GENMASK(15, 8) +#define MMA9553_MASK_CONF_WEIGHT GENMASK(7, 0) + +#define MMA9553_REG_CONF_FILTER 0x0A +#define MMA9553_MASK_CONF_FILTSTEP GENMASK(15, 8) +#define MMA9553_MASK_CONF_MALE BIT(7) +#define MMA9553_MASK_CONF_FILTTIME GENMASK(6, 0) + +#define MMA9553_REG_CONF_SPEED_STEP 0x0C +#define MMA9553_MASK_CONF_SPDPRD GENMASK(15, 8) +#define MMA9553_MASK_CONF_STEPCOALESCE GENMASK(7, 0) + +#define MMA9553_REG_CONF_ACTTHD 0x0E + +/* Pedometer status registers (R-only) */ +#define MMA9553_REG_STATUS 0x00 +#define MMA9553_MASK_STATUS_MRGFL BIT(15) +#define MMA9553_MASK_STATUS_SUSPCHG BIT(14) +#define MMA9553_MASK_STATUS_STEPCHG BIT(13) +#define MMA9553_MASK_STATUS_ACTCHG BIT(12) +#define MMA9553_MASK_STATUS_SUSP BIT(11) +#define MMA9553_MASK_STATUS_ACTIVITY (BIT(10) | BIT(9) | BIT(8)) +#define MMA9553_MASK_STATUS_VERSION 0x00FF + +#define MMA9553_REG_STEPCNT 0x02 +#define MMA9553_REG_DISTANCE 0x04 +#define MMA9553_REG_SPEED 0x06 +#define MMA9553_REG_CALORIES 0x08 +#define MMA9553_REG_SLEEPCNT 0x0A + +/* Pedometer events are always mapped to this pin. */ +#define MMA9553_DEFAULT_GPIO_PIN mma9551_gpio6 +#define MMA9553_DEFAULT_GPIO_POLARITY 0 + +/* Bitnum used for gpio configuration = bit number in high status byte */ +#define STATUS_TO_BITNUM(bit) (ffs(bit) - 9) + +#define MMA9553_DEFAULT_SAMPLE_RATE 30 /* Hz */ + +/* + * The internal activity level must be stable for ACTTHD samples before + * ACTIVITY is updated.The ACTIVITY variable contains the current activity + * level and is updated every time a step is detected or once a second + * if there are no steps. + */ +#define MMA9553_ACTIVITY_THD_TO_SEC(thd) ((thd) / MMA9553_DEFAULT_SAMPLE_RATE) +#define MMA9553_ACTIVITY_SEC_TO_THD(sec) ((sec) * MMA9553_DEFAULT_SAMPLE_RATE) + +/* + * Autonomously suspend pedometer if acceleration vector magnitude + * is near 1g (4096 at 0.244 mg/LSB resolution) for 30 seconds. + */ +#define MMA9553_DEFAULT_SLEEPMIN 3688 /* 0,9 g */ +#define MMA9553_DEFAULT_SLEEPMAX 4508 /* 1,1 g */ +#define MMA9553_DEFAULT_SLEEPTHD (MMA9553_DEFAULT_SAMPLE_RATE * 30) + +#define MMA9553_CONFIG_RETRIES 2 + +/* Status register - activity field */ +enum activity_level { + ACTIVITY_UNKNOWN, + ACTIVITY_REST, + ACTIVITY_WALKING, + ACTIVITY_JOGGING, + ACTIVITY_RUNNING, +}; + +static struct mma9553_event_info { + enum iio_chan_type type; + enum iio_modifier mod; + enum iio_event_direction dir; +} mma9553_events_info[] = { + { + .type = IIO_STEPS, + .mod = IIO_NO_MOD, + .dir = IIO_EV_DIR_NONE, + }, + { + .type = IIO_ACTIVITY, + .mod = IIO_MOD_STILL, + .dir = IIO_EV_DIR_RISING, + }, + { + .type = IIO_ACTIVITY, + .mod = IIO_MOD_STILL, + .dir = IIO_EV_DIR_FALLING, + }, + { + .type = IIO_ACTIVITY, + .mod = IIO_MOD_WALKING, + .dir = IIO_EV_DIR_RISING, + }, + { + .type = IIO_ACTIVITY, + .mod = IIO_MOD_WALKING, + .dir = IIO_EV_DIR_FALLING, + }, + { + .type = IIO_ACTIVITY, + .mod = IIO_MOD_JOGGING, + .dir = IIO_EV_DIR_RISING, + }, + { + .type = IIO_ACTIVITY, + .mod = IIO_MOD_JOGGING, + .dir = IIO_EV_DIR_FALLING, + }, + { + .type = IIO_ACTIVITY, + .mod = IIO_MOD_RUNNING, + .dir = IIO_EV_DIR_RISING, + }, + { + .type = IIO_ACTIVITY, + .mod = IIO_MOD_RUNNING, + .dir = IIO_EV_DIR_FALLING, + }, +}; + +#define MMA9553_EVENTS_INFO_SIZE ARRAY_SIZE(mma9553_events_info) + +struct mma9553_event { + struct mma9553_event_info *info; + bool enabled; +}; + +struct mma9553_conf_regs { + u16 sleepmin; + u16 sleepmax; + u16 sleepthd; + u16 config; + u16 height_weight; + u16 filter; + u16 speed_step; + u16 actthd; +} __packed; + +struct mma9553_data { + struct i2c_client *client; + struct mutex mutex; + struct mma9553_conf_regs conf; + struct mma9553_event events[MMA9553_EVENTS_INFO_SIZE]; + int num_events; + u8 gpio_bitnum; + /* + * This is used for all features that depend on step count: + * step count, distance, speed, calories. + */ + bool stepcnt_enabled; + u16 stepcnt; + u8 activity; + s64 timestamp; +}; + +static u8 mma9553_get_bits(u16 val, u16 mask) +{ + return (val & mask) >> (ffs(mask) - 1); +} + +static u16 mma9553_set_bits(u16 current_val, u16 val, u16 mask) +{ + return (current_val & ~mask) | (val << (ffs(mask) - 1)); +} + +static enum iio_modifier mma9553_activity_to_mod(enum activity_level activity) +{ + switch (activity) { + case ACTIVITY_RUNNING: + return IIO_MOD_RUNNING; + case ACTIVITY_JOGGING: + return IIO_MOD_JOGGING; + case ACTIVITY_WALKING: + return IIO_MOD_WALKING; + case ACTIVITY_REST: + return IIO_MOD_STILL; + case ACTIVITY_UNKNOWN: + default: + return IIO_NO_MOD; + } +} + +static void mma9553_init_events(struct mma9553_data *data) +{ + int i; + + data->num_events = MMA9553_EVENTS_INFO_SIZE; + for (i = 0; i < data->num_events; i++) { + data->events[i].info = &mma9553_events_info[i]; + data->events[i].enabled = false; + } +} + +static struct mma9553_event *mma9553_get_event(struct mma9553_data *data, + enum iio_chan_type type, + enum iio_modifier mod, + enum iio_event_direction dir) +{ + int i; + + for (i = 0; i < data->num_events; i++) + if (data->events[i].info->type == type && + data->events[i].info->mod == mod && + data->events[i].info->dir == dir) + return &data->events[i]; + + return NULL; +} + +static bool mma9553_is_any_event_enabled(struct mma9553_data *data, + bool check_type, + enum iio_chan_type type) +{ + int i; + + for (i = 0; i < data->num_events; i++) + if ((check_type && data->events[i].info->type == type && + data->events[i].enabled) || + (!check_type && data->events[i].enabled)) + return true; + + return false; +} + +static int mma9553_set_config(struct mma9553_data *data, u16 reg, + u16 *p_reg_val, u16 val, u16 mask) +{ + int ret, retries; + u16 reg_val, config; + + reg_val = *p_reg_val; + if (val == mma9553_get_bits(reg_val, mask)) + return 0; + + reg_val = mma9553_set_bits(reg_val, val, mask); + ret = mma9551_write_config_word(data->client, MMA9551_APPID_PEDOMETER, + reg, reg_val); + if (ret < 0) { + dev_err(&data->client->dev, + "error writing config register 0x%x\n", reg); + return ret; + } + + *p_reg_val = reg_val; + + /* Reinitializes the pedometer with current configuration values */ + config = mma9553_set_bits(data->conf.config, 1, + MMA9553_MASK_CONF_CONFIG); + + ret = mma9551_write_config_word(data->client, MMA9551_APPID_PEDOMETER, + MMA9553_REG_CONF_CONF_STEPLEN, config); + if (ret < 0) { + dev_err(&data->client->dev, + "error writing config register 0x%x\n", + MMA9553_REG_CONF_CONF_STEPLEN); + return ret; + } + + retries = MMA9553_CONFIG_RETRIES; + do { + mma9551_sleep(MMA9553_DEFAULT_SAMPLE_RATE); + ret = mma9551_read_config_word(data->client, + MMA9551_APPID_PEDOMETER, + MMA9553_REG_CONF_CONF_STEPLEN, + &config); + if (ret < 0) + return ret; + } while (mma9553_get_bits(config, MMA9553_MASK_CONF_CONFIG) && + --retries > 0); + + return 0; +} + +static int mma9553_read_activity_stepcnt(struct mma9553_data *data, + u8 *activity, u16 *stepcnt) +{ + u32 status_stepcnt; + u16 status; + int ret; + + ret = mma9551_read_status_words(data->client, MMA9551_APPID_PEDOMETER, + MMA9553_REG_STATUS, sizeof(u32), + (u16 *) &status_stepcnt); + if (ret < 0) { + dev_err(&data->client->dev, + "error reading status and stepcnt\n"); + return ret; + } + + status = status_stepcnt & MMA9553_MASK_CONF_WORD; + *activity = mma9553_get_bits(status, MMA9553_MASK_STATUS_ACTIVITY); + *stepcnt = status_stepcnt >> 16; + + return 0; +} + +static int mma9553_conf_gpio(struct mma9553_data *data) +{ + u8 bitnum = 0, appid = MMA9551_APPID_PEDOMETER; + int ret; + struct mma9553_event *ev_step_detect; + bool activity_enabled; + + activity_enabled = + mma9553_is_any_event_enabled(data, true, IIO_ACTIVITY); + ev_step_detect = + mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD, IIO_EV_DIR_NONE); + + /* + * If both step detector and activity are enabled, use the MRGFL bit. + * This bit is the logical OR of the SUSPCHG, STEPCHG, and ACTCHG flags. + */ + if (activity_enabled && ev_step_detect->enabled) + bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_MRGFL); + else if (ev_step_detect->enabled) + bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_STEPCHG); + else if (activity_enabled) + bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_ACTCHG); + else /* Reset */ + appid = MMA9551_APPID_NONE; + + if (data->gpio_bitnum == bitnum) + return 0; + + /* Save initial values for activity and stepcnt */ + if (activity_enabled || ev_step_detect->enabled) + mma9553_read_activity_stepcnt(data, &data->activity, + &data->stepcnt); + + ret = mma9551_gpio_config(data->client, + MMA9553_DEFAULT_GPIO_PIN, + appid, bitnum, MMA9553_DEFAULT_GPIO_POLARITY); + if (ret < 0) + return ret; + data->gpio_bitnum = bitnum; + + return 0; +} + +static int mma9553_init(struct mma9553_data *data) +{ + int ret; + + ret = mma9551_read_version(data->client); + if (ret) + return ret; + + /* + * Read all the pedometer configuration registers. This is used as + * a device identification command to differentiate the MMA9553L + * from the MMA9550L. + */ + ret = + mma9551_read_config_words(data->client, MMA9551_APPID_PEDOMETER, + MMA9553_REG_CONF_SLEEPMIN, + sizeof(data->conf), (u16 *) &data->conf); + if (ret < 0) { + dev_err(&data->client->dev, + "device is not MMA9553L: failed to read cfg regs\n"); + return ret; + } + + + /* Reset gpio */ + data->gpio_bitnum = -1; + ret = mma9553_conf_gpio(data); + if (ret < 0) + return ret; + + ret = mma9551_app_reset(data->client, MMA9551_RSC_PED); + if (ret < 0) + return ret; + + /* Init config registers */ + data->conf.sleepmin = MMA9553_DEFAULT_SLEEPMIN; + data->conf.sleepmax = MMA9553_DEFAULT_SLEEPMAX; + data->conf.sleepthd = MMA9553_DEFAULT_SLEEPTHD; + data->conf.config = + mma9553_set_bits(data->conf.config, 1, MMA9553_MASK_CONF_CONFIG); + /* + * Clear the activity debounce counter when the activity level changes, + * so that the confidence level applies for any activity level. + */ + data->conf.config = mma9553_set_bits(data->conf.config, 1, + MMA9553_MASK_CONF_ACT_DBCNTM); + ret = + mma9551_write_config_words(data->client, MMA9551_APPID_PEDOMETER, + MMA9553_REG_CONF_SLEEPMIN, + sizeof(data->conf), (u16 *) &data->conf); + if (ret < 0) { + dev_err(&data->client->dev, + "failed to write configuration registers\n"); + return ret; + } + + return mma9551_set_device_state(data->client, true); +} + +static int mma9553_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct mma9553_data *data = iio_priv(indio_dev); + int ret; + u16 tmp; + u8 activity; + bool powered_on; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + switch (chan->type) { + case IIO_STEPS: + /* + * The HW only counts steps and other dependent + * parameters (speed, distance, calories, activity) + * if power is on (from enabling an event or the + * step counter */ + powered_on = + mma9553_is_any_event_enabled(data, false, 0) || + data->stepcnt_enabled; + if (!powered_on) { + dev_err(&data->client->dev, + "No channels enabled\n"); + return -EINVAL; + } + mutex_lock(&data->mutex); + ret = mma9551_read_status_word(data->client, + MMA9551_APPID_PEDOMETER, + MMA9553_REG_STEPCNT, + &tmp); + mutex_unlock(&data->mutex); + if (ret < 0) + return ret; + *val = tmp; + return IIO_VAL_INT; + case IIO_DISTANCE: + powered_on = + mma9553_is_any_event_enabled(data, false, 0) || + data->stepcnt_enabled; + if (!powered_on) { + dev_err(&data->client->dev, + "No channels enabled\n"); + return -EINVAL; + } + mutex_lock(&data->mutex); + ret = mma9551_read_status_word(data->client, + MMA9551_APPID_PEDOMETER, + MMA9553_REG_DISTANCE, + &tmp); + mutex_unlock(&data->mutex); + if (ret < 0) + return ret; + *val = tmp; + return IIO_VAL_INT; + case IIO_ACTIVITY: + powered_on = + mma9553_is_any_event_enabled(data, false, 0) || + data->stepcnt_enabled; + if (!powered_on) { + dev_err(&data->client->dev, + "No channels enabled\n"); + return -EINVAL; + } + mutex_lock(&data->mutex); + ret = mma9551_read_status_word(data->client, + MMA9551_APPID_PEDOMETER, + MMA9553_REG_STATUS, + &tmp); + mutex_unlock(&data->mutex); + if (ret < 0) + return ret; + + activity = + mma9553_get_bits(tmp, MMA9553_MASK_STATUS_ACTIVITY); + + /* + * The device does not support confidence value levels, + * so we will always have 100% for current activity and + * 0% for the others. + */ + if (chan->channel2 == mma9553_activity_to_mod(activity)) + *val = 100; + else + *val = 0; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_VELOCITY: /* m/h */ + if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) + return -EINVAL; + powered_on = + mma9553_is_any_event_enabled(data, false, 0) || + data->stepcnt_enabled; + if (!powered_on) { + dev_err(&data->client->dev, + "No channels enabled\n"); + return -EINVAL; + } + mutex_lock(&data->mutex); + ret = mma9551_read_status_word(data->client, + MMA9551_APPID_PEDOMETER, + MMA9553_REG_SPEED, &tmp); + mutex_unlock(&data->mutex); + if (ret < 0) + return ret; + *val = tmp; + return IIO_VAL_INT; + case IIO_ENERGY: /* Cal or kcal */ + powered_on = + mma9553_is_any_event_enabled(data, false, 0) || + data->stepcnt_enabled; + if (!powered_on) { + dev_err(&data->client->dev, + "No channels enabled\n"); + return -EINVAL; + } + mutex_lock(&data->mutex); + ret = mma9551_read_status_word(data->client, + MMA9551_APPID_PEDOMETER, + MMA9553_REG_CALORIES, + &tmp); + mutex_unlock(&data->mutex); + if (ret < 0) + return ret; + *val = tmp; + return IIO_VAL_INT; + case IIO_ACCEL: + mutex_lock(&data->mutex); + ret = mma9551_read_accel_chan(data->client, + chan, val, val2); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_VELOCITY: /* m/h to m/s */ + if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) + return -EINVAL; + *val = 0; + *val2 = 277; /* 0.000277 */ + return IIO_VAL_INT_PLUS_MICRO; + case IIO_ENERGY: /* Cal or kcal to J */ + *val = 4184; + return IIO_VAL_INT; + case IIO_ACCEL: + return mma9551_read_accel_scale(val, val2); + default: + return -EINVAL; + } + case IIO_CHAN_INFO_ENABLE: + *val = data->stepcnt_enabled; + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBHEIGHT: + tmp = mma9553_get_bits(data->conf.height_weight, + MMA9553_MASK_CONF_HEIGHT); + *val = tmp / 100; /* cm to m */ + *val2 = (tmp % 100) * 10000; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_CALIBWEIGHT: + *val = mma9553_get_bits(data->conf.height_weight, + MMA9553_MASK_CONF_WEIGHT); + return IIO_VAL_INT; + case IIO_CHAN_INFO_DEBOUNCE_COUNT: + switch (chan->type) { + case IIO_STEPS: + *val = mma9553_get_bits(data->conf.filter, + MMA9553_MASK_CONF_FILTSTEP); + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_DEBOUNCE_TIME: + switch (chan->type) { + case IIO_STEPS: + *val = mma9553_get_bits(data->conf.filter, + MMA9553_MASK_CONF_FILTTIME); + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_INT_TIME: + switch (chan->type) { + case IIO_VELOCITY: + if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) + return -EINVAL; + *val = mma9553_get_bits(data->conf.speed_step, + MMA9553_MASK_CONF_SPDPRD); + return IIO_VAL_INT; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int mma9553_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct mma9553_data *data = iio_priv(indio_dev); + int ret, tmp; + + switch (mask) { + case IIO_CHAN_INFO_ENABLE: + if (data->stepcnt_enabled == !!val) + return 0; + mutex_lock(&data->mutex); + ret = mma9551_set_power_state(data->client, val); + if (ret < 0) { + mutex_unlock(&data->mutex); + return ret; + } + data->stepcnt_enabled = val; + mutex_unlock(&data->mutex); + return 0; + case IIO_CHAN_INFO_CALIBHEIGHT: + /* m to cm */ + tmp = val * 100 + val2 / 10000; + if (tmp < 0 || tmp > 255) + return -EINVAL; + mutex_lock(&data->mutex); + ret = mma9553_set_config(data, + MMA9553_REG_CONF_HEIGHT_WEIGHT, + &data->conf.height_weight, + tmp, MMA9553_MASK_CONF_HEIGHT); + mutex_unlock(&data->mutex); + return ret; + case IIO_CHAN_INFO_CALIBWEIGHT: + if (val < 0 || val > 255) + return -EINVAL; + mutex_lock(&data->mutex); + ret = mma9553_set_config(data, + MMA9553_REG_CONF_HEIGHT_WEIGHT, + &data->conf.height_weight, + val, MMA9553_MASK_CONF_WEIGHT); + mutex_unlock(&data->mutex); + return ret; + case IIO_CHAN_INFO_DEBOUNCE_COUNT: + switch (chan->type) { + case IIO_STEPS: + /* + * Set to 0 to disable step filtering. If the value + * specified is greater than 6, then 6 will be used. + */ + if (val < 0) + return -EINVAL; + if (val > 6) + val = 6; + mutex_lock(&data->mutex); + ret = mma9553_set_config(data, MMA9553_REG_CONF_FILTER, + &data->conf.filter, val, + MMA9553_MASK_CONF_FILTSTEP); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_DEBOUNCE_TIME: + switch (chan->type) { + case IIO_STEPS: + if (val < 0 || val > 127) + return -EINVAL; + mutex_lock(&data->mutex); + ret = mma9553_set_config(data, MMA9553_REG_CONF_FILTER, + &data->conf.filter, val, + MMA9553_MASK_CONF_FILTTIME); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_INT_TIME: + switch (chan->type) { + case IIO_VELOCITY: + if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) + return -EINVAL; + /* + * If set to a value greater than 5, then 5 will be + * used. Warning: Do not set SPDPRD to 0 or 1 as + * this may cause undesirable behavior. + */ + if (val < 2) + return -EINVAL; + if (val > 5) + val = 5; + mutex_lock(&data->mutex); + ret = mma9553_set_config(data, + MMA9553_REG_CONF_SPEED_STEP, + &data->conf.speed_step, val, + MMA9553_MASK_CONF_SPDPRD); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int mma9553_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + + struct mma9553_data *data = iio_priv(indio_dev); + struct mma9553_event *event; + + event = mma9553_get_event(data, chan->type, chan->channel2, dir); + if (!event) + return -EINVAL; + + return event->enabled; +} + +static int mma9553_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, int state) +{ + struct mma9553_data *data = iio_priv(indio_dev); + struct mma9553_event *event; + int ret; + + event = mma9553_get_event(data, chan->type, chan->channel2, dir); + if (!event) + return -EINVAL; + + if (event->enabled == state) + return 0; + + mutex_lock(&data->mutex); + + ret = mma9551_set_power_state(data->client, state); + if (ret < 0) + goto err_out; + event->enabled = state; + + ret = mma9553_conf_gpio(data); + if (ret < 0) + goto err_conf_gpio; + + mutex_unlock(&data->mutex); + + return ret; + +err_conf_gpio: + if (state) { + event->enabled = false; + mma9551_set_power_state(data->client, false); + } +err_out: + mutex_unlock(&data->mutex); + return ret; +} + +static int mma9553_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct mma9553_data *data = iio_priv(indio_dev); + + *val2 = 0; + switch (info) { + case IIO_EV_INFO_VALUE: + switch (chan->type) { + case IIO_STEPS: + *val = mma9553_get_bits(data->conf.speed_step, + MMA9553_MASK_CONF_STEPCOALESCE); + return IIO_VAL_INT; + case IIO_ACTIVITY: + /* + * The device does not support confidence value levels. + * We set an average of 50%. + */ + *val = 50; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_EV_INFO_PERIOD: + switch (chan->type) { + case IIO_ACTIVITY: + *val = MMA9553_ACTIVITY_THD_TO_SEC(data->conf.actthd); + return IIO_VAL_INT; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int mma9553_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct mma9553_data *data = iio_priv(indio_dev); + int ret; + + switch (info) { + case IIO_EV_INFO_VALUE: + switch (chan->type) { + case IIO_STEPS: + if (val < 0 || val > 255) + return -EINVAL; + mutex_lock(&data->mutex); + ret = mma9553_set_config(data, + MMA9553_REG_CONF_SPEED_STEP, + &data->conf.speed_step, val, + MMA9553_MASK_CONF_STEPCOALESCE); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } + case IIO_EV_INFO_PERIOD: + switch (chan->type) { + case IIO_ACTIVITY: + mutex_lock(&data->mutex); + ret = mma9553_set_config(data, MMA9553_REG_CONF_ACTTHD, + &data->conf.actthd, + MMA9553_ACTIVITY_SEC_TO_THD + (val), MMA9553_MASK_CONF_WORD); + mutex_unlock(&data->mutex); + return ret; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int mma9553_get_calibgender_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct mma9553_data *data = iio_priv(indio_dev); + u8 gender; + + gender = mma9553_get_bits(data->conf.filter, MMA9553_MASK_CONF_MALE); + /* + * HW expects 0 for female and 1 for male, + * while iio index is 0 for male and 1 for female + */ + return !gender; +} + +static int mma9553_set_calibgender_mode(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + unsigned int mode) +{ + struct mma9553_data *data = iio_priv(indio_dev); + u8 gender = !mode; + int ret; + + if ((mode != 0) && (mode != 1)) + return -EINVAL; + mutex_lock(&data->mutex); + ret = mma9553_set_config(data, MMA9553_REG_CONF_FILTER, + &data->conf.filter, gender, + MMA9553_MASK_CONF_MALE); + mutex_unlock(&data->mutex); + + return ret; +} + +static const struct iio_event_spec mma9553_step_event = { + .type = IIO_EV_TYPE_CHANGE, + .dir = IIO_EV_DIR_NONE, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_VALUE), +}; + +static const struct iio_event_spec mma9553_activity_events[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), + }, + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), + }, +}; + +static const char * const calibgender_modes[] = { "male", "female" }; + +static const struct iio_enum mma9553_calibgender_enum = { + .items = calibgender_modes, + .num_items = ARRAY_SIZE(calibgender_modes), + .get = mma9553_get_calibgender_mode, + .set = mma9553_set_calibgender_mode, +}; + +static const struct iio_chan_spec_ext_info mma9553_ext_info[] = { + IIO_ENUM("calibgender", IIO_SHARED_BY_TYPE, &mma9553_calibgender_enum), + IIO_ENUM_AVAILABLE("calibgender", &mma9553_calibgender_enum), + {}, +}; + +#define MMA9553_PEDOMETER_CHANNEL(_type, _mask) { \ + .type = _type, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_ENABLE) | \ + BIT(IIO_CHAN_INFO_CALIBHEIGHT) | \ + _mask, \ + .ext_info = mma9553_ext_info, \ +} + +#define MMA9553_ACTIVITY_CHANNEL(_chan2) { \ + .type = IIO_ACTIVITY, \ + .modified = 1, \ + .channel2 = _chan2, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBHEIGHT), \ + .event_spec = mma9553_activity_events, \ + .num_event_specs = ARRAY_SIZE(mma9553_activity_events), \ + .ext_info = mma9553_ext_info, \ +} + +static const struct iio_chan_spec mma9553_channels[] = { + MMA9551_ACCEL_CHANNEL(IIO_MOD_X), + MMA9551_ACCEL_CHANNEL(IIO_MOD_Y), + MMA9551_ACCEL_CHANNEL(IIO_MOD_Z), + + { + .type = IIO_STEPS, + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_ENABLE) | + BIT(IIO_CHAN_INFO_DEBOUNCE_COUNT) | + BIT(IIO_CHAN_INFO_DEBOUNCE_TIME), + .event_spec = &mma9553_step_event, + .num_event_specs = 1, + }, + + MMA9553_PEDOMETER_CHANNEL(IIO_DISTANCE, BIT(IIO_CHAN_INFO_PROCESSED)), + { + .type = IIO_VELOCITY, + .modified = 1, + .channel2 = IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_INT_TIME) | + BIT(IIO_CHAN_INFO_ENABLE), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBHEIGHT), + .ext_info = mma9553_ext_info, + }, + MMA9553_PEDOMETER_CHANNEL(IIO_ENERGY, BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_CALIBWEIGHT)), + + MMA9553_ACTIVITY_CHANNEL(IIO_MOD_RUNNING), + MMA9553_ACTIVITY_CHANNEL(IIO_MOD_JOGGING), + MMA9553_ACTIVITY_CHANNEL(IIO_MOD_WALKING), + MMA9553_ACTIVITY_CHANNEL(IIO_MOD_STILL), +}; + +static const struct iio_info mma9553_info = { + .driver_module = THIS_MODULE, + .read_raw = mma9553_read_raw, + .write_raw = mma9553_write_raw, + .read_event_config = mma9553_read_event_config, + .write_event_config = mma9553_write_event_config, + .read_event_value = mma9553_read_event_value, + .write_event_value = mma9553_write_event_value, +}; + +static irqreturn_t mma9553_irq_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct mma9553_data *data = iio_priv(indio_dev); + + data->timestamp = iio_get_time_ns(); + /* + * Since we only configure the interrupt pin when an + * event is enabled, we are sure we have at least + * one event enabled at this point. + */ + return IRQ_WAKE_THREAD; +} + +static irqreturn_t mma9553_event_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct mma9553_data *data = iio_priv(indio_dev); + u16 stepcnt; + u8 activity; + struct mma9553_event *ev_activity, *ev_prev_activity, *ev_step_detect; + int ret; + + mutex_lock(&data->mutex); + ret = mma9553_read_activity_stepcnt(data, &activity, &stepcnt); + if (ret < 0) { + mutex_unlock(&data->mutex); + return IRQ_HANDLED; + } + + ev_prev_activity = + mma9553_get_event(data, IIO_ACTIVITY, + mma9553_activity_to_mod(data->activity), + IIO_EV_DIR_FALLING); + ev_activity = + mma9553_get_event(data, IIO_ACTIVITY, + mma9553_activity_to_mod(activity), + IIO_EV_DIR_RISING); + ev_step_detect = + mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD, IIO_EV_DIR_NONE); + + if (ev_step_detect->enabled && (stepcnt != data->stepcnt)) { + data->stepcnt = stepcnt; + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD, + IIO_EV_DIR_NONE, IIO_EV_TYPE_CHANGE, 0, 0, 0), + data->timestamp); + } + + if (activity != data->activity) { + data->activity = activity; + /* ev_activity can be NULL if activity == ACTIVITY_UNKNOWN */ + if (ev_prev_activity && ev_prev_activity->enabled) + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_ACTIVITY, 0, + ev_prev_activity->info->mod, + IIO_EV_DIR_FALLING, + IIO_EV_TYPE_THRESH, 0, 0, 0), + data->timestamp); + + if (ev_activity && ev_activity->enabled) + iio_push_event(indio_dev, + IIO_EVENT_CODE(IIO_ACTIVITY, 0, + ev_activity->info->mod, + IIO_EV_DIR_RISING, + IIO_EV_TYPE_THRESH, 0, 0, 0), + data->timestamp); + } + mutex_unlock(&data->mutex); + + return IRQ_HANDLED; +} + +static int mma9553_gpio_probe(struct i2c_client *client) +{ + struct device *dev; + struct gpio_desc *gpio; + int ret; + + if (!client) + return -EINVAL; + + dev = &client->dev; + + /* data ready gpio interrupt pin */ + gpio = devm_gpiod_get_index(dev, MMA9553_GPIO_NAME, 0); + if (IS_ERR(gpio)) { + dev_err(dev, "acpi gpio get index failed\n"); + return PTR_ERR(gpio); + } + + ret = gpiod_direction_input(gpio); + if (ret) + return ret; + + ret = gpiod_to_irq(gpio); + + dev_dbg(dev, "gpio resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); + + return ret; +} + +static const char *mma9553_match_acpi_device(struct device *dev) +{ + const struct acpi_device_id *id; + + id = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!id) + return NULL; + + return dev_name(dev); +} + +static int mma9553_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct mma9553_data *data; + struct iio_dev *indio_dev; + const char *name = NULL; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + + if (id) + name = id->name; + else if (ACPI_HANDLE(&client->dev)) + name = mma9553_match_acpi_device(&client->dev); + else + return -ENOSYS; + + mutex_init(&data->mutex); + mma9553_init_events(data); + + ret = mma9553_init(data); + if (ret < 0) + return ret; + + indio_dev->dev.parent = &client->dev; + indio_dev->channels = mma9553_channels; + indio_dev->num_channels = ARRAY_SIZE(mma9553_channels); + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &mma9553_info; + + if (client->irq < 0) + client->irq = mma9553_gpio_probe(client); + + if (client->irq >= 0) { + ret = devm_request_threaded_irq(&client->dev, client->irq, + mma9553_irq_handler, + mma9553_event_handler, + IRQF_TRIGGER_RISING, + MMA9553_IRQ_NAME, indio_dev); + if (ret < 0) { + dev_err(&client->dev, "request irq %d failed\n", + client->irq); + goto out_poweroff; + } + + } + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "unable to register iio device\n"); + goto out_poweroff; + } + + ret = pm_runtime_set_active(&client->dev); + if (ret < 0) + goto out_iio_unregister; + + pm_runtime_enable(&client->dev); + pm_runtime_set_autosuspend_delay(&client->dev, + MMA9551_AUTO_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&client->dev); + + dev_dbg(&indio_dev->dev, "Registered device %s\n", name); + + return 0; + +out_iio_unregister: + iio_device_unregister(indio_dev); +out_poweroff: + mma9551_set_device_state(client, false); + return ret; +} + +static int mma9553_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct mma9553_data *data = iio_priv(indio_dev); + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + + iio_device_unregister(indio_dev); + mutex_lock(&data->mutex); + mma9551_set_device_state(data->client, false); + mutex_unlock(&data->mutex); + + return 0; +} + +#ifdef CONFIG_PM +static int mma9553_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma9553_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + ret = mma9551_set_device_state(data->client, false); + mutex_unlock(&data->mutex); + if (ret < 0) { + dev_err(&data->client->dev, "powering off device failed\n"); + return -EAGAIN; + } + + return 0; +} + +static int mma9553_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma9553_data *data = iio_priv(indio_dev); + int ret; + + ret = mma9551_set_device_state(data->client, true); + if (ret < 0) + return ret; + + mma9551_sleep(MMA9553_DEFAULT_SAMPLE_RATE); + + return 0; +} +#endif + +#ifdef CONFIG_PM_SLEEP +static int mma9553_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma9553_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + ret = mma9551_set_device_state(data->client, false); + mutex_unlock(&data->mutex); + + return ret; +} + +static int mma9553_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct mma9553_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->mutex); + ret = mma9551_set_device_state(data->client, true); + mutex_unlock(&data->mutex); + + return ret; +} +#endif + +static const struct dev_pm_ops mma9553_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(mma9553_suspend, mma9553_resume) + SET_RUNTIME_PM_OPS(mma9553_runtime_suspend, + mma9553_runtime_resume, NULL) +}; + +static const struct acpi_device_id mma9553_acpi_match[] = { + {"MMA9553", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(acpi, mma9553_acpi_match); + +static const struct i2c_device_id mma9553_id[] = { + {"mma9553", 0}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, mma9553_id); + +static struct i2c_driver mma9553_driver = { + .driver = { + .name = MMA9553_DRV_NAME, + .acpi_match_table = ACPI_PTR(mma9553_acpi_match), + .pm = &mma9553_pm_ops, + }, + .probe = mma9553_probe, + .remove = mma9553_remove, + .id_table = mma9553_id, +}; + +module_i2c_driver(mma9553_driver); + +MODULE_AUTHOR("Irina Tirdea "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MMA9553L pedometer platform driver"); -- cgit v0.10.2 From 67460e8c9a5c59f66e1d476fd9341086cd792e5a Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 31 Jan 2015 09:41:14 +0000 Subject: iio:common:ssp_sensors fix warnings due to 32 bit instead of 64 bit passed to do_div Also change to div64_u64 in one place to avoid loss of precision (was dividing a 32 bit number by a 64 bit number, but casting this to 64 bit divided by 32 bit) Those divide functions certainly have esoteric naming! Fixes warnings with asm-generic/div64.h do_div such as: In file included from drivers/iio/common/ssp_sensors/ssp_iio.c:20:0: drivers/iio/common/ssp_sensors/ssp_iio_sensor.h: In function 'ssp_convert_to_freq': >> drivers/iio/common/ssp_sensors/ssp_iio_sensor.h:56:16: warning: comparison of distinct pointer types lacks a cast [enabled by default] drivers/iio/common/ssp_sensors/ssp_iio_sensor.h:56:2: warning: right shift count >= width of type [enabled by default] >> drivers/iio/common/ssp_sensors/ssp_iio_sensor.h:56:2: warning: passing argument 1 of '__div64_32' from incompatible pointer type [enabled by default] include/asm-generic/div64.h:35:17: note: expected 'uint64_t *' but argument is of type 'int *' drivers/iio/common/ssp_sensors/ssp_iio.c: In function 'ssp_common_process_data': include/linux/iio/buffer.h:142:32: warning: 'calculated_time' may be used uninitialized in this function [-Wuninitialized] drivers/iio/common/ssp_sensors/ssp_iio.c:83:10: note: 'calculated_time' was declared here Fixed by using straight coded version as per the description in the div64.h header, thus ensuring no issue with 32 bit integers. Reported-by: kbuild test robot Signed-off-by: Jonathan Cameron diff --git a/drivers/iio/common/ssp_sensors/ssp_iio_sensor.h b/drivers/iio/common/ssp_sensors/ssp_iio_sensor.h index dda267c..541c659 100644 --- a/drivers/iio/common/ssp_sensors/ssp_iio_sensor.h +++ b/drivers/iio/common/ssp_sensors/ssp_iio_sensor.h @@ -30,7 +30,7 @@ } #define SSP_MS_PER_S 1000 -#define SSP_INVERTED_SCALING_FACTOR 1000000ULL +#define SSP_INVERTED_SCALING_FACTOR 1000000U #define SSP_FACTOR_WITH_MS \ (SSP_INVERTED_SCALING_FACTOR * SSP_MS_PER_S) @@ -53,7 +53,8 @@ static inline void ssp_convert_to_freq(u32 time, int *integer_part, } *integer_part = SSP_FACTOR_WITH_MS / time; - *fractional = do_div(*integer_part, SSP_INVERTED_SCALING_FACTOR); + *fractional = *integer_part % SSP_INVERTED_SCALING_FACTOR; + *integer_part = *integer_part / SSP_INVERTED_SCALING_FACTOR; } /* Converts frequency to time in ms */ @@ -61,10 +62,10 @@ static inline int ssp_convert_to_time(int integer_part, int fractional) { u64 value; - value = integer_part * SSP_INVERTED_SCALING_FACTOR + fractional; + value = (u64)integer_part * SSP_INVERTED_SCALING_FACTOR + fractional; if (value == 0) return 0; - return div_u64(SSP_FACTOR_WITH_MS, value); + return div64_u64((u64)SSP_FACTOR_WITH_MS, value); } #endif /* __SSP_IIO_SENSOR_H__ */ -- cgit v0.10.2 From 2cbf7fe2d5d32a4747c1f8ad163e886dccad930c Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 3 Feb 2015 13:18:55 +0000 Subject: i2o: move to staging The I2O layer deals with a technology that to say the least didn't catch on in the market. The only relevant products are some of the AMI MegaRAID - which supported I2O and its native mode (The native mode is faster and runs on Linux), an obscure crypto ethernet card that's now so many years out of date nobody would use it, the old DPT controllers, which speak their own dialect and have their own driver - and ermm.. thats about it. We also know the code isn't in good shape as recently a patch was proposed and queried as buggy, which in turn showed the existing code was broken already by prior "clean up" and nobody had noticed that either. It's coding style robot code nothing more. Like some forgotten corridor cleaned relentlessly by a lost Roomba but where no user has trodden in years. Move it to staging and then to /dev/null. The headers remain as they are shared with dpt_i2o. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/Kconfig b/drivers/Kconfig index c70d6e4..c0cc96b 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -36,8 +36,6 @@ source "drivers/message/fusion/Kconfig" source "drivers/firewire/Kconfig" -source "drivers/message/i2o/Kconfig" - source "drivers/macintosh/Kconfig" source "drivers/net/Kconfig" diff --git a/drivers/message/Makefile b/drivers/message/Makefile index 97ef5a0..755676d 100644 --- a/drivers/message/Makefile +++ b/drivers/message/Makefile @@ -2,5 +2,4 @@ # Makefile for MPT based block devices # -obj-$(CONFIG_I2O) += i2o/ obj-$(CONFIG_FUSION) += fusion/ diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig deleted file mode 100644 index 5afa0e3..0000000 --- a/drivers/message/i2o/Kconfig +++ /dev/null @@ -1,121 +0,0 @@ - -menuconfig I2O - tristate "I2O device support" - depends on PCI - ---help--- - The Intelligent Input/Output (I2O) architecture allows hardware - drivers to be split into two parts: an operating system specific - module called the OSM and an hardware specific module called the - HDM. The OSM can talk to a whole range of HDM's, and ideally the - HDM's are not OS dependent. This allows for the same HDM driver to - be used under different operating systems if the relevant OSM is in - place. In order for this to work, you need to have an I2O interface - adapter card in your computer. This card contains a special I/O - processor (IOP), thus allowing high speeds since the CPU does not - have to deal with I/O. - - If you say Y here, you will get a choice of interface adapter - drivers and OSM's with the following questions. - - To compile this support as a module, choose M here: the - modules will be called i2o_core. - - If unsure, say N. - -if I2O - -config I2O_LCT_NOTIFY_ON_CHANGES - bool "Enable LCT notification" - default y - ---help--- - Only say N here if you have a I2O controller from SUN. The SUN - firmware doesn't support LCT notification on changes. If this option - is enabled on such a controller the driver will hang up in a endless - loop. On all other controllers say Y. - - If unsure, say Y. - -config I2O_EXT_ADAPTEC - bool "Enable Adaptec extensions" - default y - ---help--- - Say Y for support of raidutils for Adaptec I2O controllers. You also - have to say Y to "I2O Configuration support", "I2O SCSI OSM" below - and to "SCSI generic support" under "SCSI device configuration". - -config I2O_EXT_ADAPTEC_DMA64 - bool "Enable 64-bit DMA" - depends on I2O_EXT_ADAPTEC && ( 64BIT || HIGHMEM64G ) - default y - ---help--- - Say Y for support of 64-bit DMA transfer mode on Adaptec I2O - controllers. - Note: You need at least firmware version 3709. - -config I2O_CONFIG - tristate "I2O Configuration support" - depends on VIRT_TO_BUS - ---help--- - Say Y for support of the configuration interface for the I2O adapters. - If you have a RAID controller from Adaptec and you want to use the - raidutils to manage your RAID array, you have to say Y here. - - To compile this support as a module, choose M here: the - module will be called i2o_config. - - Note: If you want to use the new API you have to download the - i2o_config patch from http://i2o.shadowconnect.com/ - -config I2O_CONFIG_OLD_IOCTL - bool "Enable ioctls (OBSOLETE)" - depends on I2O_CONFIG - default y - ---help--- - Enables old ioctls. - -config I2O_BUS - tristate "I2O Bus Adapter OSM" - ---help--- - Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM - provides access to the busses on the I2O controller. The main purpose - is to rescan the bus to find new devices. - - To compile this support as a module, choose M here: the - module will be called i2o_bus. - -config I2O_BLOCK - tristate "I2O Block OSM" - depends on BLOCK - ---help--- - Include support for the I2O Block OSM. The Block OSM presents disk - and other structured block devices to the operating system. If you - are using an RAID controller, you could access the array only by - the Block OSM driver. But it is possible to access the single disks - by the SCSI OSM driver, for example to monitor the disks. - - To compile this support as a module, choose M here: the - module will be called i2o_block. - -config I2O_SCSI - tristate "I2O SCSI OSM" - depends on SCSI - ---help--- - Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel - I2O controller. You can use both the SCSI and Block OSM together if - you wish. To access a RAID array, you must use the Block OSM driver. - But you could use the SCSI OSM driver to monitor the single disks. - - To compile this support as a module, choose M here: the - module will be called i2o_scsi. - -config I2O_PROC - tristate "I2O /proc support" - ---help--- - If you say Y here and to "/proc file system support", you will be - able to read I2O related information from the virtual directory - /proc/i2o. - - To compile this support as a module, choose M here: the - module will be called i2o_proc. - -endif # I2O diff --git a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile deleted file mode 100644 index b0982da..0000000 --- a/drivers/message/i2o/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# -# Makefile for the kernel I2O OSM. -# -# Note : at this point, these files are compiled on all systems. -# In the future, some of these should be built conditionally. -# - -i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o memory.o -i2o_bus-y += bus-osm.o -i2o_config-y += config-osm.o -obj-$(CONFIG_I2O) += i2o_core.o -obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o -obj-$(CONFIG_I2O_BUS) += i2o_bus.o -obj-$(CONFIG_I2O_BLOCK) += i2o_block.o -obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o -obj-$(CONFIG_I2O_PROC) += i2o_proc.o diff --git a/drivers/message/i2o/README b/drivers/message/i2o/README deleted file mode 100644 index f072a8e..0000000 --- a/drivers/message/i2o/README +++ /dev/null @@ -1,98 +0,0 @@ - - Linux I2O Support (c) Copyright 1999 Red Hat Software - and others. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version - 2 of the License, or (at your option) any later version. - -AUTHORS (so far) - -Alan Cox, Building Number Three Ltd. - Core code, SCSI and Block OSMs - -Steve Ralston, LSI Logic Corp. - Debugging SCSI and Block OSM - -Deepak Saxena, Intel Corp. - Various core/block extensions - /proc interface, bug fixes - Ioctl interfaces for control - Debugging LAN OSM - -Philip Rumpf - Fixed assorted dumb SMP locking bugs - -Juha Sievanen, University of Helsinki Finland - LAN OSM code - /proc interface to LAN class - Bug fixes - Core code extensions - -Auvo Häkkinen, University of Helsinki Finland - LAN OSM code - /Proc interface to LAN class - Bug fixes - Core code extensions - -Taneli Vähäkangas, University of Helsinki Finland - Fixes to i2o_config - -CREDITS - - This work was made possible by - -Red Hat Software - Funding for the Building #3 part of the project - -Symbios Logic (Now LSI) - Host adapters, hints, known to work platforms when I hit - compatibility problems - -BoxHill Corporation - Loan of initial FibreChannel disk array used for development work. - -European Commission - Funding the work done by the University of Helsinki - -SysKonnect - Loan of FDDI and Gigabit Ethernet cards - -ASUSTeK - Loan of I2O motherboard - -STATUS: - -o The core setup works within limits. -o The scsi layer seems to almost work. - I'm still chasing down the hang bug. -o The block OSM is mostly functional -o LAN OSM works with FDDI and Ethernet cards. - -TO DO: - -General: -o Provide hidden address space if asked -o Long term message flow control -o PCI IOP's without interrupts are not supported yet -o Push FAIL handling into the core -o DDM control interfaces for module load etc -o Add I2O 2.0 support (Deffered to 2.5 kernel) - -Block: -o Multiple major numbers -o Read ahead and cache handling stuff. Talk to Ingo and people -o Power management -o Finish Media changers - -SCSI: -o Find the right way to associate drives/luns/busses - -Lan: -o Performance tuning -o Test Fibre Channel code - -Tape: -o Anyone seen anything implementing this ? - (D.S: Will attempt to do so if spare cycles permit) diff --git a/drivers/message/i2o/README.ioctl b/drivers/message/i2o/README.ioctl deleted file mode 100644 index 4a7d2eb..0000000 --- a/drivers/message/i2o/README.ioctl +++ /dev/null @@ -1,394 +0,0 @@ - -Linux I2O User Space Interface -rev 0.3 - 04/20/99 - -============================================================================= -Originally written by Deepak Saxena(deepak@plexity.net) -Currently maintained by Deepak Saxena(deepak@plexity.net) -============================================================================= - -I. Introduction - -The Linux I2O subsystem provides a set of ioctl() commands that can be -utilized by user space applications to communicate with IOPs and devices -on individual IOPs. This document defines the specific ioctl() commands -that are available to the user and provides examples of their uses. - -This document assumes the reader is familiar with or has access to the -I2O specification as no I2O message parameters are outlined. For information -on the specification, see http://www.i2osig.org - -This document and the I2O user space interface are currently maintained -by Deepak Saxena. Please send all comments, errata, and bug fixes to -deepak@csociety.purdue.edu - -II. IOP Access - -Access to the I2O subsystem is provided through the device file named -/dev/i2o/ctl. This file is a character file with major number 10 and minor -number 166. It can be created through the following command: - - mknod /dev/i2o/ctl c 10 166 - -III. Determining the IOP Count - - SYNOPSIS - - ioctl(fd, I2OGETIOPS, int *count); - - u8 count[MAX_I2O_CONTROLLERS]; - - DESCRIPTION - - This function returns the system's active IOP table. count should - point to a buffer containing MAX_I2O_CONTROLLERS entries. Upon - returning, each entry will contain a non-zero value if the given - IOP unit is active, and NULL if it is inactive or non-existent. - - RETURN VALUE. - - Returns 0 if no errors occur, and -1 otherwise. If an error occurs, - errno is set appropriately: - - EFAULT Invalid user space pointer was passed - -IV. Getting Hardware Resource Table - - SYNOPSIS - - ioctl(fd, I2OHRTGET, struct i2o_cmd_hrt *hrt); - - struct i2o_cmd_hrtlct - { - u32 iop; /* IOP unit number */ - void *resbuf; /* Buffer for result */ - u32 *reslen; /* Buffer length in bytes */ - }; - - DESCRIPTION - - This function returns the Hardware Resource Table of the IOP specified - by hrt->iop in the buffer pointed to by hrt->resbuf. The actual size of - the data is written into *(hrt->reslen). - - RETURNS - - This function returns 0 if no errors occur. If an error occurs, -1 - is returned and errno is set appropriately: - - EFAULT Invalid user space pointer was passed - ENXIO Invalid IOP number - ENOBUFS Buffer not large enough. If this occurs, the required - buffer length is written into *(hrt->reslen) - -V. Getting Logical Configuration Table - - SYNOPSIS - - ioctl(fd, I2OLCTGET, struct i2o_cmd_lct *lct); - - struct i2o_cmd_hrtlct - { - u32 iop; /* IOP unit number */ - void *resbuf; /* Buffer for result */ - u32 *reslen; /* Buffer length in bytes */ - }; - - DESCRIPTION - - This function returns the Logical Configuration Table of the IOP specified - by lct->iop in the buffer pointed to by lct->resbuf. The actual size of - the data is written into *(lct->reslen). - - RETURNS - - This function returns 0 if no errors occur. If an error occurs, -1 - is returned and errno is set appropriately: - - EFAULT Invalid user space pointer was passed - ENXIO Invalid IOP number - ENOBUFS Buffer not large enough. If this occurs, the required - buffer length is written into *(lct->reslen) - -VI. Setting Parameters - - SYNOPSIS - - ioctl(fd, I2OPARMSET, struct i2o_parm_setget *ops); - - struct i2o_cmd_psetget - { - u32 iop; /* IOP unit number */ - u32 tid; /* Target device TID */ - void *opbuf; /* Operation List buffer */ - u32 oplen; /* Operation List buffer length in bytes */ - void *resbuf; /* Result List buffer */ - u32 *reslen; /* Result List buffer length in bytes */ - }; - - DESCRIPTION - - This function posts a UtilParamsSet message to the device identified - by ops->iop and ops->tid. The operation list for the message is - sent through the ops->opbuf buffer, and the result list is written - into the buffer pointed to by ops->resbuf. The number of bytes - written is placed into *(ops->reslen). - - RETURNS - - The return value is the size in bytes of the data written into - ops->resbuf if no errors occur. If an error occurs, -1 is returned - and errno is set appropriately: - - EFAULT Invalid user space pointer was passed - ENXIO Invalid IOP number - ENOBUFS Buffer not large enough. If this occurs, the required - buffer length is written into *(ops->reslen) - ETIMEDOUT Timeout waiting for reply message - ENOMEM Kernel memory allocation error - - A return value of 0 does not mean that the value was actually - changed properly on the IOP. The user should check the result - list to determine the specific status of the transaction. - -VII. Getting Parameters - - SYNOPSIS - - ioctl(fd, I2OPARMGET, struct i2o_parm_setget *ops); - - struct i2o_parm_setget - { - u32 iop; /* IOP unit number */ - u32 tid; /* Target device TID */ - void *opbuf; /* Operation List buffer */ - u32 oplen; /* Operation List buffer length in bytes */ - void *resbuf; /* Result List buffer */ - u32 *reslen; /* Result List buffer length in bytes */ - }; - - DESCRIPTION - - This function posts a UtilParamsGet message to the device identified - by ops->iop and ops->tid. The operation list for the message is - sent through the ops->opbuf buffer, and the result list is written - into the buffer pointed to by ops->resbuf. The actual size of data - written is placed into *(ops->reslen). - - RETURNS - - EFAULT Invalid user space pointer was passed - ENXIO Invalid IOP number - ENOBUFS Buffer not large enough. If this occurs, the required - buffer length is written into *(ops->reslen) - ETIMEDOUT Timeout waiting for reply message - ENOMEM Kernel memory allocation error - - A return value of 0 does not mean that the value was actually - properly retrieved. The user should check the result list - to determine the specific status of the transaction. - -VIII. Downloading Software - - SYNOPSIS - - ioctl(fd, I2OSWDL, struct i2o_sw_xfer *sw); - - struct i2o_sw_xfer - { - u32 iop; /* IOP unit number */ - u8 flags; /* DownloadFlags field */ - u8 sw_type; /* Software type */ - u32 sw_id; /* Software ID */ - void *buf; /* Pointer to software buffer */ - u32 *swlen; /* Length of software buffer */ - u32 *maxfrag; /* Number of fragments */ - u32 *curfrag; /* Current fragment number */ - }; - - DESCRIPTION - - This function downloads a software fragment pointed by sw->buf - to the iop identified by sw->iop. The DownloadFlags, SwID, SwType - and SwSize fields of the ExecSwDownload message are filled in with - the values of sw->flags, sw->sw_id, sw->sw_type and *(sw->swlen). - - The fragments _must_ be sent in order and be 8K in size. The last - fragment _may_ be shorter, however. The kernel will compute its - size based on information in the sw->swlen field. - - Please note that SW transfers can take a long time. - - RETURNS - - This function returns 0 no errors occur. If an error occurs, -1 - is returned and errno is set appropriately: - - EFAULT Invalid user space pointer was passed - ENXIO Invalid IOP number - ETIMEDOUT Timeout waiting for reply message - ENOMEM Kernel memory allocation error - -IX. Uploading Software - - SYNOPSIS - - ioctl(fd, I2OSWUL, struct i2o_sw_xfer *sw); - - struct i2o_sw_xfer - { - u32 iop; /* IOP unit number */ - u8 flags; /* UploadFlags */ - u8 sw_type; /* Software type */ - u32 sw_id; /* Software ID */ - void *buf; /* Pointer to software buffer */ - u32 *swlen; /* Length of software buffer */ - u32 *maxfrag; /* Number of fragments */ - u32 *curfrag; /* Current fragment number */ - }; - - DESCRIPTION - - This function uploads a software fragment from the IOP identified - by sw->iop, sw->sw_type, sw->sw_id and optionally sw->swlen fields. - The UploadFlags, SwID, SwType and SwSize fields of the ExecSwUpload - message are filled in with the values of sw->flags, sw->sw_id, - sw->sw_type and *(sw->swlen). - - The fragments _must_ be requested in order and be 8K in size. The - user is responsible for allocating memory pointed by sw->buf. The - last fragment _may_ be shorter. - - Please note that SW transfers can take a long time. - - RETURNS - - This function returns 0 if no errors occur. If an error occurs, -1 - is returned and errno is set appropriately: - - EFAULT Invalid user space pointer was passed - ENXIO Invalid IOP number - ETIMEDOUT Timeout waiting for reply message - ENOMEM Kernel memory allocation error - -X. Removing Software - - SYNOPSIS - - ioctl(fd, I2OSWDEL, struct i2o_sw_xfer *sw); - - struct i2o_sw_xfer - { - u32 iop; /* IOP unit number */ - u8 flags; /* RemoveFlags */ - u8 sw_type; /* Software type */ - u32 sw_id; /* Software ID */ - void *buf; /* Unused */ - u32 *swlen; /* Length of the software data */ - u32 *maxfrag; /* Unused */ - u32 *curfrag; /* Unused */ - }; - - DESCRIPTION - - This function removes software from the IOP identified by sw->iop. - The RemoveFlags, SwID, SwType and SwSize fields of the ExecSwRemove message - are filled in with the values of sw->flags, sw->sw_id, sw->sw_type and - *(sw->swlen). Give zero in *(sw->len) if the value is unknown. IOP uses - *(sw->swlen) value to verify correct identication of the module to remove. - The actual size of the module is written into *(sw->swlen). - - RETURNS - - This function returns 0 if no errors occur. If an error occurs, -1 - is returned and errno is set appropriately: - - EFAULT Invalid user space pointer was passed - ENXIO Invalid IOP number - ETIMEDOUT Timeout waiting for reply message - ENOMEM Kernel memory allocation error - -X. Validating Configuration - - SYNOPSIS - - ioctl(fd, I2OVALIDATE, int *iop); - u32 iop; - - DESCRIPTION - - This function posts an ExecConfigValidate message to the controller - identified by iop. This message indicates that the current - configuration is accepted. The iop changes the status of suspect drivers - to valid and may delete old drivers from its store. - - RETURNS - - This function returns 0 if no erro occur. If an error occurs, -1 is - returned and errno is set appropriately: - - ETIMEDOUT Timeout waiting for reply message - ENXIO Invalid IOP number - -XI. Configuration Dialog - - SYNOPSIS - - ioctl(fd, I2OHTML, struct i2o_html *htquery); - struct i2o_html - { - u32 iop; /* IOP unit number */ - u32 tid; /* Target device ID */ - u32 page; /* HTML page */ - void *resbuf; /* Buffer for reply HTML page */ - u32 *reslen; /* Length in bytes of reply buffer */ - void *qbuf; /* Pointer to HTTP query string */ - u32 qlen; /* Length in bytes of query string buffer */ - }; - - DESCRIPTION - - This function posts an UtilConfigDialog message to the device identified - by htquery->iop and htquery->tid. The requested HTML page number is - provided by the htquery->page field, and the resultant data is stored - in the buffer pointed to by htquery->resbuf. If there is an HTTP query - string that is to be sent to the device, it should be sent in the buffer - pointed to by htquery->qbuf. If there is no query string, this field - should be set to NULL. The actual size of the reply received is written - into *(htquery->reslen). - - RETURNS - - This function returns 0 if no error occur. If an error occurs, -1 - is returned and errno is set appropriately: - - EFAULT Invalid user space pointer was passed - ENXIO Invalid IOP number - ENOBUFS Buffer not large enough. If this occurs, the required - buffer length is written into *(ops->reslen) - ETIMEDOUT Timeout waiting for reply message - ENOMEM Kernel memory allocation error - -XII. Events - - In the process of determining this. Current idea is to have use - the select() interface to allow user apps to periodically poll - the /dev/i2o/ctl device for events. When select() notifies the user - that an event is available, the user would call read() to retrieve - a list of all the events that are pending for the specific device. - -============================================================================= -Revision History -============================================================================= - -Rev 0.1 - 04/01/99 -- Initial revision - -Rev 0.2 - 04/06/99 -- Changed return values to match UNIX ioctl() standard. Only return values - are 0 and -1. All errors are reported through errno. -- Added summary of proposed possible event interfaces - -Rev 0.3 - 04/20/99 -- Changed all ioctls() to use pointers to user data instead of actual data -- Updated error values to match the code diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c deleted file mode 100644 index c463dc2..0000000 --- a/drivers/message/i2o/bus-osm.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Bus Adapter OSM - * - * Copyright (C) 2005 Markus Lidel - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * Fixes/additions: - * Markus Lidel - * initial version. - */ - -#include -#include - -#define OSM_NAME "bus-osm" -#define OSM_VERSION "1.317" -#define OSM_DESCRIPTION "I2O Bus Adapter OSM" - -static struct i2o_driver i2o_bus_driver; - -/* Bus OSM class handling definition */ -static struct i2o_class_id i2o_bus_class_id[] = { - {I2O_CLASS_BUS_ADAPTER}, - {I2O_CLASS_END} -}; - -/** - * i2o_bus_scan - Scan the bus for new devices - * @dev: I2O device of the bus, which should be scanned - * - * Scans the bus dev for new / removed devices. After the scan a new LCT - * will be fetched automatically. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_bus_scan(struct i2o_device *dev) -{ - struct i2o_message *msg; - - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return -ETIMEDOUT; - - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data. - tid); - - return i2o_msg_post_wait(dev->iop, msg, 60); -}; - -/** - * i2o_bus_store_scan - Scan the I2O Bus Adapter - * @d: device which should be scanned - * @attr: device_attribute - * @buf: output buffer - * @count: buffer size - * - * Returns count. - */ -static ssize_t i2o_bus_store_scan(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2o_device *i2o_dev = to_i2o_device(d); - int rc; - - if ((rc = i2o_bus_scan(i2o_dev))) - osm_warn("bus scan failed %d\n", rc); - - return count; -} - -/* Bus Adapter OSM device attributes */ -static DEVICE_ATTR(scan, S_IWUSR, NULL, i2o_bus_store_scan); - -/** - * i2o_bus_probe - verify if dev is a I2O Bus Adapter device and install it - * @dev: device to verify if it is a I2O Bus Adapter device - * - * Because we want all Bus Adapters always return 0. - * Except when we fail. Then we are sad. - * - * Returns 0, except when we fail to excel. - */ -static int i2o_bus_probe(struct device *dev) -{ - struct i2o_device *i2o_dev = to_i2o_device(get_device(dev)); - int rc; - - rc = device_create_file(dev, &dev_attr_scan); - if (rc) - goto err_out; - - osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid); - - return 0; - -err_out: - put_device(dev); - return rc; -}; - -/** - * i2o_bus_remove - remove the I2O Bus Adapter device from the system again - * @dev: I2O Bus Adapter device which should be removed - * - * Always returns 0. - */ -static int i2o_bus_remove(struct device *dev) -{ - struct i2o_device *i2o_dev = to_i2o_device(dev); - - device_remove_file(dev, &dev_attr_scan); - - put_device(dev); - - osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid); - - return 0; -}; - -/* Bus Adapter OSM driver struct */ -static struct i2o_driver i2o_bus_driver = { - .name = OSM_NAME, - .classes = i2o_bus_class_id, - .driver = { - .probe = i2o_bus_probe, - .remove = i2o_bus_remove, - }, -}; - -/** - * i2o_bus_init - Bus Adapter OSM initialization function - * - * Only register the Bus Adapter OSM in the I2O core. - * - * Returns 0 on success or negative error code on failure. - */ -static int __init i2o_bus_init(void) -{ - int rc; - - printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); - - /* Register Bus Adapter OSM into I2O core */ - rc = i2o_driver_register(&i2o_bus_driver); - if (rc) { - osm_err("Could not register Bus Adapter OSM\n"); - return rc; - } - - return 0; -}; - -/** - * i2o_bus_exit - Bus Adapter OSM exit function - * - * Unregisters Bus Adapter OSM from I2O core. - */ -static void __exit i2o_bus_exit(void) -{ - i2o_driver_unregister(&i2o_bus_driver); -}; - -MODULE_AUTHOR("Markus Lidel "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(OSM_DESCRIPTION); -MODULE_VERSION(OSM_VERSION); - -module_init(i2o_bus_init); -module_exit(i2o_bus_exit); diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c deleted file mode 100644 index 3bba7aa..0000000 --- a/drivers/message/i2o/config-osm.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Configuration OSM - * - * Copyright (C) 2005 Markus Lidel - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * Fixes/additions: - * Markus Lidel - * initial version. - */ - -#include -#include -#include -#include -#include - -#include - -#define OSM_NAME "config-osm" -#define OSM_VERSION "1.323" -#define OSM_DESCRIPTION "I2O Configuration OSM" - -/* access mode user rw */ -#define S_IWRSR (S_IRUSR | S_IWUSR) - -static struct i2o_driver i2o_config_driver; - -/* Config OSM driver struct */ -static struct i2o_driver i2o_config_driver = { - .name = OSM_NAME, -}; - -#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL -#include "i2o_config.c" -#endif - -/** - * i2o_config_init - Configuration OSM initialization function - * - * Registers Configuration OSM in the I2O core and if old ioctl's are - * compiled in initialize them. - * - * Returns 0 on success or negative error code on failure. - */ -static int __init i2o_config_init(void) -{ - printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); - - if (i2o_driver_register(&i2o_config_driver)) { - osm_err("handler register failed.\n"); - return -EBUSY; - } -#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL - if (i2o_config_old_init()) { - osm_err("old config handler initialization failed\n"); - i2o_driver_unregister(&i2o_config_driver); - return -EBUSY; - } -#endif - - return 0; -} - -/** - * i2o_config_exit - Configuration OSM exit function - * - * If old ioctl's are compiled in exit remove them and unregisters - * Configuration OSM from I2O core. - */ -static void i2o_config_exit(void) -{ -#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL - i2o_config_old_exit(); -#endif - - i2o_driver_unregister(&i2o_config_driver); -} - -MODULE_AUTHOR("Markus Lidel "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(OSM_DESCRIPTION); -MODULE_VERSION(OSM_VERSION); - -module_init(i2o_config_init); -module_exit(i2o_config_exit); diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h deleted file mode 100644 index 91614f1..0000000 --- a/drivers/message/i2o/core.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * I2O core internal declarations - * - * Copyright (C) 2005 Markus Lidel - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * Fixes/additions: - * Markus Lidel - * initial version. - */ - -/* Exec-OSM */ -extern struct i2o_driver i2o_exec_driver; -extern int i2o_exec_lct_get(struct i2o_controller *); - -extern int __init i2o_exec_init(void); -extern void i2o_exec_exit(void); - -/* driver */ -extern struct bus_type i2o_bus_type; - -extern int i2o_driver_dispatch(struct i2o_controller *, u32); - -extern int __init i2o_driver_init(void); -extern void i2o_driver_exit(void); - -/* PCI */ -extern int __init i2o_pci_init(void); -extern void __exit i2o_pci_exit(void); - -/* device */ -extern const struct attribute_group *i2o_device_groups[]; - -extern void i2o_device_remove(struct i2o_device *); -extern int i2o_device_parse_lct(struct i2o_controller *); - -int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, - int oplen, void *reslist, int reslen); - -/* IOP */ -extern struct i2o_controller *i2o_iop_alloc(void); - -/** - * i2o_iop_free - Free the i2o_controller struct - * @c: I2O controller to free - */ -static inline void i2o_iop_free(struct i2o_controller *c) -{ - i2o_pool_free(&c->in_msg); - kfree(c); -} - -extern int i2o_iop_add(struct i2o_controller *); -extern void i2o_iop_remove(struct i2o_controller *); - -/* control registers relative to c->base */ -#define I2O_IRQ_STATUS 0x30 -#define I2O_IRQ_MASK 0x34 -#define I2O_IN_PORT 0x40 -#define I2O_OUT_PORT 0x44 - -/* Motorola/Freescale specific register offset */ -#define I2O_MOTOROLA_PORT_OFFSET 0x10400 - -#define I2O_IRQ_OUTBOUND_POST 0x00000008 diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c deleted file mode 100644 index ce62d8b..0000000 --- a/drivers/message/i2o/debug.c +++ /dev/null @@ -1,472 +0,0 @@ -#include -#include -#include -#include - -static void i2o_report_util_cmd(u8 cmd); -static void i2o_report_exec_cmd(u8 cmd); -static void i2o_report_fail_status(u8 req_status, u32 * msg); -static void i2o_report_common_status(u8 req_status); -static void i2o_report_common_dsc(u16 detailed_status); - -/* - * Used for error reporting/debugging purposes. - * Report Cmd name, Request status, Detailed Status. - */ -void i2o_report_status(const char *severity, const char *str, - struct i2o_message *m) -{ - u32 *msg = (u32 *) m; - u8 cmd = (msg[1] >> 24) & 0xFF; - u8 req_status = (msg[4] >> 24) & 0xFF; - u16 detailed_status = msg[4] & 0xFFFF; - - if (cmd == I2O_CMD_UTIL_EVT_REGISTER) - return; // No status in this reply - - printk("%s%s: ", severity, str); - - if (cmd < 0x1F) // Utility cmd - i2o_report_util_cmd(cmd); - - else if (cmd >= 0xA0 && cmd <= 0xEF) // Executive cmd - i2o_report_exec_cmd(cmd); - else - printk("Cmd = %0#2x, ", cmd); // Other cmds - - if (msg[0] & MSG_FAIL) { - i2o_report_fail_status(req_status, msg); - return; - } - - i2o_report_common_status(req_status); - - if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF)) - i2o_report_common_dsc(detailed_status); - else - printk(" / DetailedStatus = %0#4x.\n", - detailed_status); -} - -/* Used to dump a message to syslog during debugging */ -void i2o_dump_message(struct i2o_message *m) -{ -#ifdef DEBUG - u32 *msg = (u32 *) m; - int i; - printk(KERN_INFO "Dumping I2O message size %d @ %p\n", - msg[0] >> 16 & 0xffff, msg); - for (i = 0; i < ((msg[0] >> 16) & 0xffff); i++) - printk(KERN_INFO " msg[%d] = %0#10x\n", i, msg[i]); -#endif -} - -/* - * Used for error reporting/debugging purposes. - * Following fail status are common to all classes. - * The preserved message must be handled in the reply handler. - */ -static void i2o_report_fail_status(u8 req_status, u32 * msg) -{ - static char *FAIL_STATUS[] = { - "0x80", /* not used */ - "SERVICE_SUSPENDED", /* 0x81 */ - "SERVICE_TERMINATED", /* 0x82 */ - "CONGESTION", - "FAILURE", - "STATE_ERROR", - "TIME_OUT", - "ROUTING_FAILURE", - "INVALID_VERSION", - "INVALID_OFFSET", - "INVALID_MSG_FLAGS", - "FRAME_TOO_SMALL", - "FRAME_TOO_LARGE", - "INVALID_TARGET_ID", - "INVALID_INITIATOR_ID", - "INVALID_INITIATOR_CONTEX", /* 0x8F */ - "UNKNOWN_FAILURE" /* 0xFF */ - }; - - if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE) - printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n", - req_status); - else - printk("TRANSPORT_%s.\n", - FAIL_STATUS[req_status & 0x0F]); - - /* Dump some details */ - - printk(KERN_ERR " InitiatorId = %d, TargetId = %d\n", - (msg[1] >> 12) & 0xFFF, msg[1] & 0xFFF); - printk(KERN_ERR " LowestVersion = 0x%02X, HighestVersion = 0x%02X\n", - (msg[4] >> 8) & 0xFF, msg[4] & 0xFF); - printk(KERN_ERR " FailingHostUnit = 0x%04X, FailingIOP = 0x%03X\n", - msg[5] >> 16, msg[5] & 0xFFF); - - printk(KERN_ERR " Severity: 0x%02X\n", (msg[4] >> 16) & 0xFF); - if (msg[4] & (1 << 16)) - printk(KERN_DEBUG "(FormatError), " - "this msg can never be delivered/processed.\n"); - if (msg[4] & (1 << 17)) - printk(KERN_DEBUG "(PathError), " - "this msg can no longer be delivered/processed.\n"); - if (msg[4] & (1 << 18)) - printk(KERN_DEBUG "(PathState), " - "the system state does not allow delivery.\n"); - if (msg[4] & (1 << 19)) - printk(KERN_DEBUG - "(Congestion), resources temporarily not available;" - "do not retry immediately.\n"); -} - -/* - * Used for error reporting/debugging purposes. - * Following reply status are common to all classes. - */ -static void i2o_report_common_status(u8 req_status) -{ - static char *REPLY_STATUS[] = { - "SUCCESS", - "ABORT_DIRTY", - "ABORT_NO_DATA_TRANSFER", - "ABORT_PARTIAL_TRANSFER", - "ERROR_DIRTY", - "ERROR_NO_DATA_TRANSFER", - "ERROR_PARTIAL_TRANSFER", - "PROCESS_ABORT_DIRTY", - "PROCESS_ABORT_NO_DATA_TRANSFER", - "PROCESS_ABORT_PARTIAL_TRANSFER", - "TRANSACTION_ERROR", - "PROGRESS_REPORT" - }; - - if (req_status >= ARRAY_SIZE(REPLY_STATUS)) - printk("RequestStatus = %0#2x", req_status); - else - printk("%s", REPLY_STATUS[req_status]); -} - -/* - * Used for error reporting/debugging purposes. - * Following detailed status are valid for executive class, - * utility class, DDM class and for transaction error replies. - */ -static void i2o_report_common_dsc(u16 detailed_status) -{ - static char *COMMON_DSC[] = { - "SUCCESS", - "0x01", // not used - "BAD_KEY", - "TCL_ERROR", - "REPLY_BUFFER_FULL", - "NO_SUCH_PAGE", - "INSUFFICIENT_RESOURCE_SOFT", - "INSUFFICIENT_RESOURCE_HARD", - "0x08", // not used - "CHAIN_BUFFER_TOO_LARGE", - "UNSUPPORTED_FUNCTION", - "DEVICE_LOCKED", - "DEVICE_RESET", - "INAPPROPRIATE_FUNCTION", - "INVALID_INITIATOR_ADDRESS", - "INVALID_MESSAGE_FLAGS", - "INVALID_OFFSET", - "INVALID_PARAMETER", - "INVALID_REQUEST", - "INVALID_TARGET_ADDRESS", - "MESSAGE_TOO_LARGE", - "MESSAGE_TOO_SMALL", - "MISSING_PARAMETER", - "TIMEOUT", - "UNKNOWN_ERROR", - "UNKNOWN_FUNCTION", - "UNSUPPORTED_VERSION", - "DEVICE_BUSY", - "DEVICE_NOT_AVAILABLE" - }; - - if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE) - printk(" / DetailedStatus = %0#4x.\n", - detailed_status); - else - printk(" / %s.\n", COMMON_DSC[detailed_status]); -} - -/* - * Used for error reporting/debugging purposes - */ -static void i2o_report_util_cmd(u8 cmd) -{ - switch (cmd) { - case I2O_CMD_UTIL_NOP: - printk("UTIL_NOP, "); - break; - case I2O_CMD_UTIL_ABORT: - printk("UTIL_ABORT, "); - break; - case I2O_CMD_UTIL_CLAIM: - printk("UTIL_CLAIM, "); - break; - case I2O_CMD_UTIL_RELEASE: - printk("UTIL_CLAIM_RELEASE, "); - break; - case I2O_CMD_UTIL_CONFIG_DIALOG: - printk("UTIL_CONFIG_DIALOG, "); - break; - case I2O_CMD_UTIL_DEVICE_RESERVE: - printk("UTIL_DEVICE_RESERVE, "); - break; - case I2O_CMD_UTIL_DEVICE_RELEASE: - printk("UTIL_DEVICE_RELEASE, "); - break; - case I2O_CMD_UTIL_EVT_ACK: - printk("UTIL_EVENT_ACKNOWLEDGE, "); - break; - case I2O_CMD_UTIL_EVT_REGISTER: - printk("UTIL_EVENT_REGISTER, "); - break; - case I2O_CMD_UTIL_LOCK: - printk("UTIL_LOCK, "); - break; - case I2O_CMD_UTIL_LOCK_RELEASE: - printk("UTIL_LOCK_RELEASE, "); - break; - case I2O_CMD_UTIL_PARAMS_GET: - printk("UTIL_PARAMS_GET, "); - break; - case I2O_CMD_UTIL_PARAMS_SET: - printk("UTIL_PARAMS_SET, "); - break; - case I2O_CMD_UTIL_REPLY_FAULT_NOTIFY: - printk("UTIL_REPLY_FAULT_NOTIFY, "); - break; - default: - printk("Cmd = %0#2x, ", cmd); - } -} - -/* - * Used for error reporting/debugging purposes - */ -static void i2o_report_exec_cmd(u8 cmd) -{ - switch (cmd) { - case I2O_CMD_ADAPTER_ASSIGN: - printk("EXEC_ADAPTER_ASSIGN, "); - break; - case I2O_CMD_ADAPTER_READ: - printk("EXEC_ADAPTER_READ, "); - break; - case I2O_CMD_ADAPTER_RELEASE: - printk("EXEC_ADAPTER_RELEASE, "); - break; - case I2O_CMD_BIOS_INFO_SET: - printk("EXEC_BIOS_INFO_SET, "); - break; - case I2O_CMD_BOOT_DEVICE_SET: - printk("EXEC_BOOT_DEVICE_SET, "); - break; - case I2O_CMD_CONFIG_VALIDATE: - printk("EXEC_CONFIG_VALIDATE, "); - break; - case I2O_CMD_CONN_SETUP: - printk("EXEC_CONN_SETUP, "); - break; - case I2O_CMD_DDM_DESTROY: - printk("EXEC_DDM_DESTROY, "); - break; - case I2O_CMD_DDM_ENABLE: - printk("EXEC_DDM_ENABLE, "); - break; - case I2O_CMD_DDM_QUIESCE: - printk("EXEC_DDM_QUIESCE, "); - break; - case I2O_CMD_DDM_RESET: - printk("EXEC_DDM_RESET, "); - break; - case I2O_CMD_DDM_SUSPEND: - printk("EXEC_DDM_SUSPEND, "); - break; - case I2O_CMD_DEVICE_ASSIGN: - printk("EXEC_DEVICE_ASSIGN, "); - break; - case I2O_CMD_DEVICE_RELEASE: - printk("EXEC_DEVICE_RELEASE, "); - break; - case I2O_CMD_HRT_GET: - printk("EXEC_HRT_GET, "); - break; - case I2O_CMD_ADAPTER_CLEAR: - printk("EXEC_IOP_CLEAR, "); - break; - case I2O_CMD_ADAPTER_CONNECT: - printk("EXEC_IOP_CONNECT, "); - break; - case I2O_CMD_ADAPTER_RESET: - printk("EXEC_IOP_RESET, "); - break; - case I2O_CMD_LCT_NOTIFY: - printk("EXEC_LCT_NOTIFY, "); - break; - case I2O_CMD_OUTBOUND_INIT: - printk("EXEC_OUTBOUND_INIT, "); - break; - case I2O_CMD_PATH_ENABLE: - printk("EXEC_PATH_ENABLE, "); - break; - case I2O_CMD_PATH_QUIESCE: - printk("EXEC_PATH_QUIESCE, "); - break; - case I2O_CMD_PATH_RESET: - printk("EXEC_PATH_RESET, "); - break; - case I2O_CMD_STATIC_MF_CREATE: - printk("EXEC_STATIC_MF_CREATE, "); - break; - case I2O_CMD_STATIC_MF_RELEASE: - printk("EXEC_STATIC_MF_RELEASE, "); - break; - case I2O_CMD_STATUS_GET: - printk("EXEC_STATUS_GET, "); - break; - case I2O_CMD_SW_DOWNLOAD: - printk("EXEC_SW_DOWNLOAD, "); - break; - case I2O_CMD_SW_UPLOAD: - printk("EXEC_SW_UPLOAD, "); - break; - case I2O_CMD_SW_REMOVE: - printk("EXEC_SW_REMOVE, "); - break; - case I2O_CMD_SYS_ENABLE: - printk("EXEC_SYS_ENABLE, "); - break; - case I2O_CMD_SYS_MODIFY: - printk("EXEC_SYS_MODIFY, "); - break; - case I2O_CMD_SYS_QUIESCE: - printk("EXEC_SYS_QUIESCE, "); - break; - case I2O_CMD_SYS_TAB_SET: - printk("EXEC_SYS_TAB_SET, "); - break; - default: - printk("Cmd = %#02x, ", cmd); - } -} - -void i2o_debug_state(struct i2o_controller *c) -{ - printk(KERN_INFO "%s: State = ", c->name); - switch (((i2o_status_block *) c->status_block.virt)->iop_state) { - case 0x01: - printk("INIT\n"); - break; - case 0x02: - printk("RESET\n"); - break; - case 0x04: - printk("HOLD\n"); - break; - case 0x05: - printk("READY\n"); - break; - case 0x08: - printk("OPERATIONAL\n"); - break; - case 0x10: - printk("FAILED\n"); - break; - case 0x11: - printk("FAULTED\n"); - break; - default: - printk("%x (unknown !!)\n", - ((i2o_status_block *) c->status_block.virt)->iop_state); - } -}; - -void i2o_dump_hrt(struct i2o_controller *c) -{ - u32 *rows = (u32 *) c->hrt.virt; - u8 *p = (u8 *) c->hrt.virt; - u8 *d; - int count; - int length; - int i; - int state; - - if (p[3] != 0) { - printk(KERN_ERR - "%s: HRT table for controller is too new a version.\n", - c->name); - return; - } - - count = p[0] | (p[1] << 8); - length = p[2]; - - printk(KERN_INFO "%s: HRT has %d entries of %d bytes each.\n", - c->name, count, length << 2); - - rows += 2; - - for (i = 0; i < count; i++) { - printk(KERN_INFO "Adapter %08X: ", rows[0]); - p = (u8 *) (rows + 1); - d = (u8 *) (rows + 2); - state = p[1] << 8 | p[0]; - - printk("TID %04X:[", state & 0xFFF); - state >>= 12; - if (state & (1 << 0)) - printk("H"); /* Hidden */ - if (state & (1 << 2)) { - printk("P"); /* Present */ - if (state & (1 << 1)) - printk("C"); /* Controlled */ - } - if (state > 9) - printk("*"); /* Hard */ - - printk("]:"); - - switch (p[3] & 0xFFFF) { - case 0: - /* Adapter private bus - easy */ - printk("Local bus %d: I/O at 0x%04X Mem 0x%08X", p[2], - d[1] << 8 | d[0], *(u32 *) (d + 4)); - break; - case 1: - /* ISA bus */ - printk("ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", p[2], - d[2], d[1] << 8 | d[0], *(u32 *) (d + 4)); - break; - - case 2: /* EISA bus */ - printk("EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X", - p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); - break; - - case 3: /* MCA bus */ - printk("MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2], - d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); - break; - - case 4: /* PCI bus */ - printk("PCI %d: Bus %d Device %d Function %d", p[2], - d[2], d[1], d[0]); - break; - - case 0x80: /* Other */ - default: - printk("Unsupported bus type."); - break; - } - printk("\n"); - rows += length; - } -} - -EXPORT_SYMBOL(i2o_dump_message); diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c deleted file mode 100644 index 98348f4..0000000 --- a/drivers/message/i2o/device.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - * Functions to handle I2O devices - * - * Copyright (C) 2004 Markus Lidel - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * Fixes/additions: - * Markus Lidel - * initial version. - */ - -#include -#include -#include -#include -#include -#include "core.h" - -/** - * i2o_device_issue_claim - claim or release a device - * @dev: I2O device to claim or release - * @cmd: claim or release command - * @type: type of claim - * - * Issue I2O UTIL_CLAIM or UTIL_RELEASE messages. The message to be sent - * is set by cmd. dev is the I2O device which should be claim or - * released and the type is the claim type (see the I2O spec). - * - * Returs 0 on success or negative error code on failure. - */ -static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, - u32 type) -{ - struct i2o_message *msg; - - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid); - msg->body[0] = cpu_to_le32(type); - - return i2o_msg_post_wait(dev->iop, msg, 60); -} - -/** - * i2o_device_claim - claim a device for use by an OSM - * @dev: I2O device to claim - * - * Do the leg work to assign a device to a given OSM. If the claim succeeds, - * the owner is the primary. If the attempt fails a negative errno code - * is returned. On success zero is returned. - */ -int i2o_device_claim(struct i2o_device *dev) -{ - int rc = 0; - - mutex_lock(&dev->lock); - - rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY); - if (!rc) - pr_debug("i2o: claim of device %d succeeded\n", - dev->lct_data.tid); - else - pr_debug("i2o: claim of device %d failed %d\n", - dev->lct_data.tid, rc); - - mutex_unlock(&dev->lock); - - return rc; -} - -/** - * i2o_device_claim_release - release a device that the OSM is using - * @dev: device to release - * - * Drop a claim by an OSM on a given I2O device. - * - * AC - some devices seem to want to refuse an unclaim until they have - * finished internal processing. It makes sense since you don't want a - * new device to go reconfiguring the entire system until you are done. - * Thus we are prepared to wait briefly. - * - * Returns 0 on success or negative error code on failure. - */ -int i2o_device_claim_release(struct i2o_device *dev) -{ - int tries; - int rc = 0; - - mutex_lock(&dev->lock); - - /* - * If the controller takes a nonblocking approach to - * releases we have to sleep/poll for a few times. - */ - for (tries = 0; tries < 10; tries++) { - rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_RELEASE, - I2O_CLAIM_PRIMARY); - if (!rc) - break; - - ssleep(1); - } - - if (!rc) - pr_debug("i2o: claim release of device %d succeeded\n", - dev->lct_data.tid); - else - pr_debug("i2o: claim release of device %d failed %d\n", - dev->lct_data.tid, rc); - - mutex_unlock(&dev->lock); - - return rc; -} - -/** - * i2o_device_release - release the memory for a I2O device - * @dev: I2O device which should be released - * - * Release the allocated memory. This function is called if refcount of - * device reaches 0 automatically. - */ -static void i2o_device_release(struct device *dev) -{ - struct i2o_device *i2o_dev = to_i2o_device(dev); - - pr_debug("i2o: device %s released\n", dev_name(dev)); - - kfree(i2o_dev); -} - -/** - * class_id_show - Displays class id of I2O device - * @dev: device of which the class id should be displayed - * @attr: pointer to device attribute - * @buf: buffer into which the class id should be printed - * - * Returns the number of bytes which are printed into the buffer. - */ -static ssize_t class_id_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct i2o_device *i2o_dev = to_i2o_device(dev); - - sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id); - return strlen(buf) + 1; -} -static DEVICE_ATTR_RO(class_id); - -/** - * tid_show - Displays TID of I2O device - * @dev: device of which the TID should be displayed - * @attr: pointer to device attribute - * @buf: buffer into which the TID should be printed - * - * Returns the number of bytes which are printed into the buffer. - */ -static ssize_t tid_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct i2o_device *i2o_dev = to_i2o_device(dev); - - sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid); - return strlen(buf) + 1; -} -static DEVICE_ATTR_RO(tid); - -/* I2O device attributes */ -static struct attribute *i2o_device_attrs[] = { - &dev_attr_class_id.attr, - &dev_attr_tid.attr, - NULL, -}; - -static const struct attribute_group i2o_device_group = { - .attrs = i2o_device_attrs, -}; - -const struct attribute_group *i2o_device_groups[] = { - &i2o_device_group, - NULL, -}; - -/** - * i2o_device_alloc - Allocate a I2O device and initialize it - * - * Allocate the memory for a I2O device and initialize locks and lists - * - * Returns the allocated I2O device or a negative error code if the device - * could not be allocated. - */ -static struct i2o_device *i2o_device_alloc(void) -{ - struct i2o_device *dev; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return ERR_PTR(-ENOMEM); - - INIT_LIST_HEAD(&dev->list); - mutex_init(&dev->lock); - - dev->device.bus = &i2o_bus_type; - dev->device.release = &i2o_device_release; - - return dev; -} - -/** - * i2o_device_add - allocate a new I2O device and add it to the IOP - * @c: I2O controller that the device is on - * @entry: LCT entry of the I2O device - * - * Allocate a new I2O device and initialize it with the LCT entry. The - * device is appended to the device list of the controller. - * - * Returns zero on success, or a -ve errno. - */ -static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry) -{ - struct i2o_device *i2o_dev, *tmp; - int rc; - - i2o_dev = i2o_device_alloc(); - if (IS_ERR(i2o_dev)) { - printk(KERN_ERR "i2o: unable to allocate i2o device\n"); - return PTR_ERR(i2o_dev); - } - - i2o_dev->lct_data = *entry; - - dev_set_name(&i2o_dev->device, "%d:%03x", c->unit, - i2o_dev->lct_data.tid); - - i2o_dev->iop = c; - i2o_dev->device.parent = &c->device; - - rc = device_register(&i2o_dev->device); - if (rc) - goto err; - - list_add_tail(&i2o_dev->list, &c->devices); - - /* create user entries for this device */ - tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); - if (tmp && (tmp != i2o_dev)) { - rc = sysfs_create_link(&i2o_dev->device.kobj, - &tmp->device.kobj, "user"); - if (rc) - goto unreg_dev; - } - - /* create user entries referring to this device */ - list_for_each_entry(tmp, &c->devices, list) - if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) - && (tmp != i2o_dev)) { - rc = sysfs_create_link(&tmp->device.kobj, - &i2o_dev->device.kobj, "user"); - if (rc) - goto rmlink1; - } - - /* create parent entries for this device */ - tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); - if (tmp && (tmp != i2o_dev)) { - rc = sysfs_create_link(&i2o_dev->device.kobj, - &tmp->device.kobj, "parent"); - if (rc) - goto rmlink1; - } - - /* create parent entries referring to this device */ - list_for_each_entry(tmp, &c->devices, list) - if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) - && (tmp != i2o_dev)) { - rc = sysfs_create_link(&tmp->device.kobj, - &i2o_dev->device.kobj, "parent"); - if (rc) - goto rmlink2; - } - - i2o_driver_notify_device_add_all(i2o_dev); - - pr_debug("i2o: device %s added\n", dev_name(&i2o_dev->device)); - - return 0; - -rmlink2: - /* If link creating failed halfway, we loop whole list to cleanup. - * And we don't care wrong removing of link, because sysfs_remove_link - * will take care of it. - */ - list_for_each_entry(tmp, &c->devices, list) { - if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) - sysfs_remove_link(&tmp->device.kobj, "parent"); - } - sysfs_remove_link(&i2o_dev->device.kobj, "parent"); -rmlink1: - list_for_each_entry(tmp, &c->devices, list) - if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) - sysfs_remove_link(&tmp->device.kobj, "user"); - sysfs_remove_link(&i2o_dev->device.kobj, "user"); -unreg_dev: - list_del(&i2o_dev->list); - device_unregister(&i2o_dev->device); -err: - kfree(i2o_dev); - return rc; -} - -/** - * i2o_device_remove - remove an I2O device from the I2O core - * @i2o_dev: I2O device which should be released - * - * Is used on I2O controller removal or LCT modification, when the device - * is removed from the system. Note that the device could still hang - * around until the refcount reaches 0. - */ -void i2o_device_remove(struct i2o_device *i2o_dev) -{ - struct i2o_device *tmp; - struct i2o_controller *c = i2o_dev->iop; - - i2o_driver_notify_device_remove_all(i2o_dev); - - sysfs_remove_link(&i2o_dev->device.kobj, "parent"); - sysfs_remove_link(&i2o_dev->device.kobj, "user"); - - list_for_each_entry(tmp, &c->devices, list) { - if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) - sysfs_remove_link(&tmp->device.kobj, "parent"); - if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) - sysfs_remove_link(&tmp->device.kobj, "user"); - } - list_del(&i2o_dev->list); - - device_unregister(&i2o_dev->device); -} - -/** - * i2o_device_parse_lct - Parse a previously fetched LCT and create devices - * @c: I2O controller from which the LCT should be parsed. - * - * The Logical Configuration Table tells us what we can talk to on the - * board. For every entry we create an I2O device, which is registered in - * the I2O core. - * - * Returns 0 on success or negative error code on failure. - */ -int i2o_device_parse_lct(struct i2o_controller *c) -{ - struct i2o_device *dev, *tmp; - i2o_lct *lct; - u32 *dlct = c->dlct.virt; - int max = 0, i = 0; - u16 table_size; - u32 buf; - - mutex_lock(&c->lct_lock); - - kfree(c->lct); - - buf = le32_to_cpu(*dlct++); - table_size = buf & 0xffff; - - lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL); - if (!lct) { - mutex_unlock(&c->lct_lock); - return -ENOMEM; - } - - lct->lct_ver = buf >> 28; - lct->boot_tid = buf >> 16 & 0xfff; - lct->table_size = table_size; - lct->change_ind = le32_to_cpu(*dlct++); - lct->iop_flags = le32_to_cpu(*dlct++); - - table_size -= 3; - - pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max, - lct->table_size); - - while (table_size > 0) { - i2o_lct_entry *entry = &lct->lct_entry[max]; - int found = 0; - - buf = le32_to_cpu(*dlct++); - entry->entry_size = buf & 0xffff; - entry->tid = buf >> 16 & 0xfff; - - entry->change_ind = le32_to_cpu(*dlct++); - entry->device_flags = le32_to_cpu(*dlct++); - - buf = le32_to_cpu(*dlct++); - entry->class_id = buf & 0xfff; - entry->version = buf >> 12 & 0xf; - entry->vendor_id = buf >> 16; - - entry->sub_class = le32_to_cpu(*dlct++); - - buf = le32_to_cpu(*dlct++); - entry->user_tid = buf & 0xfff; - entry->parent_tid = buf >> 12 & 0xfff; - entry->bios_info = buf >> 24; - - memcpy(&entry->identity_tag, dlct, 8); - dlct += 2; - - entry->event_capabilities = le32_to_cpu(*dlct++); - - /* add new devices, which are new in the LCT */ - list_for_each_entry_safe(dev, tmp, &c->devices, list) { - if (entry->tid == dev->lct_data.tid) { - found = 1; - break; - } - } - - if (!found) - i2o_device_add(c, entry); - - table_size -= 9; - max++; - } - - /* remove devices, which are not in the LCT anymore */ - list_for_each_entry_safe(dev, tmp, &c->devices, list) { - int found = 0; - - for (i = 0; i < max; i++) { - if (lct->lct_entry[i].tid == dev->lct_data.tid) { - found = 1; - break; - } - } - - if (!found) - i2o_device_remove(dev); - } - - mutex_unlock(&c->lct_lock); - - return 0; -} - -/* - * Run time support routines - */ - -/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET - * - * This function can be used for all UtilParamsGet/Set operations. - * The OperationList is given in oplist-buffer, - * and results are returned in reslist-buffer. - * Note that the minimum sized reslist is 8 bytes and contains - * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. - */ -int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, - int oplen, void *reslist, int reslen) -{ - struct i2o_message *msg; - int i = 0; - int rc; - struct i2o_dma res; - struct i2o_controller *c = i2o_dev->iop; - struct device *dev = &c->pdev->dev; - - res.virt = NULL; - - if (i2o_dma_alloc(dev, &res, reslen)) - return -ENOMEM; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) { - i2o_dma_free(dev, &res); - return PTR_ERR(msg); - } - - i = 0; - msg->u.head[1] = - cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid); - msg->body[i++] = cpu_to_le32(0x00000000); - msg->body[i++] = cpu_to_le32(0x4C000000 | oplen); /* OperationList */ - memcpy(&msg->body[i], oplist, oplen); - i += (oplen / 4 + (oplen % 4 ? 1 : 0)); - msg->body[i++] = cpu_to_le32(0xD0000000 | res.len); /* ResultList */ - msg->body[i++] = cpu_to_le32(res.phys); - - msg->u.head[0] = - cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) | - SGL_OFFSET_5); - - rc = i2o_msg_post_wait_mem(c, msg, 10, &res); - - /* This only looks like a memory leak - don't "fix" it. */ - if (rc == -ETIMEDOUT) - return rc; - - memcpy(reslist, res.virt, res.len); - i2o_dma_free(dev, &res); - - return rc; -} - -/* - * Query one field group value or a whole scalar group. - */ -int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, - void *buf, int buflen) -{ - u32 opblk[] = { cpu_to_le32(0x00000001), - cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET), - cpu_to_le32((s16) field << 16 | 0x00000001) - }; - u8 *resblk; /* 8 bytes for header */ - int rc; - - resblk = kmalloc(buflen + 8, GFP_KERNEL); - if (!resblk) - return -ENOMEM; - - rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, - sizeof(opblk), resblk, buflen + 8); - - memcpy(buf, resblk + 8, buflen); /* cut off header */ - - kfree(resblk); - - return rc; -} - -/* - * if oper == I2O_PARAMS_TABLE_GET, get from all rows - * if fieldcount == -1 return all fields - * ibuf and ibuflen are unused (use NULL, 0) - * else return specific fields - * ibuf contains fieldindexes - * - * if oper == I2O_PARAMS_LIST_GET, get from specific rows - * if fieldcount == -1 return all fields - * ibuf contains rowcount, keyvalues - * else return specific fields - * fieldcount is # of fieldindexes - * ibuf contains fieldindexes, rowcount, keyvalues - * - * You could also use directly function i2o_issue_params(). - */ -int i2o_parm_table_get(struct i2o_device *dev, int oper, int group, - int fieldcount, void *ibuf, int ibuflen, void *resblk, - int reslen) -{ - u16 *opblk; - int size; - - size = 10 + ibuflen; - if (size % 4) - size += 4 - size % 4; - - opblk = kmalloc(size, GFP_KERNEL); - if (opblk == NULL) { - printk(KERN_ERR "i2o: no memory for query buffer.\n"); - return -ENOMEM; - } - - opblk[0] = 1; /* operation count */ - opblk[1] = 0; /* pad */ - opblk[2] = oper; - opblk[3] = group; - opblk[4] = fieldcount; - memcpy(opblk + 5, ibuf, ibuflen); /* other params */ - - size = i2o_parm_issue(dev, I2O_CMD_UTIL_PARAMS_GET, opblk, - size, resblk, reslen); - - kfree(opblk); - if (size > reslen) - return reslen; - - return size; -} - -EXPORT_SYMBOL(i2o_device_claim); -EXPORT_SYMBOL(i2o_device_claim_release); -EXPORT_SYMBOL(i2o_parm_field_get); -EXPORT_SYMBOL(i2o_parm_table_get); -EXPORT_SYMBOL(i2o_parm_issue); diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c deleted file mode 100644 index 1b18a0d..0000000 --- a/drivers/message/i2o/driver.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Functions to handle I2O drivers (OSMs) and I2O bus type for sysfs - * - * Copyright (C) 2004 Markus Lidel - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * Fixes/additions: - * Markus Lidel - * initial version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "core.h" - -#define OSM_NAME "i2o" - -/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ -static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; -module_param_named(max_drivers, i2o_max_drivers, uint, 0); -MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); - -/* I2O drivers lock and array */ -static spinlock_t i2o_drivers_lock; -static struct i2o_driver **i2o_drivers; - -/** - * i2o_bus_match - Tell if I2O device class id matches the class ids of the I2O driver (OSM) - * @dev: device which should be verified - * @drv: the driver to match against - * - * Used by the bus to check if the driver wants to handle the device. - * - * Returns 1 if the class ids of the driver match the class id of the - * device, otherwise 0. - */ -static int i2o_bus_match(struct device *dev, struct device_driver *drv) -{ - struct i2o_device *i2o_dev = to_i2o_device(dev); - struct i2o_driver *i2o_drv = to_i2o_driver(drv); - struct i2o_class_id *ids = i2o_drv->classes; - - if (ids) - while (ids->class_id != I2O_CLASS_END) { - if (ids->class_id == i2o_dev->lct_data.class_id) - return 1; - ids++; - } - return 0; -}; - -/* I2O bus type */ -struct bus_type i2o_bus_type = { - .name = "i2o", - .match = i2o_bus_match, - .dev_groups = i2o_device_groups, -}; - -/** - * i2o_driver_register - Register a I2O driver (OSM) in the I2O core - * @drv: I2O driver which should be registered - * - * Registers the OSM drv in the I2O core and creates an event queues if - * necessary. - * - * Returns 0 on success or negative error code on failure. - */ -int i2o_driver_register(struct i2o_driver *drv) -{ - struct i2o_controller *c; - int i; - int rc = 0; - unsigned long flags; - - osm_debug("Register driver %s\n", drv->name); - - if (drv->event) { - drv->event_queue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, - drv->name); - if (!drv->event_queue) { - osm_err("Could not initialize event queue for driver " - "%s\n", drv->name); - return -EFAULT; - } - osm_debug("Event queue initialized for driver %s\n", drv->name); - } else - drv->event_queue = NULL; - - drv->driver.name = drv->name; - drv->driver.bus = &i2o_bus_type; - - spin_lock_irqsave(&i2o_drivers_lock, flags); - - for (i = 0; i2o_drivers[i]; i++) - if (i >= i2o_max_drivers) { - osm_err("too many drivers registered, increase " - "max_drivers\n"); - spin_unlock_irqrestore(&i2o_drivers_lock, flags); - rc = -EFAULT; - goto out; - } - - drv->context = i; - i2o_drivers[i] = drv; - - spin_unlock_irqrestore(&i2o_drivers_lock, flags); - - osm_debug("driver %s gets context id %d\n", drv->name, drv->context); - - list_for_each_entry(c, &i2o_controllers, list) { - struct i2o_device *i2o_dev; - - i2o_driver_notify_controller_add(drv, c); - list_for_each_entry(i2o_dev, &c->devices, list) - i2o_driver_notify_device_add(drv, i2o_dev); - } - - rc = driver_register(&drv->driver); - if (rc) - goto out; - - return 0; -out: - if (drv->event_queue) { - destroy_workqueue(drv->event_queue); - drv->event_queue = NULL; - } - - return rc; -}; - -/** - * i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core - * @drv: I2O driver which should be unregistered - * - * Unregisters the OSM drv from the I2O core and cleanup event queues if - * necessary. - */ -void i2o_driver_unregister(struct i2o_driver *drv) -{ - struct i2o_controller *c; - unsigned long flags; - - osm_debug("unregister driver %s\n", drv->name); - - driver_unregister(&drv->driver); - - list_for_each_entry(c, &i2o_controllers, list) { - struct i2o_device *i2o_dev; - - list_for_each_entry(i2o_dev, &c->devices, list) - i2o_driver_notify_device_remove(drv, i2o_dev); - - i2o_driver_notify_controller_remove(drv, c); - } - - spin_lock_irqsave(&i2o_drivers_lock, flags); - i2o_drivers[drv->context] = NULL; - spin_unlock_irqrestore(&i2o_drivers_lock, flags); - - if (drv->event_queue) { - destroy_workqueue(drv->event_queue); - drv->event_queue = NULL; - osm_debug("event queue removed for %s\n", drv->name); - } -}; - -/** - * i2o_driver_dispatch - dispatch an I2O reply message - * @c: I2O controller of the message - * @m: I2O message number - * - * The reply is delivered to the driver from which the original message - * was. This function is only called from interrupt context. - * - * Returns 0 on success and the message should not be flushed. Returns > 0 - * on success and if the message should be flushed afterwords. Returns - * negative error code on failure (the message will be flushed too). - */ -int i2o_driver_dispatch(struct i2o_controller *c, u32 m) -{ - struct i2o_driver *drv; - struct i2o_message *msg = i2o_msg_out_to_virt(c, m); - u32 context = le32_to_cpu(msg->u.s.icntxt); - unsigned long flags; - - if (unlikely(context >= i2o_max_drivers)) { - osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, - context); - return -EIO; - } - - spin_lock_irqsave(&i2o_drivers_lock, flags); - drv = i2o_drivers[context]; - spin_unlock_irqrestore(&i2o_drivers_lock, flags); - - if (unlikely(!drv)) { - osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, - context); - return -EIO; - } - - if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { - struct i2o_device *dev, *tmp; - struct i2o_event *evt; - u16 size; - u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff; - - osm_debug("event received from device %d\n", tid); - - if (!drv->event) - return -EIO; - - /* cut of header from message size (in 32-bit words) */ - size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5; - - evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); - if (!evt) - return -ENOMEM; - - evt->size = size; - evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt); - evt->event_indicator = le32_to_cpu(msg->body[0]); - memcpy(&evt->data, &msg->body[1], size * 4); - - list_for_each_entry_safe(dev, tmp, &c->devices, list) - if (dev->lct_data.tid == tid) { - evt->i2o_dev = dev; - break; - } - - INIT_WORK(&evt->work, drv->event); - queue_work(drv->event_queue, &evt->work); - return 1; - } - - if (unlikely(!drv->reply)) { - osm_debug("%s: Reply to driver %s, but no reply function" - " defined!\n", c->name, drv->name); - return -EIO; - } - - return drv->reply(c, m, msg); -} - -/** - * i2o_driver_notify_controller_add_all - Send notify of added controller - * @c: newly added controller - * - * Send notifications to all registered drivers that a new controller was - * added. - */ -void i2o_driver_notify_controller_add_all(struct i2o_controller *c) -{ - int i; - struct i2o_driver *drv; - - for (i = 0; i < i2o_max_drivers; i++) { - drv = i2o_drivers[i]; - - if (drv) - i2o_driver_notify_controller_add(drv, c); - } -} - -/** - * i2o_driver_notify_controller_remove_all - Send notify of removed controller - * @c: controller that is being removed - * - * Send notifications to all registered drivers that a controller was - * removed. - */ -void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) -{ - int i; - struct i2o_driver *drv; - - for (i = 0; i < i2o_max_drivers; i++) { - drv = i2o_drivers[i]; - - if (drv) - i2o_driver_notify_controller_remove(drv, c); - } -} - -/** - * i2o_driver_notify_device_add_all - Send notify of added device - * @i2o_dev: newly added I2O device - * - * Send notifications to all registered drivers that a device was added. - */ -void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) -{ - int i; - struct i2o_driver *drv; - - for (i = 0; i < i2o_max_drivers; i++) { - drv = i2o_drivers[i]; - - if (drv) - i2o_driver_notify_device_add(drv, i2o_dev); - } -} - -/** - * i2o_driver_notify_device_remove_all - Send notify of removed device - * @i2o_dev: device that is being removed - * - * Send notifications to all registered drivers that a device was removed. - */ -void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) -{ - int i; - struct i2o_driver *drv; - - for (i = 0; i < i2o_max_drivers; i++) { - drv = i2o_drivers[i]; - - if (drv) - i2o_driver_notify_device_remove(drv, i2o_dev); - } -} - -/** - * i2o_driver_init - initialize I2O drivers (OSMs) - * - * Registers the I2O bus and allocate memory for the array of OSMs. - * - * Returns 0 on success or negative error code on failure. - */ -int __init i2o_driver_init(void) -{ - int rc = 0; - - spin_lock_init(&i2o_drivers_lock); - - if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64)) { - osm_warn("max_drivers set to %d, but must be >=2 and <= 64\n", - i2o_max_drivers); - i2o_max_drivers = I2O_MAX_DRIVERS; - } - osm_info("max drivers = %d\n", i2o_max_drivers); - - i2o_drivers = - kcalloc(i2o_max_drivers, sizeof(*i2o_drivers), GFP_KERNEL); - if (!i2o_drivers) - return -ENOMEM; - - rc = bus_register(&i2o_bus_type); - - if (rc < 0) - kfree(i2o_drivers); - - return rc; -}; - -/** - * i2o_driver_exit - clean up I2O drivers (OSMs) - * - * Unregisters the I2O bus and frees driver array. - */ -void i2o_driver_exit(void) -{ - bus_unregister(&i2o_bus_type); - kfree(i2o_drivers); -}; - -EXPORT_SYMBOL(i2o_driver_register); -EXPORT_SYMBOL(i2o_driver_unregister); -EXPORT_SYMBOL(i2o_driver_notify_controller_add_all); -EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all); -EXPORT_SYMBOL(i2o_driver_notify_device_add_all); -EXPORT_SYMBOL(i2o_driver_notify_device_remove_all); diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c deleted file mode 100644 index a3970e5..0000000 --- a/drivers/message/i2o/exec-osm.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Executive OSM - * - * Copyright (C) 1999-2002 Red Hat Software - * - * Written by Alan Cox, Building Number Three Ltd - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * A lot of the I2O message side code from this is taken from the Red - * Creek RCPCI45 adapter driver by Red Creek Communications - * - * Fixes/additions: - * Philipp Rumpf - * Juha Sievänen - * Auvo Häkkinen - * Deepak Saxena - * Boji T Kannanthanam - * Alan Cox : - * Ported to Linux 2.5. - * Markus Lidel : - * Minor fixes for 2.6. - * Markus Lidel : - * Support for sysfs included. - */ - -#include -#include -#include -#include -#include -#include -#include /* wait_event_interruptible_timeout() needs this */ -#include /* HZ */ -#include "core.h" - -#define OSM_NAME "exec-osm" - -struct i2o_driver i2o_exec_driver; - -/* global wait list for POST WAIT */ -static LIST_HEAD(i2o_exec_wait_list); - -/* Wait struct needed for POST WAIT */ -struct i2o_exec_wait { - wait_queue_head_t *wq; /* Pointer to Wait queue */ - struct i2o_dma dma; /* DMA buffers to free on failure */ - u32 tcntxt; /* transaction context from reply */ - int complete; /* 1 if reply received otherwise 0 */ - u32 m; /* message id */ - struct i2o_message *msg; /* pointer to the reply message */ - struct list_head list; /* node in global wait list */ - spinlock_t lock; /* lock before modifying */ -}; - -/* Work struct needed to handle LCT NOTIFY replies */ -struct i2o_exec_lct_notify_work { - struct work_struct work; /* work struct */ - struct i2o_controller *c; /* controller on which the LCT NOTIFY - was received */ -}; - -/* Exec OSM class handling definition */ -static struct i2o_class_id i2o_exec_class_id[] = { - {I2O_CLASS_EXECUTIVE}, - {I2O_CLASS_END} -}; - -/** - * i2o_exec_wait_alloc - Allocate a i2o_exec_wait struct an initialize it - * - * Allocate the i2o_exec_wait struct and initialize the wait. - * - * Returns i2o_exec_wait pointer on success or negative error code on - * failure. - */ -static struct i2o_exec_wait *i2o_exec_wait_alloc(void) -{ - struct i2o_exec_wait *wait; - - wait = kzalloc(sizeof(*wait), GFP_KERNEL); - if (!wait) - return NULL; - - INIT_LIST_HEAD(&wait->list); - spin_lock_init(&wait->lock); - - return wait; -}; - -/** - * i2o_exec_wait_free - Free an i2o_exec_wait struct - * @wait: I2O wait data which should be cleaned up - */ -static void i2o_exec_wait_free(struct i2o_exec_wait *wait) -{ - kfree(wait); -}; - -/** - * i2o_msg_post_wait_mem - Post and wait a message with DMA buffers - * @c: controller - * @msg: message to post - * @timeout: time in seconds to wait - * @dma: i2o_dma struct of the DMA buffer to free on failure - * - * This API allows an OSM to post a message and then be told whether or - * not the system received a successful reply. If the message times out - * then the value '-ETIMEDOUT' is returned. This is a special case. In - * this situation the message may (should) complete at an indefinite time - * in the future. When it completes it will use the memory buffer - * attached to the request. If -ETIMEDOUT is returned then the memory - * buffer must not be freed. Instead the event completion will free them - * for you. In all other cases the buffer are your problem. - * - * Returns 0 on success, negative error code on timeout or positive error - * code from reply. - */ -int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, - unsigned long timeout, struct i2o_dma *dma) -{ - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); - struct i2o_exec_wait *wait; - static u32 tcntxt = 0x80000000; - unsigned long flags; - int rc = 0; - - wait = i2o_exec_wait_alloc(); - if (!wait) { - i2o_msg_nop(c, msg); - return -ENOMEM; - } - - if (tcntxt == 0xffffffff) - tcntxt = 0x80000000; - - if (dma) - wait->dma = *dma; - - /* - * Fill in the message initiator context and transaction context. - * We will only use transaction contexts >= 0x80000000 for POST WAIT, - * so we could find a POST WAIT reply easier in the reply handler. - */ - msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); - wait->tcntxt = tcntxt++; - msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt); - - wait->wq = &wq; - /* - * we add elements to the head, because if a entry in the list will - * never be removed, we have to iterate over it every time - */ - list_add(&wait->list, &i2o_exec_wait_list); - - /* - * Post the message to the controller. At some point later it will - * return. If we time out before it returns then complete will be zero. - */ - i2o_msg_post(c, msg); - - wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ); - - spin_lock_irqsave(&wait->lock, flags); - - wait->wq = NULL; - - if (wait->complete) - rc = le32_to_cpu(wait->msg->body[0]) >> 24; - else { - /* - * We cannot remove it now. This is important. When it does - * terminate (which it must do if the controller has not - * died...) then it will otherwise scribble on stuff. - * - * FIXME: try abort message - */ - if (dma) - dma->virt = NULL; - - rc = -ETIMEDOUT; - } - - spin_unlock_irqrestore(&wait->lock, flags); - - if (rc != -ETIMEDOUT) { - i2o_flush_reply(c, wait->m); - i2o_exec_wait_free(wait); - } - - return rc; -}; - -/** - * i2o_msg_post_wait_complete - Reply to a i2o_msg_post request from IOP - * @c: I2O controller which answers - * @m: message id - * @msg: pointer to the I2O reply message - * @context: transaction context of request - * - * This function is called in interrupt context only. If the reply reached - * before the timeout, the i2o_exec_wait struct is filled with the message - * and the task will be waked up. The task is now responsible for returning - * the message m back to the controller! If the message reaches us after - * the timeout clean up the i2o_exec_wait struct (including allocated - * DMA buffer). - * - * Return 0 on success and if the message m should not be given back to the - * I2O controller, or >0 on success and if the message should be given back - * afterwords. Returns negative error code on failure. In this case the - * message must also be given back to the controller. - */ -static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, - struct i2o_message *msg, u32 context) -{ - struct i2o_exec_wait *wait, *tmp; - unsigned long flags; - int rc = 1; - - /* - * We need to search through the i2o_exec_wait_list to see if the given - * message is still outstanding. If not, it means that the IOP took - * longer to respond to the message than we had allowed and timer has - * already expired. Not much we can do about that except log it for - * debug purposes, increase timeout, and recompile. - */ - list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { - if (wait->tcntxt == context) { - spin_lock_irqsave(&wait->lock, flags); - - list_del(&wait->list); - - wait->m = m; - wait->msg = msg; - wait->complete = 1; - - if (wait->wq) - rc = 0; - else - rc = -1; - - spin_unlock_irqrestore(&wait->lock, flags); - - if (rc) { - struct device *dev; - - dev = &c->pdev->dev; - - pr_debug("%s: timedout reply received!\n", - c->name); - i2o_dma_free(dev, &wait->dma); - i2o_exec_wait_free(wait); - } else - wake_up_interruptible(wait->wq); - - return rc; - } - } - - osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, - context); - - return -1; -}; - -/** - * i2o_exec_show_vendor_id - Displays Vendor ID of controller - * @d: device of which the Vendor ID should be displayed - * @attr: device_attribute to display - * @buf: buffer into which the Vendor ID should be printed - * - * Returns number of bytes printed into buffer. - */ -static ssize_t i2o_exec_show_vendor_id(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct i2o_device *dev = to_i2o_device(d); - u16 id; - - if (!i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) { - sprintf(buf, "0x%04x", le16_to_cpu(id)); - return strlen(buf) + 1; - } - - return 0; -}; - -/** - * i2o_exec_show_product_id - Displays Product ID of controller - * @d: device of which the Product ID should be displayed - * @attr: device_attribute to display - * @buf: buffer into which the Product ID should be printed - * - * Returns number of bytes printed into buffer. - */ -static ssize_t i2o_exec_show_product_id(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct i2o_device *dev = to_i2o_device(d); - u16 id; - - if (!i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) { - sprintf(buf, "0x%04x", le16_to_cpu(id)); - return strlen(buf) + 1; - } - - return 0; -}; - -/* Exec-OSM device attributes */ -static DEVICE_ATTR(vendor_id, S_IRUGO, i2o_exec_show_vendor_id, NULL); -static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL); - -/** - * i2o_exec_probe - Called if a new I2O device (executive class) appears - * @dev: I2O device which should be probed - * - * Registers event notification for every event from Executive device. The - * return is always 0, because we want all devices of class Executive. - * - * Returns 0 on success. - */ -static int i2o_exec_probe(struct device *dev) -{ - struct i2o_device *i2o_dev = to_i2o_device(dev); - int rc; - - rc = i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); - if (rc) goto err_out; - - rc = device_create_file(dev, &dev_attr_vendor_id); - if (rc) goto err_evtreg; - rc = device_create_file(dev, &dev_attr_product_id); - if (rc) goto err_vid; - - i2o_dev->iop->exec = i2o_dev; - - return 0; - -err_vid: - device_remove_file(dev, &dev_attr_vendor_id); -err_evtreg: - i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); -err_out: - return rc; -}; - -/** - * i2o_exec_remove - Called on I2O device removal - * @dev: I2O device which was removed - * - * Unregisters event notification from Executive I2O device. - * - * Returns 0 on success. - */ -static int i2o_exec_remove(struct device *dev) -{ - device_remove_file(dev, &dev_attr_product_id); - device_remove_file(dev, &dev_attr_vendor_id); - - i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); - - return 0; -}; - -#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES -/** - * i2o_exec_lct_notify - Send a asynchronus LCT NOTIFY request - * @c: I2O controller to which the request should be send - * @change_ind: change indicator - * - * This function sends a LCT NOTIFY request to the I2O controller with - * the change indicator change_ind. If the change_ind == 0 the controller - * replies immediately after the request. If change_ind > 0 the reply is - * send after change indicator of the LCT is > change_ind. - */ -static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) -{ - i2o_status_block *sb = c->status_block.virt; - struct device *dev; - struct i2o_message *msg; - - mutex_lock(&c->lct_lock); - - dev = &c->pdev->dev; - - if (i2o_dma_realloc(dev, &c->dlct, - le32_to_cpu(sb->expected_lct_size))) { - mutex_unlock(&c->lct_lock); - return -ENOMEM; - } - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) { - mutex_unlock(&c->lct_lock); - return PTR_ERR(msg); - } - - msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); - msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); - msg->u.s.tcntxt = cpu_to_le32(0x00000000); - msg->body[0] = cpu_to_le32(0xffffffff); - msg->body[1] = cpu_to_le32(change_ind); - msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len); - msg->body[3] = cpu_to_le32(c->dlct.phys); - - i2o_msg_post(c, msg); - - mutex_unlock(&c->lct_lock); - - return 0; -} -#endif - -/** - * i2o_exec_lct_modified - Called on LCT NOTIFY reply - * @_work: work struct for a specific controller - * - * This function handles asynchronus LCT NOTIFY replies. It parses the - * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY - * again, otherwise send LCT NOTIFY to get informed on next LCT change. - */ -static void i2o_exec_lct_modified(struct work_struct *_work) -{ - struct i2o_exec_lct_notify_work *work = - container_of(_work, struct i2o_exec_lct_notify_work, work); - u32 change_ind = 0; - struct i2o_controller *c = work->c; - - kfree(work); - - if (i2o_device_parse_lct(c) != -EAGAIN) - change_ind = c->lct->change_ind + 1; - -#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES - i2o_exec_lct_notify(c, change_ind); -#endif -}; - -/** - * i2o_exec_reply - I2O Executive reply handler - * @c: I2O controller from which the reply comes - * @m: message id - * @msg: pointer to the I2O reply message - * - * This function is always called from interrupt context. If a POST WAIT - * reply was received, pass it to the complete function. If a LCT NOTIFY - * reply was received, a new event is created to handle the update. - * - * Returns 0 on success and if the reply should not be flushed or > 0 - * on success and if the reply should be flushed. Returns negative error - * code on failure and if the reply should be flushed. - */ -static int i2o_exec_reply(struct i2o_controller *c, u32 m, - struct i2o_message *msg) -{ - u32 context; - - if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { - struct i2o_message __iomem *pmsg; - u32 pm; - - /* - * If Fail bit is set we must take the transaction context of - * the preserved message to find the right request again. - */ - - pm = le32_to_cpu(msg->body[3]); - pmsg = i2o_msg_in_to_virt(c, pm); - context = readl(&pmsg->u.s.tcntxt); - - i2o_report_status(KERN_INFO, "i2o_core", msg); - - /* Release the preserved msg */ - i2o_msg_nop_mfa(c, pm); - } else - context = le32_to_cpu(msg->u.s.tcntxt); - - if (context & 0x80000000) - return i2o_msg_post_wait_complete(c, m, msg, context); - - if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { - struct i2o_exec_lct_notify_work *work; - - pr_debug("%s: LCT notify received\n", c->name); - - work = kmalloc(sizeof(*work), GFP_ATOMIC); - if (!work) - return -ENOMEM; - - work->c = c; - - INIT_WORK(&work->work, i2o_exec_lct_modified); - queue_work(i2o_exec_driver.event_queue, &work->work); - return 1; - } - - /* - * If this happens, we want to dump the message to the syslog so - * it can be sent back to the card manufacturer by the end user - * to aid in debugging. - * - */ - printk(KERN_WARNING "%s: Unsolicited message reply sent to core!" - "Message dumped to syslog\n", c->name); - i2o_dump_message(msg); - - return -EFAULT; -} - -/** - * i2o_exec_event - Event handling function - * @work: Work item in occurring event - * - * Handles events send by the Executive device. At the moment does not do - * anything useful. - */ -static void i2o_exec_event(struct work_struct *work) -{ - struct i2o_event *evt = container_of(work, struct i2o_event, work); - - if (likely(evt->i2o_dev)) - osm_debug("Event received from device: %d\n", - evt->i2o_dev->lct_data.tid); - kfree(evt); -}; - -/** - * i2o_exec_lct_get - Get the IOP's Logical Configuration Table - * @c: I2O controller from which the LCT should be fetched - * - * Send a LCT NOTIFY request to the controller, and wait - * I2O_TIMEOUT_LCT_GET seconds until arrival of response. If the LCT is - * to large, retry it. - * - * Returns 0 on success or negative error code on failure. - */ -int i2o_exec_lct_get(struct i2o_controller *c) -{ - struct i2o_message *msg; - int i = 0; - int rc = -EAGAIN; - - for (i = 1; i <= I2O_LCT_GET_TRIES; i++) { - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = - cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->body[0] = cpu_to_le32(0xffffffff); - msg->body[1] = cpu_to_le32(0x00000000); - msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len); - msg->body[3] = cpu_to_le32(c->dlct.phys); - - rc = i2o_msg_post_wait(c, msg, I2O_TIMEOUT_LCT_GET); - if (rc < 0) - break; - - rc = i2o_device_parse_lct(c); - if (rc != -EAGAIN) - break; - } - - return rc; -} - -/* Exec OSM driver struct */ -struct i2o_driver i2o_exec_driver = { - .name = OSM_NAME, - .reply = i2o_exec_reply, - .event = i2o_exec_event, - .classes = i2o_exec_class_id, - .driver = { - .probe = i2o_exec_probe, - .remove = i2o_exec_remove, - }, -}; - -/** - * i2o_exec_init - Registers the Exec OSM - * - * Registers the Exec OSM in the I2O core. - * - * Returns 0 on success or negative error code on failure. - */ -int __init i2o_exec_init(void) -{ - return i2o_driver_register(&i2o_exec_driver); -}; - -/** - * i2o_exec_exit - Removes the Exec OSM - * - * Unregisters the Exec OSM from the I2O core. - */ -void i2o_exec_exit(void) -{ - i2o_driver_unregister(&i2o_exec_driver); -}; - -EXPORT_SYMBOL(i2o_msg_post_wait_mem); -EXPORT_SYMBOL(i2o_exec_lct_get); diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c deleted file mode 100644 index 6fc3866..0000000 --- a/drivers/message/i2o/i2o_block.c +++ /dev/null @@ -1,1228 +0,0 @@ -/* - * Block OSM - * - * Copyright (C) 1999-2002 Red Hat Software - * - * Written by Alan Cox, Building Number Three Ltd - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * For the purpose of avoiding doubt the preferred form of the work - * for making modifications shall be a standards compliant form such - * gzipped tar and not one requiring a proprietary or patent encumbered - * tool to unpack. - * - * Fixes/additions: - * Steve Ralston: - * Multiple device handling error fixes, - * Added a queue depth. - * Alan Cox: - * FC920 has an rmw bug. Dont or in the end marker. - * Removed queue walk, fixed for 64bitness. - * Rewrote much of the code over time - * Added indirect block lists - * Handle 64K limits on many controllers - * Don't use indirects on the Promise (breaks) - * Heavily chop down the queue depths - * Deepak Saxena: - * Independent queues per IOP - * Support for dynamic device creation/deletion - * Code cleanup - * Support for larger I/Os through merge* functions - * (taken from DAC960 driver) - * Boji T Kannanthanam: - * Set the I2O Block devices to be detected in increasing - * order of TIDs during boot. - * Search and set the I2O block device that we boot off - * from as the first device to be claimed (as /dev/i2o/hda) - * Properly attach/detach I2O gendisk structure from the - * system gendisk list. The I2O block devices now appear in - * /proc/partitions. - * Markus Lidel : - * Minor bugfixes for 2.6. - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include - -#include "i2o_block.h" - -#define OSM_NAME "block-osm" -#define OSM_VERSION "1.325" -#define OSM_DESCRIPTION "I2O Block Device OSM" - -static DEFINE_MUTEX(i2o_block_mutex); -static struct i2o_driver i2o_block_driver; - -/* global Block OSM request mempool */ -static struct i2o_block_mempool i2o_blk_req_pool; - -/* Block OSM class handling definition */ -static struct i2o_class_id i2o_block_class_id[] = { - {I2O_CLASS_RANDOM_BLOCK_STORAGE}, - {I2O_CLASS_END} -}; - -/** - * i2o_block_device_free - free the memory of the I2O Block device - * @dev: I2O Block device, which should be cleaned up - * - * Frees the request queue, gendisk and the i2o_block_device structure. - */ -static void i2o_block_device_free(struct i2o_block_device *dev) -{ - blk_cleanup_queue(dev->gd->queue); - - put_disk(dev->gd); - - kfree(dev); -}; - -/** - * i2o_block_remove - remove the I2O Block device from the system again - * @dev: I2O Block device which should be removed - * - * Remove gendisk from system and free all allocated memory. - * - * Always returns 0. - */ -static int i2o_block_remove(struct device *dev) -{ - struct i2o_device *i2o_dev = to_i2o_device(dev); - struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev); - - osm_info("device removed (TID: %03x): %s\n", i2o_dev->lct_data.tid, - i2o_blk_dev->gd->disk_name); - - i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0); - - del_gendisk(i2o_blk_dev->gd); - - dev_set_drvdata(dev, NULL); - - i2o_device_claim_release(i2o_dev); - - i2o_block_device_free(i2o_blk_dev); - - return 0; -}; - -/** - * i2o_block_device flush - Flush all dirty data of I2O device dev - * @dev: I2O device which should be flushed - * - * Flushes all dirty data on device dev. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_block_device_flush(struct i2o_device *dev) -{ - struct i2o_message *msg; - - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev-> - lct_data.tid); - msg->body[0] = cpu_to_le32(60 << 16); - osm_debug("Flushing...\n"); - - return i2o_msg_post_wait(dev->iop, msg, 60); -}; - -/** - * i2o_block_device_mount - Mount (load) the media of device dev - * @dev: I2O device which should receive the mount request - * @media_id: Media Identifier - * - * Load a media into drive. Identifier should be set to -1, because the - * spec does not support any other value. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) -{ - struct i2o_message *msg; - - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev-> - lct_data.tid); - msg->body[0] = cpu_to_le32(-1); - msg->body[1] = cpu_to_le32(0x00000000); - osm_debug("Mounting...\n"); - - return i2o_msg_post_wait(dev->iop, msg, 2); -}; - -/** - * i2o_block_device_lock - Locks the media of device dev - * @dev: I2O device which should receive the lock request - * @media_id: Media Identifier - * - * Lock media of device dev to prevent removal. The media identifier - * should be set to -1, because the spec does not support any other value. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) -{ - struct i2o_message *msg; - - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev-> - lct_data.tid); - msg->body[0] = cpu_to_le32(-1); - osm_debug("Locking...\n"); - - return i2o_msg_post_wait(dev->iop, msg, 2); -}; - -/** - * i2o_block_device_unlock - Unlocks the media of device dev - * @dev: I2O device which should receive the unlocked request - * @media_id: Media Identifier - * - * Unlocks the media in device dev. The media identifier should be set to - * -1, because the spec does not support any other value. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id) -{ - struct i2o_message *msg; - - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev-> - lct_data.tid); - msg->body[0] = cpu_to_le32(media_id); - osm_debug("Unlocking...\n"); - - return i2o_msg_post_wait(dev->iop, msg, 2); -}; - -/** - * i2o_block_device_power - Power management for device dev - * @dev: I2O device which should receive the power management request - * @op: Operation to send - * - * Send a power management request to the device dev. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_block_device_power(struct i2o_block_device *dev, u8 op) -{ - struct i2o_device *i2o_dev = dev->i2o_dev; - struct i2o_controller *c = i2o_dev->iop; - struct i2o_message *msg; - int rc; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev-> - lct_data.tid); - msg->body[0] = cpu_to_le32(op << 24); - osm_debug("Power...\n"); - - rc = i2o_msg_post_wait(c, msg, 60); - if (!rc) - dev->power = op; - - return rc; -}; - -/** - * i2o_block_request_alloc - Allocate an I2O block request struct - * - * Allocates an I2O block request struct and initialize the list. - * - * Returns a i2o_block_request pointer on success or negative error code - * on failure. - */ -static inline struct i2o_block_request *i2o_block_request_alloc(void) -{ - struct i2o_block_request *ireq; - - ireq = mempool_alloc(i2o_blk_req_pool.pool, GFP_ATOMIC); - if (!ireq) - return ERR_PTR(-ENOMEM); - - INIT_LIST_HEAD(&ireq->queue); - sg_init_table(ireq->sg_table, I2O_MAX_PHYS_SEGMENTS); - - return ireq; -}; - -/** - * i2o_block_request_free - Frees a I2O block request - * @ireq: I2O block request which should be freed - * - * Frees the allocated memory (give it back to the request mempool). - */ -static inline void i2o_block_request_free(struct i2o_block_request *ireq) -{ - mempool_free(ireq, i2o_blk_req_pool.pool); -}; - -/** - * i2o_block_sglist_alloc - Allocate the SG list and map it - * @c: I2O controller to which the request belongs - * @ireq: I2O block request - * @mptr: message body pointer - * - * Builds the SG list and map it to be accessible by the controller. - * - * Returns 0 on failure or 1 on success. - */ -static inline int i2o_block_sglist_alloc(struct i2o_controller *c, - struct i2o_block_request *ireq, - u32 ** mptr) -{ - int nents; - enum dma_data_direction direction; - - ireq->dev = &c->pdev->dev; - nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table); - - if (rq_data_dir(ireq->req) == READ) - direction = PCI_DMA_FROMDEVICE; - else - direction = PCI_DMA_TODEVICE; - - ireq->sg_nents = nents; - - return i2o_dma_map_sg(c, ireq->sg_table, nents, direction, mptr); -}; - -/** - * i2o_block_sglist_free - Frees the SG list - * @ireq: I2O block request from which the SG should be freed - * - * Frees the SG list from the I2O block request. - */ -static inline void i2o_block_sglist_free(struct i2o_block_request *ireq) -{ - enum dma_data_direction direction; - - if (rq_data_dir(ireq->req) == READ) - direction = PCI_DMA_FROMDEVICE; - else - direction = PCI_DMA_TODEVICE; - - dma_unmap_sg(ireq->dev, ireq->sg_table, ireq->sg_nents, direction); -}; - -/** - * i2o_block_prep_req_fn - Allocates I2O block device specific struct - * @q: request queue for the request - * @req: the request to prepare - * - * Allocate the necessary i2o_block_request struct and connect it to - * the request. This is needed that we not lose the SG list later on. - * - * Returns BLKPREP_OK on success or BLKPREP_DEFER on failure. - */ -static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) -{ - struct i2o_block_device *i2o_blk_dev = q->queuedata; - struct i2o_block_request *ireq; - - if (unlikely(!i2o_blk_dev)) { - osm_err("block device already removed\n"); - return BLKPREP_KILL; - } - - /* connect the i2o_block_request to the request */ - if (!req->special) { - ireq = i2o_block_request_alloc(); - if (IS_ERR(ireq)) { - osm_debug("unable to allocate i2o_block_request!\n"); - return BLKPREP_DEFER; - } - - ireq->i2o_blk_dev = i2o_blk_dev; - req->special = ireq; - ireq->req = req; - } - /* do not come back here */ - req->cmd_flags |= REQ_DONTPREP; - - return BLKPREP_OK; -}; - -/** - * i2o_block_delayed_request_fn - delayed request queue function - * @work: the delayed request with the queue to start - * - * If the request queue is stopped for a disk, and there is no open - * request, a new event is created, which calls this function to start - * the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never - * be started again. - */ -static void i2o_block_delayed_request_fn(struct work_struct *work) -{ - struct i2o_block_delayed_request *dreq = - container_of(work, struct i2o_block_delayed_request, - work.work); - struct request_queue *q = dreq->queue; - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - blk_start_queue(q); - spin_unlock_irqrestore(q->queue_lock, flags); - kfree(dreq); -}; - -/** - * i2o_block_end_request - Post-processing of completed commands - * @req: request which should be completed - * @error: 0 for success, < 0 for error - * @nr_bytes: number of bytes to complete - * - * Mark the request as complete. The lock must not be held when entering. - * - */ -static void i2o_block_end_request(struct request *req, int error, - int nr_bytes) -{ - struct i2o_block_request *ireq = req->special; - struct i2o_block_device *dev = ireq->i2o_blk_dev; - struct request_queue *q = req->q; - unsigned long flags; - - if (blk_end_request(req, error, nr_bytes)) - if (error) - blk_end_request_all(req, -EIO); - - spin_lock_irqsave(q->queue_lock, flags); - - if (likely(dev)) { - dev->open_queue_depth--; - list_del(&ireq->queue); - } - - blk_start_queue(q); - - spin_unlock_irqrestore(q->queue_lock, flags); - - i2o_block_sglist_free(ireq); - i2o_block_request_free(ireq); -}; - -/** - * i2o_block_reply - Block OSM reply handler. - * @c: I2O controller from which the message arrives - * @m: message id of reply - * @msg: the actual I2O message reply - * - * This function gets all the message replies. - * - */ -static int i2o_block_reply(struct i2o_controller *c, u32 m, - struct i2o_message *msg) -{ - struct request *req; - int error = 0; - - req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); - if (unlikely(!req)) { - osm_err("NULL reply received!\n"); - return -1; - } - - /* - * Lets see what is cooking. We stuffed the - * request in the context. - */ - - if ((le32_to_cpu(msg->body[0]) >> 24) != 0) { - u32 status = le32_to_cpu(msg->body[0]); - /* - * Device not ready means two things. One is that the - * the thing went offline (but not a removal media) - * - * The second is that you have a SuperTrak 100 and the - * firmware got constipated. Unlike standard i2o card - * setups the supertrak returns an error rather than - * blocking for the timeout in these cases. - * - * Don't stick a supertrak100 into cache aggressive modes - */ - - osm_err("TID %03x error status: 0x%02x, detailed status: " - "0x%04x\n", (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff), - status >> 24, status & 0xffff); - - req->errors++; - - error = -EIO; - } - - i2o_block_end_request(req, error, le32_to_cpu(msg->body[1])); - - return 1; -}; - -static void i2o_block_event(struct work_struct *work) -{ - struct i2o_event *evt = container_of(work, struct i2o_event, work); - osm_debug("event received\n"); - kfree(evt); -}; - -/* - * SCSI-CAM for ioctl geometry mapping - * Duplicated with SCSI - this should be moved into somewhere common - * perhaps genhd ? - * - * LBA -> CHS mapping table taken from: - * - * "Incorporating the I2O Architecture into BIOS for Intel Architecture - * Platforms" - * - * This is an I2O document that is only available to I2O members, - * not developers. - * - * From my understanding, this is how all the I2O cards do this - * - * Disk Size | Sectors | Heads | Cylinders - * ---------------+---------+-------+------------------- - * 1 < X <= 528M | 63 | 16 | X/(63 * 16 * 512) - * 528M < X <= 1G | 63 | 32 | X/(63 * 32 * 512) - * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512) - * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512) - * - */ -#define BLOCK_SIZE_528M 1081344 -#define BLOCK_SIZE_1G 2097152 -#define BLOCK_SIZE_21G 4403200 -#define BLOCK_SIZE_42G 8806400 -#define BLOCK_SIZE_84G 17612800 - -static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls, - unsigned char *hds, unsigned char *secs) -{ - unsigned long heads, sectors, cylinders; - - sectors = 63L; /* Maximize sectors per track */ - if (capacity <= BLOCK_SIZE_528M) - heads = 16; - else if (capacity <= BLOCK_SIZE_1G) - heads = 32; - else if (capacity <= BLOCK_SIZE_21G) - heads = 64; - else if (capacity <= BLOCK_SIZE_42G) - heads = 128; - else - heads = 255; - - cylinders = (unsigned long)capacity / (heads * sectors); - - *cyls = (unsigned short)cylinders; /* Stuff return values */ - *secs = (unsigned char)sectors; - *hds = (unsigned char)heads; -} - -/** - * i2o_block_open - Open the block device - * @bdev: block device being opened - * @mode: file open mode - * - * Power up the device, mount and lock the media. This function is called, - * if the block device is opened for access. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_block_open(struct block_device *bdev, fmode_t mode) -{ - struct i2o_block_device *dev = bdev->bd_disk->private_data; - - if (!dev->i2o_dev) - return -ENODEV; - - mutex_lock(&i2o_block_mutex); - if (dev->power > 0x1f) - i2o_block_device_power(dev, 0x02); - - i2o_block_device_mount(dev->i2o_dev, -1); - - i2o_block_device_lock(dev->i2o_dev, -1); - - osm_debug("Ready.\n"); - mutex_unlock(&i2o_block_mutex); - - return 0; -}; - -/** - * i2o_block_release - Release the I2O block device - * @disk: gendisk device being released - * @mode: file open mode - * - * Unlock and unmount the media, and power down the device. Gets called if - * the block device is closed. - */ -static void i2o_block_release(struct gendisk *disk, fmode_t mode) -{ - struct i2o_block_device *dev = disk->private_data; - u8 operation; - - /* - * This is to deal with the case of an application - * opening a device and then the device disappears while - * it's in use, and then the application tries to release - * it. ex: Unmounting a deleted RAID volume at reboot. - * If we send messages, it will just cause FAILs since - * the TID no longer exists. - */ - if (!dev->i2o_dev) - return; - - mutex_lock(&i2o_block_mutex); - i2o_block_device_flush(dev->i2o_dev); - - i2o_block_device_unlock(dev->i2o_dev, -1); - - if (dev->flags & (1 << 3 | 1 << 4)) /* Removable */ - operation = 0x21; - else - operation = 0x24; - - i2o_block_device_power(dev, operation); - mutex_unlock(&i2o_block_mutex); -} - -static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - i2o_block_biosparam(get_capacity(bdev->bd_disk), - &geo->cylinders, &geo->heads, &geo->sectors); - return 0; -} - -/** - * i2o_block_ioctl - Issue device specific ioctl calls. - * @bdev: block device being opened - * @mode: file open mode - * @cmd: ioctl command - * @arg: arg - * - * Handles ioctl request for the block device. - * - * Return 0 on success or negative error on failure. - */ -static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - struct gendisk *disk = bdev->bd_disk; - struct i2o_block_device *dev = disk->private_data; - int ret = -ENOTTY; - - /* Anyone capable of this syscall can do *real bad* things */ - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - mutex_lock(&i2o_block_mutex); - switch (cmd) { - case BLKI2OGRSTRAT: - ret = put_user(dev->rcache, (int __user *)arg); - break; - case BLKI2OGWSTRAT: - ret = put_user(dev->wcache, (int __user *)arg); - break; - case BLKI2OSRSTRAT: - ret = -EINVAL; - if (arg < 0 || arg > CACHE_SMARTFETCH) - break; - dev->rcache = arg; - ret = 0; - break; - case BLKI2OSWSTRAT: - ret = -EINVAL; - if (arg != 0 - && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK)) - break; - dev->wcache = arg; - ret = 0; - break; - } - mutex_unlock(&i2o_block_mutex); - - return ret; -}; - -/** - * i2o_block_check_events - Have we seen a media change? - * @disk: gendisk which should be verified - * @clearing: events being cleared - * - * Verifies if the media has changed. - * - * Returns 1 if the media was changed or 0 otherwise. - */ -static unsigned int i2o_block_check_events(struct gendisk *disk, - unsigned int clearing) -{ - struct i2o_block_device *p = disk->private_data; - - if (p->media_change_flag) { - p->media_change_flag = 0; - return DISK_EVENT_MEDIA_CHANGE; - } - return 0; -} - -/** - * i2o_block_transfer - Transfer a request to/from the I2O controller - * @req: the request which should be transferred - * - * This function converts the request into a I2O message. The necessary - * DMA buffers are allocated and after everything is setup post the message - * to the I2O controller. No cleanup is done by this function. It is done - * on the interrupt side when the reply arrives. - * - * Return 0 on success or negative error code on failure. - */ -static int i2o_block_transfer(struct request *req) -{ - struct i2o_block_device *dev = req->rq_disk->private_data; - struct i2o_controller *c; - u32 tid; - struct i2o_message *msg; - u32 *mptr; - struct i2o_block_request *ireq = req->special; - u32 tcntxt; - u32 sgl_offset = SGL_OFFSET_8; - u32 ctl_flags = 0x00000000; - int rc; - u32 cmd; - - if (unlikely(!dev->i2o_dev)) { - osm_err("transfer to removed drive\n"); - rc = -ENODEV; - goto exit; - } - - tid = dev->i2o_dev->lct_data.tid; - c = dev->i2o_dev->iop; - - msg = i2o_msg_get(c); - if (IS_ERR(msg)) { - rc = PTR_ERR(msg); - goto exit; - } - - tcntxt = i2o_cntxt_list_add(c, req); - if (!tcntxt) { - rc = -ENOMEM; - goto nop_msg; - } - - msg->u.s.icntxt = cpu_to_le32(i2o_block_driver.context); - msg->u.s.tcntxt = cpu_to_le32(tcntxt); - - mptr = &msg->body[0]; - - if (rq_data_dir(req) == READ) { - cmd = I2O_CMD_BLOCK_READ << 24; - - switch (dev->rcache) { - case CACHE_PREFETCH: - ctl_flags = 0x201F0008; - break; - - case CACHE_SMARTFETCH: - if (blk_rq_sectors(req) > 16) - ctl_flags = 0x201F0008; - else - ctl_flags = 0x001F0000; - break; - - default: - break; - } - } else { - cmd = I2O_CMD_BLOCK_WRITE << 24; - - switch (dev->wcache) { - case CACHE_WRITETHROUGH: - ctl_flags = 0x001F0008; - break; - case CACHE_WRITEBACK: - ctl_flags = 0x001F0010; - break; - case CACHE_SMARTBACK: - if (blk_rq_sectors(req) > 16) - ctl_flags = 0x001F0004; - else - ctl_flags = 0x001F0010; - break; - case CACHE_SMARTTHROUGH: - if (blk_rq_sectors(req) > 16) - ctl_flags = 0x001F0004; - else - ctl_flags = 0x001F0010; - default: - break; - } - } - -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) { - u8 cmd[10]; - u32 scsi_flags; - u16 hwsec; - - hwsec = queue_logical_block_size(req->q) >> KERNEL_SECTOR_SHIFT; - memset(cmd, 0, 10); - - sgl_offset = SGL_OFFSET_12; - - msg->u.head[1] = - cpu_to_le32(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid); - - *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); - *mptr++ = cpu_to_le32(tid); - - /* - * ENABLE_DISCONNECT - * SIMPLE_TAG - * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME - */ - if (rq_data_dir(req) == READ) { - cmd[0] = READ_10; - scsi_flags = 0x60a0000a; - } else { - cmd[0] = WRITE_10; - scsi_flags = 0xa0a0000a; - } - - *mptr++ = cpu_to_le32(scsi_flags); - - *((u32 *) & cmd[2]) = cpu_to_be32(blk_rq_pos(req) * hwsec); - *((u16 *) & cmd[7]) = cpu_to_be16(blk_rq_sectors(req) * hwsec); - - memcpy(mptr, cmd, 10); - mptr += 4; - *mptr++ = cpu_to_le32(blk_rq_bytes(req)); - } else -#endif - { - msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); - *mptr++ = cpu_to_le32(ctl_flags); - *mptr++ = cpu_to_le32(blk_rq_bytes(req)); - *mptr++ = - cpu_to_le32((u32) (blk_rq_pos(req) << KERNEL_SECTOR_SHIFT)); - *mptr++ = - cpu_to_le32(blk_rq_pos(req) >> (32 - KERNEL_SECTOR_SHIFT)); - } - - if (!i2o_block_sglist_alloc(c, ireq, &mptr)) { - rc = -ENOMEM; - goto context_remove; - } - - msg->u.head[0] = - cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset); - - list_add_tail(&ireq->queue, &dev->open_queue); - dev->open_queue_depth++; - - i2o_msg_post(c, msg); - - return 0; - - context_remove: - i2o_cntxt_list_remove(c, req); - - nop_msg: - i2o_msg_nop(c, msg); - - exit: - return rc; -}; - -/** - * i2o_block_request_fn - request queue handling function - * @q: request queue from which the request could be fetched - * - * Takes the next request from the queue, transfers it and if no error - * occurs dequeue it from the queue. On arrival of the reply the message - * will be processed further. If an error occurs requeue the request. - */ -static void i2o_block_request_fn(struct request_queue *q) -{ - struct request *req; - - while ((req = blk_peek_request(q)) != NULL) { - if (req->cmd_type == REQ_TYPE_FS) { - struct i2o_block_delayed_request *dreq; - struct i2o_block_request *ireq = req->special; - unsigned int queue_depth; - - queue_depth = ireq->i2o_blk_dev->open_queue_depth; - - if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) { - if (!i2o_block_transfer(req)) { - blk_start_request(req); - continue; - } else - osm_info("transfer error\n"); - } - - if (queue_depth) - break; - - /* stop the queue and retry later */ - dreq = kmalloc(sizeof(*dreq), GFP_ATOMIC); - if (!dreq) - continue; - - dreq->queue = q; - INIT_DELAYED_WORK(&dreq->work, - i2o_block_delayed_request_fn); - - if (!queue_delayed_work(i2o_block_driver.event_queue, - &dreq->work, - I2O_BLOCK_RETRY_TIME)) - kfree(dreq); - else { - blk_stop_queue(q); - break; - } - } else { - blk_start_request(req); - __blk_end_request_all(req, -EIO); - } - } -}; - -/* I2O Block device operations definition */ -static const struct block_device_operations i2o_block_fops = { - .owner = THIS_MODULE, - .open = i2o_block_open, - .release = i2o_block_release, - .ioctl = i2o_block_ioctl, - .compat_ioctl = i2o_block_ioctl, - .getgeo = i2o_block_getgeo, - .check_events = i2o_block_check_events, -}; - -/** - * i2o_block_device_alloc - Allocate memory for a I2O Block device - * - * Allocate memory for the i2o_block_device struct, gendisk and request - * queue and initialize them as far as no additional information is needed. - * - * Returns a pointer to the allocated I2O Block device on success or a - * negative error code on failure. - */ -static struct i2o_block_device *i2o_block_device_alloc(void) -{ - struct i2o_block_device *dev; - struct gendisk *gd; - struct request_queue *queue; - int rc; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - osm_err("Insufficient memory to allocate I2O Block disk.\n"); - rc = -ENOMEM; - goto exit; - } - - INIT_LIST_HEAD(&dev->open_queue); - spin_lock_init(&dev->lock); - dev->rcache = CACHE_PREFETCH; - dev->wcache = CACHE_WRITEBACK; - - /* allocate a gendisk with 16 partitions */ - gd = alloc_disk(16); - if (!gd) { - osm_err("Insufficient memory to allocate gendisk.\n"); - rc = -ENOMEM; - goto cleanup_dev; - } - - /* initialize the request queue */ - queue = blk_init_queue(i2o_block_request_fn, &dev->lock); - if (!queue) { - osm_err("Insufficient memory to allocate request queue.\n"); - rc = -ENOMEM; - goto cleanup_queue; - } - - blk_queue_prep_rq(queue, i2o_block_prep_req_fn); - - gd->major = I2O_MAJOR; - gd->queue = queue; - gd->fops = &i2o_block_fops; - gd->private_data = dev; - - dev->gd = gd; - - return dev; - - cleanup_queue: - put_disk(gd); - - cleanup_dev: - kfree(dev); - - exit: - return ERR_PTR(rc); -}; - -/** - * i2o_block_probe - verify if dev is a I2O Block device and install it - * @dev: device to verify if it is a I2O Block device - * - * We only verify if the user_tid of the device is 0xfff and then install - * the device. Otherwise it is used by some other device (e. g. RAID). - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_block_probe(struct device *dev) -{ - struct i2o_device *i2o_dev = to_i2o_device(dev); - struct i2o_controller *c = i2o_dev->iop; - struct i2o_block_device *i2o_blk_dev; - struct gendisk *gd; - struct request_queue *queue; - static int unit = 0; - int rc; - u64 size; - u32 blocksize; - u16 body_size = 4; - u16 power; - unsigned short max_sectors; - -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) - body_size = 8; -#endif - - if (c->limit_sectors) - max_sectors = I2O_MAX_SECTORS_LIMITED; - else - max_sectors = I2O_MAX_SECTORS; - - /* skip devices which are used by IOP */ - if (i2o_dev->lct_data.user_tid != 0xfff) { - osm_debug("skipping used device %03x\n", i2o_dev->lct_data.tid); - return -ENODEV; - } - - if (i2o_device_claim(i2o_dev)) { - osm_warn("Unable to claim device. Installation aborted\n"); - rc = -EFAULT; - goto exit; - } - - i2o_blk_dev = i2o_block_device_alloc(); - if (IS_ERR(i2o_blk_dev)) { - osm_err("could not alloc a new I2O block device"); - rc = PTR_ERR(i2o_blk_dev); - goto claim_release; - } - - i2o_blk_dev->i2o_dev = i2o_dev; - dev_set_drvdata(dev, i2o_blk_dev); - - /* setup gendisk */ - gd = i2o_blk_dev->gd; - gd->first_minor = unit << 4; - sprintf(gd->disk_name, "i2o/hd%c", 'a' + unit); - gd->driverfs_dev = &i2o_dev->device; - - /* setup request queue */ - queue = gd->queue; - queue->queuedata = i2o_blk_dev; - - blk_queue_max_hw_sectors(queue, max_sectors); - blk_queue_max_segments(queue, i2o_sg_tablesize(c, body_size)); - - osm_debug("max sectors = %d\n", queue->max_sectors); - osm_debug("phys segments = %d\n", queue->max_phys_segments); - osm_debug("max hw segments = %d\n", queue->max_hw_segments); - - /* - * Ask for the current media data. If that isn't supported - * then we ask for the device capacity data - */ - if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || - !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { - blk_queue_logical_block_size(queue, le32_to_cpu(blocksize)); - } else - osm_warn("unable to get blocksize of %s\n", gd->disk_name); - - if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) || - !i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) { - set_capacity(gd, le64_to_cpu(size) >> KERNEL_SECTOR_SHIFT); - } else - osm_warn("could not get size of %s\n", gd->disk_name); - - if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2)) - i2o_blk_dev->power = power; - - i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff); - - add_disk(gd); - - unit++; - - osm_info("device added (TID: %03x): %s\n", i2o_dev->lct_data.tid, - i2o_blk_dev->gd->disk_name); - - return 0; - - claim_release: - i2o_device_claim_release(i2o_dev); - - exit: - return rc; -}; - -/* Block OSM driver struct */ -static struct i2o_driver i2o_block_driver = { - .name = OSM_NAME, - .event = i2o_block_event, - .reply = i2o_block_reply, - .classes = i2o_block_class_id, - .driver = { - .probe = i2o_block_probe, - .remove = i2o_block_remove, - }, -}; - -/** - * i2o_block_init - Block OSM initialization function - * - * Allocate the slab and mempool for request structs, registers i2o_block - * block device and finally register the Block OSM in the I2O core. - * - * Returns 0 on success or negative error code on failure. - */ -static int __init i2o_block_init(void) -{ - int rc; - int size; - - printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); - - /* Allocate request mempool and slab */ - size = sizeof(struct i2o_block_request); - i2o_blk_req_pool.slab = kmem_cache_create("i2o_block_req", size, 0, - SLAB_HWCACHE_ALIGN, NULL); - if (!i2o_blk_req_pool.slab) { - osm_err("can't init request slab\n"); - rc = -ENOMEM; - goto exit; - } - - i2o_blk_req_pool.pool = - mempool_create_slab_pool(I2O_BLOCK_REQ_MEMPOOL_SIZE, - i2o_blk_req_pool.slab); - if (!i2o_blk_req_pool.pool) { - osm_err("can't init request mempool\n"); - rc = -ENOMEM; - goto free_slab; - } - - /* Register the block device interfaces */ - rc = register_blkdev(I2O_MAJOR, "i2o_block"); - if (rc) { - osm_err("unable to register block device\n"); - goto free_mempool; - } -#ifdef MODULE - osm_info("registered device at major %d\n", I2O_MAJOR); -#endif - - /* Register Block OSM into I2O core */ - rc = i2o_driver_register(&i2o_block_driver); - if (rc) { - osm_err("Could not register Block driver\n"); - goto unregister_blkdev; - } - - return 0; - - unregister_blkdev: - unregister_blkdev(I2O_MAJOR, "i2o_block"); - - free_mempool: - mempool_destroy(i2o_blk_req_pool.pool); - - free_slab: - kmem_cache_destroy(i2o_blk_req_pool.slab); - - exit: - return rc; -}; - -/** - * i2o_block_exit - Block OSM exit function - * - * Unregisters Block OSM from I2O core, unregisters i2o_block block device - * and frees the mempool and slab. - */ -static void __exit i2o_block_exit(void) -{ - /* Unregister I2O Block OSM from I2O core */ - i2o_driver_unregister(&i2o_block_driver); - - /* Unregister block device */ - unregister_blkdev(I2O_MAJOR, "i2o_block"); - - /* Free request mempool and slab */ - mempool_destroy(i2o_blk_req_pool.pool); - kmem_cache_destroy(i2o_blk_req_pool.slab); -}; - -MODULE_AUTHOR("Red Hat"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(OSM_DESCRIPTION); -MODULE_VERSION(OSM_VERSION); - -module_init(i2o_block_init); -module_exit(i2o_block_exit); diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h deleted file mode 100644 index cf8873c..0000000 --- a/drivers/message/i2o/i2o_block.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Block OSM structures/API - * - * Copyright (C) 1999-2002 Red Hat Software - * - * Written by Alan Cox, Building Number Three Ltd - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * For the purpose of avoiding doubt the preferred form of the work - * for making modifications shall be a standards compliant form such - * gzipped tar and not one requiring a proprietary or patent encumbered - * tool to unpack. - * - * Fixes/additions: - * Steve Ralston: - * Multiple device handling error fixes, - * Added a queue depth. - * Alan Cox: - * FC920 has an rmw bug. Dont or in the end marker. - * Removed queue walk, fixed for 64bitness. - * Rewrote much of the code over time - * Added indirect block lists - * Handle 64K limits on many controllers - * Don't use indirects on the Promise (breaks) - * Heavily chop down the queue depths - * Deepak Saxena: - * Independent queues per IOP - * Support for dynamic device creation/deletion - * Code cleanup - * Support for larger I/Os through merge* functions - * (taken from DAC960 driver) - * Boji T Kannanthanam: - * Set the I2O Block devices to be detected in increasing - * order of TIDs during boot. - * Search and set the I2O block device that we boot off - * from as the first device to be claimed (as /dev/i2o/hda) - * Properly attach/detach I2O gendisk structure from the - * system gendisk list. The I2O block devices now appear in - * /proc/partitions. - * Markus Lidel : - * Minor bugfixes for 2.6. - */ - -#ifndef I2O_BLOCK_OSM_H -#define I2O_BLOCK_OSM_H - -#define I2O_BLOCK_RETRY_TIME HZ/4 -#define I2O_BLOCK_MAX_OPEN_REQUESTS 50 - -/* request queue sizes */ -#define I2O_BLOCK_REQ_MEMPOOL_SIZE 32 - -#define KERNEL_SECTOR_SHIFT 9 -#define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT) - -/* I2O Block OSM mempool struct */ -struct i2o_block_mempool { - struct kmem_cache *slab; - mempool_t *pool; -}; - -/* I2O Block device descriptor */ -struct i2o_block_device { - struct i2o_device *i2o_dev; /* pointer to I2O device */ - struct gendisk *gd; - spinlock_t lock; /* queue lock */ - struct list_head open_queue; /* list of transferred, but unfinished - requests */ - unsigned int open_queue_depth; /* number of requests in the queue */ - - int rcache; /* read cache flags */ - int wcache; /* write cache flags */ - int flags; - u16 power; /* power state */ - int media_change_flag; /* media changed flag */ -}; - -/* I2O Block device request */ -struct i2o_block_request { - struct list_head queue; - struct request *req; /* corresponding request */ - struct i2o_block_device *i2o_blk_dev; /* I2O block device */ - struct device *dev; /* device used for DMA */ - int sg_nents; /* number of SG elements */ - struct scatterlist sg_table[I2O_MAX_PHYS_SEGMENTS]; /* SG table */ -}; - -/* I2O Block device delayed request */ -struct i2o_block_delayed_request { - struct delayed_work work; - struct request_queue *queue; -}; - -#endif diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c deleted file mode 100644 index 04bd3b6..0000000 --- a/drivers/message/i2o/i2o_config.c +++ /dev/null @@ -1,1163 +0,0 @@ -/* - * I2O Configuration Interface Driver - * - * (C) Copyright 1999-2002 Red Hat - * - * Written by Alan Cox, Building Number Three Ltd - * - * Fixes/additions: - * Deepak Saxena (04/20/1999): - * Added basic ioctl() support - * Deepak Saxena (06/07/1999): - * Added software download ioctl (still testing) - * Auvo Häkkinen (09/10/1999): - * Changes to i2o_cfg_reply(), ioctl_parms() - * Added ioct_validate() - * Taneli Vähäkangas (09/30/1999): - * Fixed ioctl_swdl() - * Taneli Vähäkangas (10/04/1999): - * Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel() - * Deepak Saxena (11/18/1999): - * Added event managmenet support - * Alan Cox : - * 2.4 rewrite ported to 2.5 - * Markus Lidel : - * Added pass-thru support for Adaptec's raidutils - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include - -#include - -#include "core.h" - -#define SG_TABLESIZE 30 - -static DEFINE_MUTEX(i2o_cfg_mutex); -static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long); - -static spinlock_t i2o_config_lock; - -#define MODINC(x,y) ((x) = ((x) + 1) % (y)) - -struct sg_simple_element { - u32 flag_count; - u32 addr_bus; -}; - -struct i2o_cfg_info { - struct file *fp; - struct fasync_struct *fasync; - struct i2o_evt_info event_q[I2O_EVT_Q_LEN]; - u16 q_in; // Queue head index - u16 q_out; // Queue tail index - u16 q_len; // Queue length - u16 q_lost; // Number of lost events - ulong q_id; // Event queue ID...used as tx_context - struct i2o_cfg_info *next; -}; -static struct i2o_cfg_info *open_files = NULL; -static ulong i2o_cfg_info_id = 0; - -static int i2o_cfg_getiops(unsigned long arg) -{ - struct i2o_controller *c; - u8 __user *user_iop_table = (void __user *)arg; - u8 tmp[MAX_I2O_CONTROLLERS]; - int ret = 0; - - memset(tmp, 0, MAX_I2O_CONTROLLERS); - - list_for_each_entry(c, &i2o_controllers, list) - tmp[c->unit] = 1; - - if (copy_to_user(user_iop_table, tmp, MAX_I2O_CONTROLLERS)) - ret = -EFAULT; - - return ret; -}; - -static int i2o_cfg_gethrt(unsigned long arg) -{ - struct i2o_controller *c; - struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg; - struct i2o_cmd_hrtlct kcmd; - i2o_hrt *hrt; - int len; - u32 reslen; - int ret = 0; - - if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct))) - return -EFAULT; - - if (get_user(reslen, kcmd.reslen) < 0) - return -EFAULT; - - if (kcmd.resbuf == NULL) - return -EFAULT; - - c = i2o_find_iop(kcmd.iop); - if (!c) - return -ENXIO; - - hrt = (i2o_hrt *) c->hrt.virt; - - len = 8 + ((hrt->entry_len * hrt->num_entries) << 2); - - if (put_user(len, kcmd.reslen)) - ret = -EFAULT; - else if (len > reslen) - ret = -ENOBUFS; - else if (copy_to_user(kcmd.resbuf, (void *)hrt, len)) - ret = -EFAULT; - - return ret; -}; - -static int i2o_cfg_getlct(unsigned long arg) -{ - struct i2o_controller *c; - struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg; - struct i2o_cmd_hrtlct kcmd; - i2o_lct *lct; - int len; - int ret = 0; - u32 reslen; - - if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct))) - return -EFAULT; - - if (get_user(reslen, kcmd.reslen) < 0) - return -EFAULT; - - if (kcmd.resbuf == NULL) - return -EFAULT; - - c = i2o_find_iop(kcmd.iop); - if (!c) - return -ENXIO; - - lct = (i2o_lct *) c->lct; - - len = (unsigned int)lct->table_size << 2; - if (put_user(len, kcmd.reslen)) - ret = -EFAULT; - else if (len > reslen) - ret = -ENOBUFS; - else if (copy_to_user(kcmd.resbuf, lct, len)) - ret = -EFAULT; - - return ret; -}; - -static int i2o_cfg_parms(unsigned long arg, unsigned int type) -{ - int ret = 0; - struct i2o_controller *c; - struct i2o_device *dev; - struct i2o_cmd_psetget __user *cmd = - (struct i2o_cmd_psetget __user *)arg; - struct i2o_cmd_psetget kcmd; - u32 reslen; - u8 *ops; - u8 *res; - int len = 0; - - u32 i2o_cmd = (type == I2OPARMGET ? - I2O_CMD_UTIL_PARAMS_GET : I2O_CMD_UTIL_PARAMS_SET); - - if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget))) - return -EFAULT; - - if (get_user(reslen, kcmd.reslen)) - return -EFAULT; - - c = i2o_find_iop(kcmd.iop); - if (!c) - return -ENXIO; - - dev = i2o_iop_find_device(c, kcmd.tid); - if (!dev) - return -ENXIO; - - /* - * Stop users being able to try and allocate arbitrary amounts - * of DMA space. 64K is way more than sufficient for this. - */ - if (kcmd.oplen > 65536) - return -EMSGSIZE; - - ops = memdup_user(kcmd.opbuf, kcmd.oplen); - if (IS_ERR(ops)) - return PTR_ERR(ops); - - /* - * It's possible to have a _very_ large table - * and that the user asks for all of it at once... - */ - res = kmalloc(65536, GFP_KERNEL); - if (!res) { - kfree(ops); - return -ENOMEM; - } - - len = i2o_parm_issue(dev, i2o_cmd, ops, kcmd.oplen, res, 65536); - kfree(ops); - - if (len < 0) { - kfree(res); - return -EAGAIN; - } - - if (put_user(len, kcmd.reslen)) - ret = -EFAULT; - else if (len > reslen) - ret = -ENOBUFS; - else if (copy_to_user(kcmd.resbuf, res, len)) - ret = -EFAULT; - - kfree(res); - - return ret; -}; - -static int i2o_cfg_swdl(unsigned long arg) -{ - struct i2o_sw_xfer kxfer; - struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; - unsigned char maxfrag = 0, curfrag = 1; - struct i2o_dma buffer; - struct i2o_message *msg; - unsigned int status = 0, swlen = 0, fragsize = 8192; - struct i2o_controller *c; - - if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) - return -EFAULT; - - if (get_user(swlen, kxfer.swlen) < 0) - return -EFAULT; - - if (get_user(maxfrag, kxfer.maxfrag) < 0) - return -EFAULT; - - if (get_user(curfrag, kxfer.curfrag) < 0) - return -EFAULT; - - if (curfrag == maxfrag) - fragsize = swlen - (maxfrag - 1) * 8192; - - if (!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize)) - return -EFAULT; - - c = i2o_find_iop(kxfer.iop); - if (!c) - return -ENXIO; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) { - i2o_msg_nop(c, msg); - return -ENOMEM; - } - - if (__copy_from_user(buffer.virt, kxfer.buf, fragsize)) { - i2o_msg_nop(c, msg); - i2o_dma_free(&c->pdev->dev, &buffer); - return -EFAULT; - } - - msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); - msg->u.head[3] = cpu_to_le32(0); - msg->body[0] = - cpu_to_le32((((u32) kxfer.flags) << 24) | (((u32) kxfer. - sw_type) << 16) | - (((u32) maxfrag) << 8) | (((u32) curfrag))); - msg->body[1] = cpu_to_le32(swlen); - msg->body[2] = cpu_to_le32(kxfer.sw_id); - msg->body[3] = cpu_to_le32(0xD0000000 | fragsize); - msg->body[4] = cpu_to_le32(buffer.phys); - - osm_debug("swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); - status = i2o_msg_post_wait_mem(c, msg, 60, &buffer); - - if (status != -ETIMEDOUT) - i2o_dma_free(&c->pdev->dev, &buffer); - - if (status != I2O_POST_WAIT_OK) { - // it fails if you try and send frags out of order - // and for some yet unknown reasons too - osm_info("swdl failed, DetailedStatus = %d\n", status); - return status; - } - - return 0; -}; - -static int i2o_cfg_swul(unsigned long arg) -{ - struct i2o_sw_xfer kxfer; - struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; - unsigned char maxfrag = 0, curfrag = 1; - struct i2o_dma buffer; - struct i2o_message *msg; - unsigned int status = 0, swlen = 0, fragsize = 8192; - struct i2o_controller *c; - int ret = 0; - - if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) - return -EFAULT; - - if (get_user(swlen, kxfer.swlen) < 0) - return -EFAULT; - - if (get_user(maxfrag, kxfer.maxfrag) < 0) - return -EFAULT; - - if (get_user(curfrag, kxfer.curfrag) < 0) - return -EFAULT; - - if (curfrag == maxfrag) - fragsize = swlen - (maxfrag - 1) * 8192; - - if (!kxfer.buf) - return -EFAULT; - - c = i2o_find_iop(kxfer.iop); - if (!c) - return -ENXIO; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) { - i2o_msg_nop(c, msg); - return -ENOMEM; - } - - msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID); - msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); - msg->u.head[3] = cpu_to_le32(0); - msg->body[0] = - cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer. - sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag); - msg->body[1] = cpu_to_le32(swlen); - msg->body[2] = cpu_to_le32(kxfer.sw_id); - msg->body[3] = cpu_to_le32(0xD0000000 | fragsize); - msg->body[4] = cpu_to_le32(buffer.phys); - - osm_debug("swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); - status = i2o_msg_post_wait_mem(c, msg, 60, &buffer); - - if (status != I2O_POST_WAIT_OK) { - if (status != -ETIMEDOUT) - i2o_dma_free(&c->pdev->dev, &buffer); - - osm_info("swul failed, DetailedStatus = %d\n", status); - return status; - } - - if (copy_to_user(kxfer.buf, buffer.virt, fragsize)) - ret = -EFAULT; - - i2o_dma_free(&c->pdev->dev, &buffer); - - return ret; -} - -static int i2o_cfg_swdel(unsigned long arg) -{ - struct i2o_controller *c; - struct i2o_sw_xfer kxfer; - struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; - struct i2o_message *msg; - unsigned int swlen; - int token; - - if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) - return -EFAULT; - - if (get_user(swlen, kxfer.swlen) < 0) - return -EFAULT; - - c = i2o_find_iop(kxfer.iop); - if (!c) - return -ENXIO; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID); - msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); - msg->u.head[3] = cpu_to_le32(0); - msg->body[0] = - cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16); - msg->body[1] = cpu_to_le32(swlen); - msg->body[2] = cpu_to_le32(kxfer.sw_id); - - token = i2o_msg_post_wait(c, msg, 10); - - if (token != I2O_POST_WAIT_OK) { - osm_info("swdel failed, DetailedStatus = %d\n", token); - return -ETIMEDOUT; - } - - return 0; -}; - -static int i2o_cfg_validate(unsigned long arg) -{ - int token; - int iop = (int)arg; - struct i2o_message *msg; - struct i2o_controller *c; - - c = i2o_find_iop(iop); - if (!c) - return -ENXIO; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop); - msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); - msg->u.head[3] = cpu_to_le32(0); - - token = i2o_msg_post_wait(c, msg, 10); - - if (token != I2O_POST_WAIT_OK) { - osm_info("Can't validate configuration, ErrorStatus = %d\n", - token); - return -ETIMEDOUT; - } - - return 0; -}; - -static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp) -{ - struct i2o_message *msg; - struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg; - struct i2o_evt_id kdesc; - struct i2o_controller *c; - struct i2o_device *d; - - if (copy_from_user(&kdesc, pdesc, sizeof(struct i2o_evt_id))) - return -EFAULT; - - /* IOP exists? */ - c = i2o_find_iop(kdesc.iop); - if (!c) - return -ENXIO; - - /* Device exists? */ - d = i2o_iop_find_device(c, kdesc.tid); - if (!d) - return -ENODEV; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | - kdesc.tid); - msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); - msg->u.head[3] = cpu_to_le32(i2o_cntxt_list_add(c, fp->private_data)); - msg->body[0] = cpu_to_le32(kdesc.evt_mask); - - i2o_msg_post(c, msg); - - return 0; -} - -static int i2o_cfg_evt_get(unsigned long arg, struct file *fp) -{ - struct i2o_cfg_info *p = NULL; - struct i2o_evt_get __user *uget = (struct i2o_evt_get __user *)arg; - struct i2o_evt_get kget; - unsigned long flags; - - for (p = open_files; p; p = p->next) - if (p->q_id == (ulong) fp->private_data) - break; - - if (!p->q_len) - return -ENOENT; - - memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info)); - MODINC(p->q_out, I2O_EVT_Q_LEN); - spin_lock_irqsave(&i2o_config_lock, flags); - p->q_len--; - kget.pending = p->q_len; - kget.lost = p->q_lost; - spin_unlock_irqrestore(&i2o_config_lock, flags); - - if (copy_to_user(uget, &kget, sizeof(struct i2o_evt_get))) - return -EFAULT; - return 0; -} - -#ifdef CONFIG_COMPAT -static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, - unsigned long arg) -{ - struct i2o_cmd_passthru32 __user *cmd; - struct i2o_controller *c; - u32 __user *user_msg; - u32 *reply = NULL; - u32 __user *user_reply = NULL; - u32 size = 0; - u32 reply_size = 0; - u32 rcode = 0; - struct i2o_dma sg_list[SG_TABLESIZE]; - u32 sg_offset = 0; - u32 sg_count = 0; - u32 i = 0; - u32 sg_index = 0; - i2o_status_block *sb; - struct i2o_message *msg; - unsigned int iop; - - cmd = (struct i2o_cmd_passthru32 __user *)arg; - - if (get_user(iop, &cmd->iop) || get_user(i, &cmd->msg)) - return -EFAULT; - - user_msg = compat_ptr(i); - - c = i2o_find_iop(iop); - if (!c) { - osm_debug("controller %d not found\n", iop); - return -ENXIO; - } - - sb = c->status_block.virt; - - if (get_user(size, &user_msg[0])) { - osm_warn("unable to get size!\n"); - return -EFAULT; - } - size = size >> 16; - - if (size > sb->inbound_frame_size) { - osm_warn("size of message > inbound_frame_size"); - return -EFAULT; - } - - user_reply = &user_msg[size]; - - size <<= 2; // Convert to bytes - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - rcode = -EFAULT; - /* Copy in the user's I2O command */ - if (copy_from_user(msg, user_msg, size)) { - osm_warn("unable to copy user message\n"); - goto out; - } - i2o_dump_message(msg); - - if (get_user(reply_size, &user_reply[0]) < 0) - goto out; - - reply_size >>= 16; - reply_size <<= 2; - - rcode = -ENOMEM; - reply = kzalloc(reply_size, GFP_KERNEL); - if (!reply) { - printk(KERN_WARNING "%s: Could not allocate reply buffer\n", - c->name); - goto out; - } - - sg_offset = (msg->u.head[0] >> 4) & 0x0f; - - memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); - if (sg_offset) { - struct sg_simple_element *sg; - - if (sg_offset * 4 >= size) { - rcode = -EFAULT; - goto cleanup; - } - // TODO 64bit fix - sg = (struct sg_simple_element *)((&msg->u.head[0]) + - sg_offset); - sg_count = - (size - sg_offset * 4) / sizeof(struct sg_simple_element); - if (sg_count > SG_TABLESIZE) { - printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", - c->name, sg_count); - rcode = -EINVAL; - goto cleanup; - } - - for (i = 0; i < sg_count; i++) { - int sg_size; - struct i2o_dma *p; - - if (!(sg[i].flag_count & 0x10000000 - /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) { - printk(KERN_DEBUG - "%s:Bad SG element %d - not simple (%x)\n", - c->name, i, sg[i].flag_count); - rcode = -EINVAL; - goto cleanup; - } - sg_size = sg[i].flag_count & 0xffffff; - p = &(sg_list[sg_index]); - /* Allocate memory for the transfer */ - if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) { - printk(KERN_DEBUG - "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", - c->name, sg_size, i, sg_count); - rcode = -ENOMEM; - goto sg_list_cleanup; - } - sg_index++; - /* Copy in the user's SG buffer if necessary */ - if (sg[i]. - flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { - // TODO 64bit fix - if (copy_from_user - (p->virt, - (void __user *)(unsigned long)sg[i]. - addr_bus, sg_size)) { - printk(KERN_DEBUG - "%s: Could not copy SG buf %d FROM user\n", - c->name, i); - rcode = -EFAULT; - goto sg_list_cleanup; - } - } - //TODO 64bit fix - sg[i].addr_bus = (u32) p->phys; - } - } - - rcode = i2o_msg_post_wait(c, msg, 60); - msg = NULL; - if (rcode) { - reply[4] = ((u32) rcode) << 24; - goto sg_list_cleanup; - } - - if (sg_offset) { - u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE]; - /* Copy back the Scatter Gather buffers back to user space */ - u32 j; - // TODO 64bit fix - struct sg_simple_element *sg; - int sg_size; - - // re-acquire the original message to handle correctly the sg copy operation - memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); - // get user msg size in u32s - if (get_user(size, &user_msg[0])) { - rcode = -EFAULT; - goto sg_list_cleanup; - } - size = size >> 16; - size *= 4; - if (size > sizeof(rmsg)) { - rcode = -EINVAL; - goto sg_list_cleanup; - } - - /* Copy in the user's I2O command */ - if (copy_from_user(rmsg, user_msg, size)) { - rcode = -EFAULT; - goto sg_list_cleanup; - } - sg_count = - (size - sg_offset * 4) / sizeof(struct sg_simple_element); - - // TODO 64bit fix - sg = (struct sg_simple_element *)(rmsg + sg_offset); - for (j = 0; j < sg_count; j++) { - /* Copy out the SG list to user's buffer if necessary */ - if (! - (sg[j]. - flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) { - sg_size = sg[j].flag_count & 0xffffff; - // TODO 64bit fix - if (copy_to_user - ((void __user *)(u64) sg[j].addr_bus, - sg_list[j].virt, sg_size)) { - printk(KERN_WARNING - "%s: Could not copy %p TO user %x\n", - c->name, sg_list[j].virt, - sg[j].addr_bus); - rcode = -EFAULT; - goto sg_list_cleanup; - } - } - } - } - -sg_list_cleanup: - /* Copy back the reply to user space */ - if (reply_size) { - // we wrote our own values for context - now restore the user supplied ones - if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) { - printk(KERN_WARNING - "%s: Could not copy message context FROM user\n", - c->name); - rcode = -EFAULT; - } - if (copy_to_user(user_reply, reply, reply_size)) { - printk(KERN_WARNING - "%s: Could not copy reply TO user\n", c->name); - rcode = -EFAULT; - } - } - for (i = 0; i < sg_index; i++) - i2o_dma_free(&c->pdev->dev, &sg_list[i]); - -cleanup: - kfree(reply); -out: - if (msg) - i2o_msg_nop(c, msg); - return rcode; -} - -static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, - unsigned long arg) -{ - int ret; - switch (cmd) { - case I2OGETIOPS: - ret = i2o_cfg_ioctl(file, cmd, arg); - break; - case I2OPASSTHRU32: - mutex_lock(&i2o_cfg_mutex); - ret = i2o_cfg_passthru32(file, cmd, arg); - mutex_unlock(&i2o_cfg_mutex); - break; - default: - ret = -ENOIOCTLCMD; - break; - } - return ret; -} - -#endif - -#ifdef CONFIG_I2O_EXT_ADAPTEC -static int i2o_cfg_passthru(unsigned long arg) -{ - struct i2o_cmd_passthru __user *cmd = - (struct i2o_cmd_passthru __user *)arg; - struct i2o_controller *c; - u32 __user *user_msg; - u32 *reply = NULL; - u32 __user *user_reply = NULL; - u32 size = 0; - u32 reply_size = 0; - u32 rcode = 0; - struct i2o_dma sg_list[SG_TABLESIZE]; - u32 sg_offset = 0; - u32 sg_count = 0; - int sg_index = 0; - u32 i = 0; - i2o_status_block *sb; - struct i2o_message *msg; - unsigned int iop; - - if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg)) - return -EFAULT; - - c = i2o_find_iop(iop); - if (!c) { - osm_warn("controller %d not found\n", iop); - return -ENXIO; - } - - sb = c->status_block.virt; - - if (get_user(size, &user_msg[0])) - return -EFAULT; - size = size >> 16; - - if (size > sb->inbound_frame_size) { - osm_warn("size of message > inbound_frame_size"); - return -EFAULT; - } - - user_reply = &user_msg[size]; - - size <<= 2; // Convert to bytes - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - rcode = -EFAULT; - /* Copy in the user's I2O command */ - if (copy_from_user(msg, user_msg, size)) - goto out; - - if (get_user(reply_size, &user_reply[0]) < 0) - goto out; - - reply_size >>= 16; - reply_size <<= 2; - - reply = kzalloc(reply_size, GFP_KERNEL); - if (!reply) { - printk(KERN_WARNING "%s: Could not allocate reply buffer\n", - c->name); - rcode = -ENOMEM; - goto out; - } - - sg_offset = (msg->u.head[0] >> 4) & 0x0f; - - memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); - if (sg_offset) { - struct sg_simple_element *sg; - struct i2o_dma *p; - - if (sg_offset * 4 >= size) { - rcode = -EFAULT; - goto cleanup; - } - // TODO 64bit fix - sg = (struct sg_simple_element *)((&msg->u.head[0]) + - sg_offset); - sg_count = - (size - sg_offset * 4) / sizeof(struct sg_simple_element); - if (sg_count > SG_TABLESIZE) { - printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", - c->name, sg_count); - rcode = -EINVAL; - goto cleanup; - } - - for (i = 0; i < sg_count; i++) { - int sg_size; - - if (!(sg[i].flag_count & 0x10000000 - /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) { - printk(KERN_DEBUG - "%s:Bad SG element %d - not simple (%x)\n", - c->name, i, sg[i].flag_count); - rcode = -EINVAL; - goto sg_list_cleanup; - } - sg_size = sg[i].flag_count & 0xffffff; - p = &(sg_list[sg_index]); - if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) { - /* Allocate memory for the transfer */ - printk(KERN_DEBUG - "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", - c->name, sg_size, i, sg_count); - rcode = -ENOMEM; - goto sg_list_cleanup; - } - sg_index++; - /* Copy in the user's SG buffer if necessary */ - if (sg[i]. - flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { - // TODO 64bit fix - if (copy_from_user - (p->virt, (void __user *)sg[i].addr_bus, - sg_size)) { - printk(KERN_DEBUG - "%s: Could not copy SG buf %d FROM user\n", - c->name, i); - rcode = -EFAULT; - goto sg_list_cleanup; - } - } - sg[i].addr_bus = p->phys; - } - } - - rcode = i2o_msg_post_wait(c, msg, 60); - msg = NULL; - if (rcode) { - reply[4] = ((u32) rcode) << 24; - goto sg_list_cleanup; - } - - if (sg_offset) { - u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE]; - /* Copy back the Scatter Gather buffers back to user space */ - u32 j; - // TODO 64bit fix - struct sg_simple_element *sg; - int sg_size; - - // re-acquire the original message to handle correctly the sg copy operation - memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); - // get user msg size in u32s - if (get_user(size, &user_msg[0])) { - rcode = -EFAULT; - goto sg_list_cleanup; - } - size = size >> 16; - size *= 4; - if (size > sizeof(rmsg)) { - rcode = -EFAULT; - goto sg_list_cleanup; - } - - /* Copy in the user's I2O command */ - if (copy_from_user(rmsg, user_msg, size)) { - rcode = -EFAULT; - goto sg_list_cleanup; - } - sg_count = - (size - sg_offset * 4) / sizeof(struct sg_simple_element); - - // TODO 64bit fix - sg = (struct sg_simple_element *)(rmsg + sg_offset); - for (j = 0; j < sg_count; j++) { - /* Copy out the SG list to user's buffer if necessary */ - if (! - (sg[j]. - flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) { - sg_size = sg[j].flag_count & 0xffffff; - // TODO 64bit fix - if (copy_to_user - ((void __user *)sg[j].addr_bus, sg_list[j].virt, - sg_size)) { - printk(KERN_WARNING - "%s: Could not copy %p TO user %x\n", - c->name, sg_list[j].virt, - sg[j].addr_bus); - rcode = -EFAULT; - goto sg_list_cleanup; - } - } - } - } - -sg_list_cleanup: - /* Copy back the reply to user space */ - if (reply_size) { - // we wrote our own values for context - now restore the user supplied ones - if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) { - printk(KERN_WARNING - "%s: Could not copy message context FROM user\n", - c->name); - rcode = -EFAULT; - } - if (copy_to_user(user_reply, reply, reply_size)) { - printk(KERN_WARNING - "%s: Could not copy reply TO user\n", c->name); - rcode = -EFAULT; - } - } - - for (i = 0; i < sg_index; i++) - i2o_dma_free(&c->pdev->dev, &sg_list[i]); - -cleanup: - kfree(reply); -out: - if (msg) - i2o_msg_nop(c, msg); - return rcode; -} -#endif - -/* - * IOCTL Handler - */ -static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) -{ - int ret; - - mutex_lock(&i2o_cfg_mutex); - switch (cmd) { - case I2OGETIOPS: - ret = i2o_cfg_getiops(arg); - break; - - case I2OHRTGET: - ret = i2o_cfg_gethrt(arg); - break; - - case I2OLCTGET: - ret = i2o_cfg_getlct(arg); - break; - - case I2OPARMSET: - ret = i2o_cfg_parms(arg, I2OPARMSET); - break; - - case I2OPARMGET: - ret = i2o_cfg_parms(arg, I2OPARMGET); - break; - - case I2OSWDL: - ret = i2o_cfg_swdl(arg); - break; - - case I2OSWUL: - ret = i2o_cfg_swul(arg); - break; - - case I2OSWDEL: - ret = i2o_cfg_swdel(arg); - break; - - case I2OVALIDATE: - ret = i2o_cfg_validate(arg); - break; - - case I2OEVTREG: - ret = i2o_cfg_evt_reg(arg, fp); - break; - - case I2OEVTGET: - ret = i2o_cfg_evt_get(arg, fp); - break; - -#ifdef CONFIG_I2O_EXT_ADAPTEC - case I2OPASSTHRU: - ret = i2o_cfg_passthru(arg); - break; -#endif - - default: - osm_debug("unknown ioctl called!\n"); - ret = -EINVAL; - } - mutex_unlock(&i2o_cfg_mutex); - return ret; -} - -static int cfg_open(struct inode *inode, struct file *file) -{ - struct i2o_cfg_info *tmp = kmalloc(sizeof(struct i2o_cfg_info), - GFP_KERNEL); - unsigned long flags; - - if (!tmp) - return -ENOMEM; - - mutex_lock(&i2o_cfg_mutex); - file->private_data = (void *)(i2o_cfg_info_id++); - tmp->fp = file; - tmp->fasync = NULL; - tmp->q_id = (ulong) file->private_data; - tmp->q_len = 0; - tmp->q_in = 0; - tmp->q_out = 0; - tmp->q_lost = 0; - tmp->next = open_files; - - spin_lock_irqsave(&i2o_config_lock, flags); - open_files = tmp; - spin_unlock_irqrestore(&i2o_config_lock, flags); - mutex_unlock(&i2o_cfg_mutex); - - return 0; -} - -static int cfg_fasync(int fd, struct file *fp, int on) -{ - ulong id = (ulong) fp->private_data; - struct i2o_cfg_info *p; - int ret = -EBADF; - - mutex_lock(&i2o_cfg_mutex); - for (p = open_files; p; p = p->next) - if (p->q_id == id) - break; - - if (p) - ret = fasync_helper(fd, fp, on, &p->fasync); - mutex_unlock(&i2o_cfg_mutex); - return ret; -} - -static int cfg_release(struct inode *inode, struct file *file) -{ - ulong id = (ulong) file->private_data; - struct i2o_cfg_info *p, **q; - unsigned long flags; - - mutex_lock(&i2o_cfg_mutex); - spin_lock_irqsave(&i2o_config_lock, flags); - for (q = &open_files; (p = *q) != NULL; q = &p->next) { - if (p->q_id == id) { - *q = p->next; - kfree(p); - break; - } - } - spin_unlock_irqrestore(&i2o_config_lock, flags); - mutex_unlock(&i2o_cfg_mutex); - - return 0; -} - -static const struct file_operations config_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .unlocked_ioctl = i2o_cfg_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = i2o_cfg_compat_ioctl, -#endif - .open = cfg_open, - .release = cfg_release, - .fasync = cfg_fasync, -}; - -static struct miscdevice i2o_miscdev = { - I2O_MINOR, - "i2octl", - &config_fops -}; - -static int __init i2o_config_old_init(void) -{ - spin_lock_init(&i2o_config_lock); - - if (misc_register(&i2o_miscdev) < 0) { - osm_err("can't register device.\n"); - return -EBUSY; - } - - return 0; -} - -static void i2o_config_old_exit(void) -{ - misc_deregister(&i2o_miscdev); -} - -MODULE_AUTHOR("Red Hat Software"); diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c deleted file mode 100644 index b7d87cd..0000000 --- a/drivers/message/i2o/i2o_proc.c +++ /dev/null @@ -1,2045 +0,0 @@ -/* - * procfs handler for Linux I2O subsystem - * - * (c) Copyright 1999 Deepak Saxena - * - * Originally written by Deepak Saxena(deepak@plexity.net) - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This is an initial test release. The code is based on the design of the - * ide procfs system (drivers/block/ide-proc.c). Some code taken from - * i2o-core module by Alan Cox. - * - * DISCLAIMER: This code is still under development/test and may cause - * your system to behave unpredictably. Use at your own discretion. - * - * - * Fixes/additions: - * Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI), - * Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI) - * University of Helsinki, Department of Computer Science - * LAN entries - * Markus Lidel - * Changes for new I2O API - */ - -#define OSM_NAME "proc-osm" -#define OSM_VERSION "1.316" -#define OSM_DESCRIPTION "I2O ProcFS OSM" - -#define I2O_MAX_MODULES 4 -// FIXME! -#define FMT_U64_HEX "0x%08x%08x" -#define U64_VAL(pu64) *((u32*)(pu64)+1), *((u32*)(pu64)) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Structure used to define /proc entries */ -typedef struct _i2o_proc_entry_t { - char *name; /* entry name */ - umode_t mode; /* mode */ - const struct file_operations *fops; /* open function */ -} i2o_proc_entry; - -/* global I2O /proc/i2o entry */ -static struct proc_dir_entry *i2o_proc_dir_root; - -/* proc OSM driver struct */ -static struct i2o_driver i2o_proc_driver = { - .name = OSM_NAME, -}; - -static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len) -{ - int i; - - /* 19990419 -sralston - * The I2O v1.5 (and v2.0 so far) "official specification" - * got serial numbers WRONG! - * Apparently, and despite what Section 3.4.4 says and - * Figure 3-35 shows (pg 3-39 in the pdf doc), - * the convention / consensus seems to be: - * + First byte is SNFormat - * + Second byte is SNLen (but only if SNFormat==7 (?)) - * + (v2.0) SCSI+BS may use IEEE Registered (64 or 128 bit) format - */ - switch (serialno[0]) { - case I2O_SNFORMAT_BINARY: /* Binary */ - seq_printf(seq, "0x"); - for (i = 0; i < serialno[1]; i++) { - seq_printf(seq, "%02X", serialno[2 + i]); - } - break; - - case I2O_SNFORMAT_ASCII: /* ASCII */ - if (serialno[1] < ' ') { /* printable or SNLen? */ - /* sanity */ - max_len = - (max_len < serialno[1]) ? max_len : serialno[1]; - serialno[1 + max_len] = '\0'; - - /* just print it */ - seq_printf(seq, "%s", &serialno[2]); - } else { - /* print chars for specified length */ - for (i = 0; i < serialno[1]; i++) { - seq_printf(seq, "%c", serialno[2 + i]); - } - } - break; - - case I2O_SNFORMAT_UNICODE: /* UNICODE */ - seq_printf(seq, "UNICODE Format. Can't Display\n"); - break; - - case I2O_SNFORMAT_LAN48_MAC: /* LAN-48 MAC Address */ - seq_printf(seq, "LAN-48 MAC address @ %pM", &serialno[2]); - break; - - case I2O_SNFORMAT_WAN: /* WAN MAC Address */ - /* FIXME: Figure out what a WAN access address looks like?? */ - seq_printf(seq, "WAN Access Address"); - break; - -/* plus new in v2.0 */ - case I2O_SNFORMAT_LAN64_MAC: /* LAN-64 MAC Address */ - /* FIXME: Figure out what a LAN-64 address really looks like?? */ - seq_printf(seq, - "LAN-64 MAC address @ [?:%02X:%02X:?] %pM", - serialno[8], serialno[9], &serialno[2]); - break; - - case I2O_SNFORMAT_DDM: /* I2O DDM */ - seq_printf(seq, - "DDM: Tid=%03Xh, Rsvd=%04Xh, OrgId=%04Xh", - *(u16 *) & serialno[2], - *(u16 *) & serialno[4], *(u16 *) & serialno[6]); - break; - - case I2O_SNFORMAT_IEEE_REG64: /* IEEE Registered (64-bit) */ - case I2O_SNFORMAT_IEEE_REG128: /* IEEE Registered (128-bit) */ - /* FIXME: Figure if this is even close?? */ - seq_printf(seq, - "IEEE NodeName(hi,lo)=(%08Xh:%08Xh), PortName(hi,lo)=(%08Xh:%08Xh)\n", - *(u32 *) & serialno[2], - *(u32 *) & serialno[6], - *(u32 *) & serialno[10], *(u32 *) & serialno[14]); - break; - - case I2O_SNFORMAT_UNKNOWN: /* Unknown 0 */ - case I2O_SNFORMAT_UNKNOWN2: /* Unknown 0xff */ - default: - seq_printf(seq, "Unknown data format (0x%02x)", serialno[0]); - break; - } - - return 0; -} - -/** - * i2o_get_class_name - do i2o class name lookup - * @class: class number - * - * Return a descriptive string for an i2o class. - */ -static const char *i2o_get_class_name(int class) -{ - int idx = 16; - static char *i2o_class_name[] = { - "Executive", - "Device Driver Module", - "Block Device", - "Tape Device", - "LAN Interface", - "WAN Interface", - "Fibre Channel Port", - "Fibre Channel Device", - "SCSI Device", - "ATE Port", - "ATE Device", - "Floppy Controller", - "Floppy Device", - "Secondary Bus Port", - "Peer Transport Agent", - "Peer Transport", - "Unknown" - }; - - switch (class & 0xfff) { - case I2O_CLASS_EXECUTIVE: - idx = 0; - break; - case I2O_CLASS_DDM: - idx = 1; - break; - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - idx = 2; - break; - case I2O_CLASS_SEQUENTIAL_STORAGE: - idx = 3; - break; - case I2O_CLASS_LAN: - idx = 4; - break; - case I2O_CLASS_WAN: - idx = 5; - break; - case I2O_CLASS_FIBRE_CHANNEL_PORT: - idx = 6; - break; - case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: - idx = 7; - break; - case I2O_CLASS_SCSI_PERIPHERAL: - idx = 8; - break; - case I2O_CLASS_ATE_PORT: - idx = 9; - break; - case I2O_CLASS_ATE_PERIPHERAL: - idx = 10; - break; - case I2O_CLASS_FLOPPY_CONTROLLER: - idx = 11; - break; - case I2O_CLASS_FLOPPY_DEVICE: - idx = 12; - break; - case I2O_CLASS_BUS_ADAPTER: - idx = 13; - break; - case I2O_CLASS_PEER_TRANSPORT_AGENT: - idx = 14; - break; - case I2O_CLASS_PEER_TRANSPORT: - idx = 15; - break; - } - - return i2o_class_name[idx]; -} - -#define SCSI_TABLE_SIZE 13 -static char *scsi_devices[] = { - "Direct-Access Read/Write", - "Sequential-Access Storage", - "Printer", - "Processor", - "WORM Device", - "CD-ROM Device", - "Scanner Device", - "Optical Memory Device", - "Medium Changer Device", - "Communications Device", - "Graphics Art Pre-Press Device", - "Graphics Art Pre-Press Device", - "Array Controller Device" -}; - -static char *chtostr(char *tmp, u8 *chars, int n) -{ - tmp[0] = 0; - return strncat(tmp, (char *)chars, n); -} - -static int i2o_report_query_status(struct seq_file *seq, int block_status, - char *group) -{ - switch (block_status) { - case -ETIMEDOUT: - return seq_printf(seq, "Timeout reading group %s.\n", group); - case -ENOMEM: - return seq_printf(seq, "No free memory to read the table.\n"); - case -I2O_PARAMS_STATUS_INVALID_GROUP_ID: - return seq_printf(seq, "Group %s not supported.\n", group); - default: - return seq_printf(seq, - "Error reading group %s. BlockStatus 0x%02X\n", - group, -block_status); - } -} - -static char *bus_strings[] = { - "Local Bus", - "ISA", - "EISA", - "PCI", - "PCMCIA", - "NUBUS", - "CARDBUS" -}; - -static int i2o_seq_show_hrt(struct seq_file *seq, void *v) -{ - struct i2o_controller *c = (struct i2o_controller *)seq->private; - i2o_hrt *hrt = (i2o_hrt *) c->hrt.virt; - u32 bus; - int i; - - if (hrt->hrt_version) { - seq_printf(seq, - "HRT table for controller is too new a version.\n"); - return 0; - } - - seq_printf(seq, "HRT has %d entries of %d bytes each.\n", - hrt->num_entries, hrt->entry_len << 2); - - for (i = 0; i < hrt->num_entries; i++) { - seq_printf(seq, "Entry %d:\n", i); - seq_printf(seq, " Adapter ID: %0#10x\n", - hrt->hrt_entry[i].adapter_id); - seq_printf(seq, " Controlling tid: %0#6x\n", - hrt->hrt_entry[i].parent_tid); - - if (hrt->hrt_entry[i].bus_type != 0x80) { - bus = hrt->hrt_entry[i].bus_type; - seq_printf(seq, " %s Information\n", - bus_strings[bus]); - - switch (bus) { - case I2O_BUS_LOCAL: - seq_printf(seq, " IOBase: %0#6x,", - hrt->hrt_entry[i].bus.local_bus. - LbBaseIOPort); - seq_printf(seq, " MemoryBase: %0#10x\n", - hrt->hrt_entry[i].bus.local_bus. - LbBaseMemoryAddress); - break; - - case I2O_BUS_ISA: - seq_printf(seq, " IOBase: %0#6x,", - hrt->hrt_entry[i].bus.isa_bus. - IsaBaseIOPort); - seq_printf(seq, " MemoryBase: %0#10x,", - hrt->hrt_entry[i].bus.isa_bus. - IsaBaseMemoryAddress); - seq_printf(seq, " CSN: %0#4x,", - hrt->hrt_entry[i].bus.isa_bus.CSN); - break; - - case I2O_BUS_EISA: - seq_printf(seq, " IOBase: %0#6x,", - hrt->hrt_entry[i].bus.eisa_bus. - EisaBaseIOPort); - seq_printf(seq, " MemoryBase: %0#10x,", - hrt->hrt_entry[i].bus.eisa_bus. - EisaBaseMemoryAddress); - seq_printf(seq, " Slot: %0#4x,", - hrt->hrt_entry[i].bus.eisa_bus. - EisaSlotNumber); - break; - - case I2O_BUS_PCI: - seq_printf(seq, " Bus: %0#4x", - hrt->hrt_entry[i].bus.pci_bus. - PciBusNumber); - seq_printf(seq, " Dev: %0#4x", - hrt->hrt_entry[i].bus.pci_bus. - PciDeviceNumber); - seq_printf(seq, " Func: %0#4x", - hrt->hrt_entry[i].bus.pci_bus. - PciFunctionNumber); - seq_printf(seq, " Vendor: %0#6x", - hrt->hrt_entry[i].bus.pci_bus. - PciVendorID); - seq_printf(seq, " Device: %0#6x\n", - hrt->hrt_entry[i].bus.pci_bus. - PciDeviceID); - break; - - default: - seq_printf(seq, " Unsupported Bus Type\n"); - } - } else - seq_printf(seq, " Unknown Bus Type\n"); - } - - return 0; -} - -static int i2o_seq_show_lct(struct seq_file *seq, void *v) -{ - struct i2o_controller *c = (struct i2o_controller *)seq->private; - i2o_lct *lct = (i2o_lct *) c->lct; - int entries; - int i; - -#define BUS_TABLE_SIZE 3 - static char *bus_ports[] = { - "Generic Bus", - "SCSI Bus", - "Fibre Channel Bus" - }; - - entries = (lct->table_size - 3) / 9; - - seq_printf(seq, "LCT contains %d %s\n", entries, - entries == 1 ? "entry" : "entries"); - if (lct->boot_tid) - seq_printf(seq, "Boot Device @ ID %d\n", lct->boot_tid); - - seq_printf(seq, "Current Change Indicator: %#10x\n", lct->change_ind); - - for (i = 0; i < entries; i++) { - seq_printf(seq, "Entry %d\n", i); - seq_printf(seq, " Class, SubClass : %s", - i2o_get_class_name(lct->lct_entry[i].class_id)); - - /* - * Classes which we'll print subclass info for - */ - switch (lct->lct_entry[i].class_id & 0xFFF) { - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - switch (lct->lct_entry[i].sub_class) { - case 0x00: - seq_printf(seq, ", Direct-Access Read/Write"); - break; - - case 0x04: - seq_printf(seq, ", WORM Drive"); - break; - - case 0x05: - seq_printf(seq, ", CD-ROM Drive"); - break; - - case 0x07: - seq_printf(seq, ", Optical Memory Device"); - break; - - default: - seq_printf(seq, ", Unknown (0x%02x)", - lct->lct_entry[i].sub_class); - break; - } - break; - - case I2O_CLASS_LAN: - switch (lct->lct_entry[i].sub_class & 0xFF) { - case 0x30: - seq_printf(seq, ", Ethernet"); - break; - - case 0x40: - seq_printf(seq, ", 100base VG"); - break; - - case 0x50: - seq_printf(seq, ", IEEE 802.5/Token-Ring"); - break; - - case 0x60: - seq_printf(seq, ", ANSI X3T9.5 FDDI"); - break; - - case 0x70: - seq_printf(seq, ", Fibre Channel"); - break; - - default: - seq_printf(seq, ", Unknown Sub-Class (0x%02x)", - lct->lct_entry[i].sub_class & 0xFF); - break; - } - break; - - case I2O_CLASS_SCSI_PERIPHERAL: - if (lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE) - seq_printf(seq, ", %s", - scsi_devices[lct->lct_entry[i]. - sub_class]); - else - seq_printf(seq, ", Unknown Device Type"); - break; - - case I2O_CLASS_BUS_ADAPTER: - if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) - seq_printf(seq, ", %s", - bus_ports[lct->lct_entry[i]. - sub_class]); - else - seq_printf(seq, ", Unknown Bus Type"); - break; - } - seq_printf(seq, "\n"); - - seq_printf(seq, " Local TID : 0x%03x\n", - lct->lct_entry[i].tid); - seq_printf(seq, " User TID : 0x%03x\n", - lct->lct_entry[i].user_tid); - seq_printf(seq, " Parent TID : 0x%03x\n", - lct->lct_entry[i].parent_tid); - seq_printf(seq, " Identity Tag : 0x%x%x%x%x%x%x%x%x\n", - lct->lct_entry[i].identity_tag[0], - lct->lct_entry[i].identity_tag[1], - lct->lct_entry[i].identity_tag[2], - lct->lct_entry[i].identity_tag[3], - lct->lct_entry[i].identity_tag[4], - lct->lct_entry[i].identity_tag[5], - lct->lct_entry[i].identity_tag[6], - lct->lct_entry[i].identity_tag[7]); - seq_printf(seq, " Change Indicator : %0#10x\n", - lct->lct_entry[i].change_ind); - seq_printf(seq, " Event Capab Mask : %0#10x\n", - lct->lct_entry[i].device_flags); - } - - return 0; -} - -static int i2o_seq_show_status(struct seq_file *seq, void *v) -{ - struct i2o_controller *c = (struct i2o_controller *)seq->private; - char prodstr[25]; - int version; - i2o_status_block *sb = c->status_block.virt; - - i2o_status_get(c); // reread the status block - - seq_printf(seq, "Organization ID : %0#6x\n", sb->org_id); - - version = sb->i2o_version; - -/* FIXME for Spec 2.0 - if (version == 0x02) { - seq_printf(seq, "Lowest I2O version supported: "); - switch(workspace[2]) { - case 0x00: - seq_printf(seq, "1.0\n"); - break; - case 0x01: - seq_printf(seq, "1.5\n"); - break; - case 0x02: - seq_printf(seq, "2.0\n"); - break; - } - - seq_printf(seq, "Highest I2O version supported: "); - switch(workspace[3]) { - case 0x00: - seq_printf(seq, "1.0\n"); - break; - case 0x01: - seq_printf(seq, "1.5\n"); - break; - case 0x02: - seq_printf(seq, "2.0\n"); - break; - } - } -*/ - seq_printf(seq, "IOP ID : %0#5x\n", sb->iop_id); - seq_printf(seq, "Host Unit ID : %0#6x\n", sb->host_unit_id); - seq_printf(seq, "Segment Number : %0#5x\n", sb->segment_number); - - seq_printf(seq, "I2O version : "); - switch (version) { - case 0x00: - seq_printf(seq, "1.0\n"); - break; - case 0x01: - seq_printf(seq, "1.5\n"); - break; - case 0x02: - seq_printf(seq, "2.0\n"); - break; - default: - seq_printf(seq, "Unknown version\n"); - } - - seq_printf(seq, "IOP State : "); - switch (sb->iop_state) { - case 0x01: - seq_printf(seq, "INIT\n"); - break; - - case 0x02: - seq_printf(seq, "RESET\n"); - break; - - case 0x04: - seq_printf(seq, "HOLD\n"); - break; - - case 0x05: - seq_printf(seq, "READY\n"); - break; - - case 0x08: - seq_printf(seq, "OPERATIONAL\n"); - break; - - case 0x10: - seq_printf(seq, "FAILED\n"); - break; - - case 0x11: - seq_printf(seq, "FAULTED\n"); - break; - - default: - seq_printf(seq, "Unknown\n"); - break; - } - - seq_printf(seq, "Messenger Type : "); - switch (sb->msg_type) { - case 0x00: - seq_printf(seq, "Memory mapped\n"); - break; - case 0x01: - seq_printf(seq, "Memory mapped only\n"); - break; - case 0x02: - seq_printf(seq, "Remote only\n"); - break; - case 0x03: - seq_printf(seq, "Memory mapped and remote\n"); - break; - default: - seq_printf(seq, "Unknown\n"); - } - - seq_printf(seq, "Inbound Frame Size : %d bytes\n", - sb->inbound_frame_size << 2); - seq_printf(seq, "Max Inbound Frames : %d\n", - sb->max_inbound_frames); - seq_printf(seq, "Current Inbound Frames : %d\n", - sb->cur_inbound_frames); - seq_printf(seq, "Max Outbound Frames : %d\n", - sb->max_outbound_frames); - - /* Spec doesn't say if NULL terminated or not... */ - memcpy(prodstr, sb->product_id, 24); - prodstr[24] = '\0'; - seq_printf(seq, "Product ID : %s\n", prodstr); - seq_printf(seq, "Expected LCT Size : %d bytes\n", - sb->expected_lct_size); - - seq_printf(seq, "IOP Capabilities\n"); - seq_printf(seq, " Context Field Size Support : "); - switch (sb->iop_capabilities & 0x0000003) { - case 0: - seq_printf(seq, "Supports only 32-bit context fields\n"); - break; - case 1: - seq_printf(seq, "Supports only 64-bit context fields\n"); - break; - case 2: - seq_printf(seq, "Supports 32-bit and 64-bit context fields, " - "but not concurrently\n"); - break; - case 3: - seq_printf(seq, "Supports 32-bit and 64-bit context fields " - "concurrently\n"); - break; - default: - seq_printf(seq, "0x%08x\n", sb->iop_capabilities); - } - seq_printf(seq, " Current Context Field Size : "); - switch (sb->iop_capabilities & 0x0000000C) { - case 0: - seq_printf(seq, "not configured\n"); - break; - case 4: - seq_printf(seq, "Supports only 32-bit context fields\n"); - break; - case 8: - seq_printf(seq, "Supports only 64-bit context fields\n"); - break; - case 12: - seq_printf(seq, "Supports both 32-bit or 64-bit context fields " - "concurrently\n"); - break; - default: - seq_printf(seq, "\n"); - } - seq_printf(seq, " Inbound Peer Support : %s\n", - (sb-> - iop_capabilities & 0x00000010) ? "Supported" : - "Not supported"); - seq_printf(seq, " Outbound Peer Support : %s\n", - (sb-> - iop_capabilities & 0x00000020) ? "Supported" : - "Not supported"); - seq_printf(seq, " Peer to Peer Support : %s\n", - (sb-> - iop_capabilities & 0x00000040) ? "Supported" : - "Not supported"); - - seq_printf(seq, "Desired private memory size : %d kB\n", - sb->desired_mem_size >> 10); - seq_printf(seq, "Allocated private memory size : %d kB\n", - sb->current_mem_size >> 10); - seq_printf(seq, "Private memory base address : %0#10x\n", - sb->current_mem_base); - seq_printf(seq, "Desired private I/O size : %d kB\n", - sb->desired_io_size >> 10); - seq_printf(seq, "Allocated private I/O size : %d kB\n", - sb->current_io_size >> 10); - seq_printf(seq, "Private I/O base address : %0#10x\n", - sb->current_io_base); - - return 0; -} - -static int i2o_seq_show_hw(struct seq_file *seq, void *v) -{ - struct i2o_controller *c = (struct i2o_controller *)seq->private; - static u32 work32[5]; - static u8 *work8 = (u8 *) work32; - static u16 *work16 = (u16 *) work32; - int token; - u32 hwcap; - - static char *cpu_table[] = { - "Intel 80960 series", - "AMD2900 series", - "Motorola 68000 series", - "ARM series", - "MIPS series", - "Sparc series", - "PowerPC series", - "Intel x86 series" - }; - - token = - i2o_parm_field_get(c->exec, 0x0000, -1, &work32, sizeof(work32)); - - if (token < 0) { - i2o_report_query_status(seq, token, "0x0000 IOP Hardware"); - return 0; - } - - seq_printf(seq, "I2O Vendor ID : %0#6x\n", work16[0]); - seq_printf(seq, "Product ID : %0#6x\n", work16[1]); - seq_printf(seq, "CPU : "); - if (work8[16] > 8) - seq_printf(seq, "Unknown\n"); - else - seq_printf(seq, "%s\n", cpu_table[work8[16]]); - /* Anyone using ProcessorVersion? */ - - seq_printf(seq, "RAM : %dkB\n", work32[1] >> 10); - seq_printf(seq, "Non-Volatile Mem : %dkB\n", work32[2] >> 10); - - hwcap = work32[3]; - seq_printf(seq, "Capabilities : 0x%08x\n", hwcap); - seq_printf(seq, " [%s] Self booting\n", - (hwcap & 0x00000001) ? "+" : "-"); - seq_printf(seq, " [%s] Upgradable IRTOS\n", - (hwcap & 0x00000002) ? "+" : "-"); - seq_printf(seq, " [%s] Supports downloading DDMs\n", - (hwcap & 0x00000004) ? "+" : "-"); - seq_printf(seq, " [%s] Supports installing DDMs\n", - (hwcap & 0x00000008) ? "+" : "-"); - seq_printf(seq, " [%s] Battery-backed RAM\n", - (hwcap & 0x00000010) ? "+" : "-"); - - return 0; -} - -/* Executive group 0003h - Executing DDM List (table) */ -static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) -{ - struct i2o_controller *c = (struct i2o_controller *)seq->private; - int token; - int i; - - typedef struct _i2o_exec_execute_ddm_table { - u16 ddm_tid; - u8 module_type; - u8 reserved; - u16 i2o_vendor_id; - u16 module_id; - u8 module_name_version[28]; - u32 data_size; - u32 code_size; - } i2o_exec_execute_ddm_table; - - struct { - u16 result_count; - u16 pad; - u16 block_size; - u8 block_status; - u8 error_info_size; - u16 row_count; - u16 more_flag; - i2o_exec_execute_ddm_table ddm_table[I2O_MAX_MODULES]; - } *result; - - i2o_exec_execute_ddm_table ddm_table; - char tmp[28 + 1]; - - result = kmalloc(sizeof(*result), GFP_KERNEL); - if (!result) - return -ENOMEM; - - token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0003, -1, - NULL, 0, result, sizeof(*result)); - - if (token < 0) { - i2o_report_query_status(seq, token, - "0x0003 Executing DDM List"); - goto out; - } - - seq_printf(seq, - "Tid Module_type Vendor Mod_id Module_name Vrs Data_size Code_size\n"); - ddm_table = result->ddm_table[0]; - - for (i = 0; i < result->row_count; ddm_table = result->ddm_table[++i]) { - seq_printf(seq, "0x%03x ", ddm_table.ddm_tid & 0xFFF); - - switch (ddm_table.module_type) { - case 0x01: - seq_printf(seq, "Downloaded DDM "); - break; - case 0x22: - seq_printf(seq, "Embedded DDM "); - break; - default: - seq_printf(seq, " "); - } - - seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id); - seq_printf(seq, "%-#8x", ddm_table.module_id); - seq_printf(seq, "%-29s", - chtostr(tmp, ddm_table.module_name_version, 28)); - seq_printf(seq, "%9d ", ddm_table.data_size); - seq_printf(seq, "%8d", ddm_table.code_size); - - seq_printf(seq, "\n"); - } - out: - kfree(result); - return 0; -} - -/* Executive group 0004h - Driver Store (scalar) */ -static int i2o_seq_show_driver_store(struct seq_file *seq, void *v) -{ - struct i2o_controller *c = (struct i2o_controller *)seq->private; - u32 work32[8]; - int token; - - token = - i2o_parm_field_get(c->exec, 0x0004, -1, &work32, sizeof(work32)); - if (token < 0) { - i2o_report_query_status(seq, token, "0x0004 Driver Store"); - return 0; - } - - seq_printf(seq, "Module limit : %d\n" - "Module count : %d\n" - "Current space : %d kB\n" - "Free space : %d kB\n", - work32[0], work32[1], work32[2] >> 10, work32[3] >> 10); - - return 0; -} - -/* Executive group 0005h - Driver Store Table (table) */ -static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) -{ - typedef struct _i2o_driver_store { - u16 stored_ddm_index; - u8 module_type; - u8 reserved; - u16 i2o_vendor_id; - u16 module_id; - u8 module_name_version[28]; - u8 date[8]; - u32 module_size; - u32 mpb_size; - u32 module_flags; - } i2o_driver_store_table; - - struct i2o_controller *c = (struct i2o_controller *)seq->private; - int token; - int i; - - typedef struct { - u16 result_count; - u16 pad; - u16 block_size; - u8 block_status; - u8 error_info_size; - u16 row_count; - u16 more_flag; - i2o_driver_store_table dst[I2O_MAX_MODULES]; - } i2o_driver_result_table; - - i2o_driver_result_table *result; - i2o_driver_store_table *dst; - char tmp[28 + 1]; - - result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL); - if (result == NULL) - return -ENOMEM; - - token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0005, -1, - NULL, 0, result, sizeof(*result)); - - if (token < 0) { - i2o_report_query_status(seq, token, - "0x0005 DRIVER STORE TABLE"); - kfree(result); - return 0; - } - - seq_printf(seq, - "# Module_type Vendor Mod_id Module_name Vrs" - "Date Mod_size Par_size Flags\n"); - for (i = 0, dst = &result->dst[0]; i < result->row_count; - dst = &result->dst[++i]) { - seq_printf(seq, "%-3d", dst->stored_ddm_index); - switch (dst->module_type) { - case 0x01: - seq_printf(seq, "Downloaded DDM "); - break; - case 0x22: - seq_printf(seq, "Embedded DDM "); - break; - default: - seq_printf(seq, " "); - } - - seq_printf(seq, "%-#7x", dst->i2o_vendor_id); - seq_printf(seq, "%-#8x", dst->module_id); - seq_printf(seq, "%-29s", - chtostr(tmp, dst->module_name_version, 28)); - seq_printf(seq, "%-9s", chtostr(tmp, dst->date, 8)); - seq_printf(seq, "%8d ", dst->module_size); - seq_printf(seq, "%8d ", dst->mpb_size); - seq_printf(seq, "0x%04x", dst->module_flags); - seq_printf(seq, "\n"); - } - - kfree(result); - return 0; -} - -/* Generic group F000h - Params Descriptor (table) */ -static int i2o_seq_show_groups(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - int token; - int i; - u8 properties; - - typedef struct _i2o_group_info { - u16 group_number; - u16 field_count; - u16 row_count; - u8 properties; - u8 reserved; - } i2o_group_info; - - struct { - u16 result_count; - u16 pad; - u16 block_size; - u8 block_status; - u8 error_info_size; - u16 row_count; - u16 more_flag; - i2o_group_info group[256]; - } *result; - - result = kmalloc(sizeof(*result), GFP_KERNEL); - if (!result) - return -ENOMEM; - - token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0, - result, sizeof(*result)); - - if (token < 0) { - i2o_report_query_status(seq, token, "0xF000 Params Descriptor"); - goto out; - } - - seq_printf(seq, - "# Group FieldCount RowCount Type Add Del Clear\n"); - - for (i = 0; i < result->row_count; i++) { - seq_printf(seq, "%-3d", i); - seq_printf(seq, "0x%04X ", result->group[i].group_number); - seq_printf(seq, "%10d ", result->group[i].field_count); - seq_printf(seq, "%8d ", result->group[i].row_count); - - properties = result->group[i].properties; - if (properties & 0x1) - seq_printf(seq, "Table "); - else - seq_printf(seq, "Scalar "); - if (properties & 0x2) - seq_printf(seq, " + "); - else - seq_printf(seq, " - "); - if (properties & 0x4) - seq_printf(seq, " + "); - else - seq_printf(seq, " - "); - if (properties & 0x8) - seq_printf(seq, " + "); - else - seq_printf(seq, " - "); - - seq_printf(seq, "\n"); - } - - if (result->more_flag) - seq_printf(seq, "There is more...\n"); - out: - kfree(result); - return 0; -} - -/* Generic group F001h - Physical Device Table (table) */ -static int i2o_seq_show_phys_device(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - int token; - int i; - - struct { - u16 result_count; - u16 pad; - u16 block_size; - u8 block_status; - u8 error_info_size; - u16 row_count; - u16 more_flag; - u32 adapter_id[64]; - } result; - - token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF001, -1, NULL, 0, - &result, sizeof(result)); - - if (token < 0) { - i2o_report_query_status(seq, token, - "0xF001 Physical Device Table"); - return 0; - } - - if (result.row_count) - seq_printf(seq, "# AdapterId\n"); - - for (i = 0; i < result.row_count; i++) { - seq_printf(seq, "%-2d", i); - seq_printf(seq, "%#7x\n", result.adapter_id[i]); - } - - if (result.more_flag) - seq_printf(seq, "There is more...\n"); - - return 0; -} - -/* Generic group F002h - Claimed Table (table) */ -static int i2o_seq_show_claimed(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - int token; - int i; - - struct { - u16 result_count; - u16 pad; - u16 block_size; - u8 block_status; - u8 error_info_size; - u16 row_count; - u16 more_flag; - u16 claimed_tid[64]; - } result; - - token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF002, -1, NULL, 0, - &result, sizeof(result)); - - if (token < 0) { - i2o_report_query_status(seq, token, "0xF002 Claimed Table"); - return 0; - } - - if (result.row_count) - seq_printf(seq, "# ClaimedTid\n"); - - for (i = 0; i < result.row_count; i++) { - seq_printf(seq, "%-2d", i); - seq_printf(seq, "%#7x\n", result.claimed_tid[i]); - } - - if (result.more_flag) - seq_printf(seq, "There is more...\n"); - - return 0; -} - -/* Generic group F003h - User Table (table) */ -static int i2o_seq_show_users(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - int token; - int i; - - typedef struct _i2o_user_table { - u16 instance; - u16 user_tid; - u8 claim_type; - u8 reserved1; - u16 reserved2; - } i2o_user_table; - - struct { - u16 result_count; - u16 pad; - u16 block_size; - u8 block_status; - u8 error_info_size; - u16 row_count; - u16 more_flag; - i2o_user_table user[64]; - } *result; - - result = kmalloc(sizeof(*result), GFP_KERNEL); - if (!result) - return -ENOMEM; - - token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF003, -1, NULL, 0, - result, sizeof(*result)); - - if (token < 0) { - i2o_report_query_status(seq, token, "0xF003 User Table"); - goto out; - } - - seq_printf(seq, "# Instance UserTid ClaimType\n"); - - for (i = 0; i < result->row_count; i++) { - seq_printf(seq, "%-3d", i); - seq_printf(seq, "%#8x ", result->user[i].instance); - seq_printf(seq, "%#7x ", result->user[i].user_tid); - seq_printf(seq, "%#9x\n", result->user[i].claim_type); - } - - if (result->more_flag) - seq_printf(seq, "There is more...\n"); - out: - kfree(result); - return 0; -} - -/* Generic group F005h - Private message extensions (table) (optional) */ -static int i2o_seq_show_priv_msgs(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - int token; - int i; - - typedef struct _i2o_private { - u16 ext_instance; - u16 organization_id; - u16 x_function_code; - } i2o_private; - - struct { - u16 result_count; - u16 pad; - u16 block_size; - u8 block_status; - u8 error_info_size; - u16 row_count; - u16 more_flag; - i2o_private extension[64]; - } result; - - token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0, - &result, sizeof(result)); - - if (token < 0) { - i2o_report_query_status(seq, token, - "0xF005 Private Message Extensions (optional)"); - return 0; - } - - seq_printf(seq, "Instance# OrgId FunctionCode\n"); - - for (i = 0; i < result.row_count; i++) { - seq_printf(seq, "%0#9x ", result.extension[i].ext_instance); - seq_printf(seq, "%0#6x ", result.extension[i].organization_id); - seq_printf(seq, "%0#6x", result.extension[i].x_function_code); - - seq_printf(seq, "\n"); - } - - if (result.more_flag) - seq_printf(seq, "There is more...\n"); - - return 0; -} - -/* Generic group F006h - Authorized User Table (table) */ -static int i2o_seq_show_authorized_users(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - int token; - int i; - - struct { - u16 result_count; - u16 pad; - u16 block_size; - u8 block_status; - u8 error_info_size; - u16 row_count; - u16 more_flag; - u32 alternate_tid[64]; - } result; - - token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF006, -1, NULL, 0, - &result, sizeof(result)); - - if (token < 0) { - i2o_report_query_status(seq, token, - "0xF006 Autohorized User Table"); - return 0; - } - - if (result.row_count) - seq_printf(seq, "# AlternateTid\n"); - - for (i = 0; i < result.row_count; i++) { - seq_printf(seq, "%-2d", i); - seq_printf(seq, "%#7x ", result.alternate_tid[i]); - } - - if (result.more_flag) - seq_printf(seq, "There is more...\n"); - - return 0; -} - -/* Generic group F100h - Device Identity (scalar) */ -static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - static u32 work32[128]; // allow for "stuff" + up to 256 byte (max) serial number - // == (allow) 512d bytes (max) - static u16 *work16 = (u16 *) work32; - int token; - char tmp[16 + 1]; - - token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32)); - - if (token < 0) { - i2o_report_query_status(seq, token, "0xF100 Device Identity"); - return 0; - } - - seq_printf(seq, "Device Class : %s\n", i2o_get_class_name(work16[0])); - seq_printf(seq, "Owner TID : %0#5x\n", work16[2]); - seq_printf(seq, "Parent TID : %0#5x\n", work16[3]); - seq_printf(seq, "Vendor info : %s\n", - chtostr(tmp, (u8 *) (work32 + 2), 16)); - seq_printf(seq, "Product info : %s\n", - chtostr(tmp, (u8 *) (work32 + 6), 16)); - seq_printf(seq, "Description : %s\n", - chtostr(tmp, (u8 *) (work32 + 10), 16)); - seq_printf(seq, "Product rev. : %s\n", - chtostr(tmp, (u8 *) (work32 + 14), 8)); - - seq_printf(seq, "Serial number : "); - print_serial_number(seq, (u8 *) (work32 + 16), - /* allow for SNLen plus - * possible trailing '\0' - */ - sizeof(work32) - (16 * sizeof(u32)) - 2); - seq_printf(seq, "\n"); - - return 0; -} - -static int i2o_seq_show_dev_name(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - - seq_printf(seq, "%s\n", dev_name(&d->device)); - - return 0; -} - -/* Generic group F101h - DDM Identity (scalar) */ -static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - int token; - - struct { - u16 ddm_tid; - u8 module_name[24]; - u8 module_rev[8]; - u8 sn_format; - u8 serial_number[12]; - u8 pad[256]; // allow up to 256 byte (max) serial number - } result; - - char tmp[24 + 1]; - - token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result)); - - if (token < 0) { - i2o_report_query_status(seq, token, "0xF101 DDM Identity"); - return 0; - } - - seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid); - seq_printf(seq, "Module name : %s\n", - chtostr(tmp, result.module_name, 24)); - seq_printf(seq, "Module revision : %s\n", - chtostr(tmp, result.module_rev, 8)); - - seq_printf(seq, "Serial number : "); - print_serial_number(seq, result.serial_number, sizeof(result) - 36); - /* allow for SNLen plus possible trailing '\0' */ - - seq_printf(seq, "\n"); - - return 0; -} - -/* Generic group F102h - User Information (scalar) */ -static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - int token; - - struct { - u8 device_name[64]; - u8 service_name[64]; - u8 physical_location[64]; - u8 instance_number[4]; - } result; - - char tmp[64 + 1]; - - token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result)); - - if (token < 0) { - i2o_report_query_status(seq, token, "0xF102 User Information"); - return 0; - } - - seq_printf(seq, "Device name : %s\n", - chtostr(tmp, result.device_name, 64)); - seq_printf(seq, "Service name : %s\n", - chtostr(tmp, result.service_name, 64)); - seq_printf(seq, "Physical name : %s\n", - chtostr(tmp, result.physical_location, 64)); - seq_printf(seq, "Instance number : %s\n", - chtostr(tmp, result.instance_number, 4)); - - return 0; -} - -/* Generic group F103h - SGL Operating Limits (scalar) */ -static int i2o_seq_show_sgl_limits(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - static u32 work32[12]; - static u16 *work16 = (u16 *) work32; - static u8 *work8 = (u8 *) work32; - int token; - - token = i2o_parm_field_get(d, 0xF103, -1, &work32, sizeof(work32)); - - if (token < 0) { - i2o_report_query_status(seq, token, - "0xF103 SGL Operating Limits"); - return 0; - } - - seq_printf(seq, "SGL chain size : %d\n", work32[0]); - seq_printf(seq, "Max SGL chain size : %d\n", work32[1]); - seq_printf(seq, "SGL chain size target : %d\n", work32[2]); - seq_printf(seq, "SGL frag count : %d\n", work16[6]); - seq_printf(seq, "Max SGL frag count : %d\n", work16[7]); - seq_printf(seq, "SGL frag count target : %d\n", work16[8]); - -/* FIXME - if (d->i2oversion == 0x02) - { -*/ - seq_printf(seq, "SGL data alignment : %d\n", work16[8]); - seq_printf(seq, "SGL addr limit : %d\n", work8[20]); - seq_printf(seq, "SGL addr sizes supported : "); - if (work8[21] & 0x01) - seq_printf(seq, "32 bit "); - if (work8[21] & 0x02) - seq_printf(seq, "64 bit "); - if (work8[21] & 0x04) - seq_printf(seq, "96 bit "); - if (work8[21] & 0x08) - seq_printf(seq, "128 bit "); - seq_printf(seq, "\n"); -/* - } -*/ - - return 0; -} - -/* Generic group F200h - Sensors (scalar) */ -static int i2o_seq_show_sensors(struct seq_file *seq, void *v) -{ - struct i2o_device *d = (struct i2o_device *)seq->private; - int token; - - struct { - u16 sensor_instance; - u8 component; - u16 component_instance; - u8 sensor_class; - u8 sensor_type; - u8 scaling_exponent; - u32 actual_reading; - u32 minimum_reading; - u32 low2lowcat_treshold; - u32 lowcat2low_treshold; - u32 lowwarn2low_treshold; - u32 low2lowwarn_treshold; - u32 norm2lowwarn_treshold; - u32 lowwarn2norm_treshold; - u32 nominal_reading; - u32 hiwarn2norm_treshold; - u32 norm2hiwarn_treshold; - u32 high2hiwarn_treshold; - u32 hiwarn2high_treshold; - u32 hicat2high_treshold; - u32 hi2hicat_treshold; - u32 maximum_reading; - u8 sensor_state; - u16 event_enable; - } result; - - token = i2o_parm_field_get(d, 0xF200, -1, &result, sizeof(result)); - - if (token < 0) { - i2o_report_query_status(seq, token, - "0xF200 Sensors (optional)"); - return 0; - } - - seq_printf(seq, "Sensor instance : %d\n", result.sensor_instance); - - seq_printf(seq, "Component : %d = ", result.component); - switch (result.component) { - case 0: - seq_printf(seq, "Other"); - break; - case 1: - seq_printf(seq, "Planar logic Board"); - break; - case 2: - seq_printf(seq, "CPU"); - break; - case 3: - seq_printf(seq, "Chassis"); - break; - case 4: - seq_printf(seq, "Power Supply"); - break; - case 5: - seq_printf(seq, "Storage"); - break; - case 6: - seq_printf(seq, "External"); - break; - } - seq_printf(seq, "\n"); - - seq_printf(seq, "Component instance : %d\n", - result.component_instance); - seq_printf(seq, "Sensor class : %s\n", - result.sensor_class ? "Analog" : "Digital"); - - seq_printf(seq, "Sensor type : %d = ", result.sensor_type); - switch (result.sensor_type) { - case 0: - seq_printf(seq, "Other\n"); - break; - case 1: - seq_printf(seq, "Thermal\n"); - break; - case 2: - seq_printf(seq, "DC voltage (DC volts)\n"); - break; - case 3: - seq_printf(seq, "AC voltage (AC volts)\n"); - break; - case 4: - seq_printf(seq, "DC current (DC amps)\n"); - break; - case 5: - seq_printf(seq, "AC current (AC volts)\n"); - break; - case 6: - seq_printf(seq, "Door open\n"); - break; - case 7: - seq_printf(seq, "Fan operational\n"); - break; - } - - seq_printf(seq, "Scaling exponent : %d\n", - result.scaling_exponent); - seq_printf(seq, "Actual reading : %d\n", result.actual_reading); - seq_printf(seq, "Minimum reading : %d\n", result.minimum_reading); - seq_printf(seq, "Low2LowCat treshold : %d\n", - result.low2lowcat_treshold); - seq_printf(seq, "LowCat2Low treshold : %d\n", - result.lowcat2low_treshold); - seq_printf(seq, "LowWarn2Low treshold : %d\n", - result.lowwarn2low_treshold); - seq_printf(seq, "Low2LowWarn treshold : %d\n", - result.low2lowwarn_treshold); - seq_printf(seq, "Norm2LowWarn treshold : %d\n", - result.norm2lowwarn_treshold); - seq_printf(seq, "LowWarn2Norm treshold : %d\n", - result.lowwarn2norm_treshold); - seq_printf(seq, "Nominal reading : %d\n", result.nominal_reading); - seq_printf(seq, "HiWarn2Norm treshold : %d\n", - result.hiwarn2norm_treshold); - seq_printf(seq, "Norm2HiWarn treshold : %d\n", - result.norm2hiwarn_treshold); - seq_printf(seq, "High2HiWarn treshold : %d\n", - result.high2hiwarn_treshold); - seq_printf(seq, "HiWarn2High treshold : %d\n", - result.hiwarn2high_treshold); - seq_printf(seq, "HiCat2High treshold : %d\n", - result.hicat2high_treshold); - seq_printf(seq, "High2HiCat treshold : %d\n", - result.hi2hicat_treshold); - seq_printf(seq, "Maximum reading : %d\n", result.maximum_reading); - - seq_printf(seq, "Sensor state : %d = ", result.sensor_state); - switch (result.sensor_state) { - case 0: - seq_printf(seq, "Normal\n"); - break; - case 1: - seq_printf(seq, "Abnormal\n"); - break; - case 2: - seq_printf(seq, "Unknown\n"); - break; - case 3: - seq_printf(seq, "Low Catastrophic (LoCat)\n"); - break; - case 4: - seq_printf(seq, "Low (Low)\n"); - break; - case 5: - seq_printf(seq, "Low Warning (LoWarn)\n"); - break; - case 6: - seq_printf(seq, "High Warning (HiWarn)\n"); - break; - case 7: - seq_printf(seq, "High (High)\n"); - break; - case 8: - seq_printf(seq, "High Catastrophic (HiCat)\n"); - break; - } - - seq_printf(seq, "Event_enable : 0x%02X\n", result.event_enable); - seq_printf(seq, " [%s] Operational state change. \n", - (result.event_enable & 0x01) ? "+" : "-"); - seq_printf(seq, " [%s] Low catastrophic. \n", - (result.event_enable & 0x02) ? "+" : "-"); - seq_printf(seq, " [%s] Low reading. \n", - (result.event_enable & 0x04) ? "+" : "-"); - seq_printf(seq, " [%s] Low warning. \n", - (result.event_enable & 0x08) ? "+" : "-"); - seq_printf(seq, - " [%s] Change back to normal from out of range state. \n", - (result.event_enable & 0x10) ? "+" : "-"); - seq_printf(seq, " [%s] High warning. \n", - (result.event_enable & 0x20) ? "+" : "-"); - seq_printf(seq, " [%s] High reading. \n", - (result.event_enable & 0x40) ? "+" : "-"); - seq_printf(seq, " [%s] High catastrophic. \n", - (result.event_enable & 0x80) ? "+" : "-"); - - return 0; -} - -static int i2o_seq_open_hrt(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_hrt, PDE_DATA(inode)); -}; - -static int i2o_seq_open_lct(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_lct, PDE_DATA(inode)); -}; - -static int i2o_seq_open_status(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_status, PDE_DATA(inode)); -}; - -static int i2o_seq_open_hw(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_hw, PDE_DATA(inode)); -}; - -static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_ddm_table, PDE_DATA(inode)); -}; - -static int i2o_seq_open_driver_store(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_driver_store, PDE_DATA(inode)); -}; - -static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_drivers_stored, PDE_DATA(inode)); -}; - -static int i2o_seq_open_groups(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_groups, PDE_DATA(inode)); -}; - -static int i2o_seq_open_phys_device(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_phys_device, PDE_DATA(inode)); -}; - -static int i2o_seq_open_claimed(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_claimed, PDE_DATA(inode)); -}; - -static int i2o_seq_open_users(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_users, PDE_DATA(inode)); -}; - -static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_priv_msgs, PDE_DATA(inode)); -}; - -static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_authorized_users, - PDE_DATA(inode)); -}; - -static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_dev_identity, PDE_DATA(inode)); -}; - -static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_ddm_identity, PDE_DATA(inode)); -}; - -static int i2o_seq_open_uinfo(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_uinfo, PDE_DATA(inode)); -}; - -static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_sgl_limits, PDE_DATA(inode)); -}; - -static int i2o_seq_open_sensors(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_sensors, PDE_DATA(inode)); -}; - -static int i2o_seq_open_dev_name(struct inode *inode, struct file *file) -{ - return single_open(file, i2o_seq_show_dev_name, PDE_DATA(inode)); -}; - -static const struct file_operations i2o_seq_fops_lct = { - .open = i2o_seq_open_lct, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_hrt = { - .open = i2o_seq_open_hrt, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_status = { - .open = i2o_seq_open_status, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_hw = { - .open = i2o_seq_open_hw, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_ddm_table = { - .open = i2o_seq_open_ddm_table, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_driver_store = { - .open = i2o_seq_open_driver_store, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_drivers_stored = { - .open = i2o_seq_open_drivers_stored, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_groups = { - .open = i2o_seq_open_groups, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_phys_device = { - .open = i2o_seq_open_phys_device, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_claimed = { - .open = i2o_seq_open_claimed, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_users = { - .open = i2o_seq_open_users, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_priv_msgs = { - .open = i2o_seq_open_priv_msgs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_authorized_users = { - .open = i2o_seq_open_authorized_users, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_dev_name = { - .open = i2o_seq_open_dev_name, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_dev_identity = { - .open = i2o_seq_open_dev_identity, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_ddm_identity = { - .open = i2o_seq_open_ddm_identity, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_uinfo = { - .open = i2o_seq_open_uinfo, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_sgl_limits = { - .open = i2o_seq_open_sgl_limits, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations i2o_seq_fops_sensors = { - .open = i2o_seq_open_sensors, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* - * IOP specific entries...write field just in case someone - * ever wants one. - */ -static i2o_proc_entry i2o_proc_generic_iop_entries[] = { - {"hrt", S_IFREG | S_IRUGO, &i2o_seq_fops_hrt}, - {"lct", S_IFREG | S_IRUGO, &i2o_seq_fops_lct}, - {"status", S_IFREG | S_IRUGO, &i2o_seq_fops_status}, - {"hw", S_IFREG | S_IRUGO, &i2o_seq_fops_hw}, - {"ddm_table", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_table}, - {"driver_store", S_IFREG | S_IRUGO, &i2o_seq_fops_driver_store}, - {"drivers_stored", S_IFREG | S_IRUGO, &i2o_seq_fops_drivers_stored}, - {NULL, 0, NULL} -}; - -/* - * Device specific entries - */ -static i2o_proc_entry generic_dev_entries[] = { - {"groups", S_IFREG | S_IRUGO, &i2o_seq_fops_groups}, - {"phys_dev", S_IFREG | S_IRUGO, &i2o_seq_fops_phys_device}, - {"claimed", S_IFREG | S_IRUGO, &i2o_seq_fops_claimed}, - {"users", S_IFREG | S_IRUGO, &i2o_seq_fops_users}, - {"priv_msgs", S_IFREG | S_IRUGO, &i2o_seq_fops_priv_msgs}, - {"authorized_users", S_IFREG | S_IRUGO, &i2o_seq_fops_authorized_users}, - {"dev_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_identity}, - {"ddm_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_identity}, - {"user_info", S_IFREG | S_IRUGO, &i2o_seq_fops_uinfo}, - {"sgl_limits", S_IFREG | S_IRUGO, &i2o_seq_fops_sgl_limits}, - {"sensors", S_IFREG | S_IRUGO, &i2o_seq_fops_sensors}, - {NULL, 0, NULL} -}; - -/* - * Storage unit specific entries (SCSI Periph, BS) with device names - */ -static i2o_proc_entry rbs_dev_entries[] = { - {"dev_name", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_name}, - {NULL, 0, NULL} -}; - -/** - * i2o_proc_create_entries - Creates proc dir entries - * @dir: proc dir entry under which the entries should be placed - * @i2o_pe: pointer to the entries which should be added - * @data: pointer to I2O controller or device - * - * Create proc dir entries for a I2O controller or I2O device. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_proc_create_entries(struct proc_dir_entry *dir, - i2o_proc_entry * i2o_pe, void *data) -{ - struct proc_dir_entry *tmp; - - while (i2o_pe->name) { - tmp = proc_create_data(i2o_pe->name, i2o_pe->mode, dir, - i2o_pe->fops, data); - if (!tmp) - return -1; - - i2o_pe++; - } - - return 0; -} - -/** - * i2o_proc_device_add - Add an I2O device to the proc dir - * @dir: proc dir entry to which the device should be added - * @dev: I2O device which should be added - * - * Add an I2O device to the proc dir entry dir and create the entries for - * the device depending on the class of the I2O device. - */ -static void i2o_proc_device_add(struct proc_dir_entry *dir, - struct i2o_device *dev) -{ - char buff[10]; - struct proc_dir_entry *devdir; - i2o_proc_entry *i2o_pe = NULL; - - sprintf(buff, "%03x", dev->lct_data.tid); - - osm_debug("adding device /proc/i2o/%s/%s\n", dev->iop->name, buff); - - devdir = proc_mkdir_data(buff, 0, dir, dev); - if (!devdir) { - osm_warn("Could not allocate procdir!\n"); - return; - } - - i2o_proc_create_entries(devdir, generic_dev_entries, dev); - - /* Inform core that we want updates about this device's status */ - switch (dev->lct_data.class_id) { - case I2O_CLASS_SCSI_PERIPHERAL: - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - i2o_pe = rbs_dev_entries; - break; - default: - break; - } - if (i2o_pe) - i2o_proc_create_entries(devdir, i2o_pe, dev); -} - -/** - * i2o_proc_iop_add - Add an I2O controller to the i2o proc tree - * @dir: parent proc dir entry - * @c: I2O controller which should be added - * - * Add the entries to the parent proc dir entry. Also each device is added - * to the controllers proc dir entry. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_proc_iop_add(struct proc_dir_entry *dir, - struct i2o_controller *c) -{ - struct proc_dir_entry *iopdir; - struct i2o_device *dev; - - osm_debug("adding IOP /proc/i2o/%s\n", c->name); - - iopdir = proc_mkdir_data(c->name, 0, dir, c); - if (!iopdir) - return -1; - - i2o_proc_create_entries(iopdir, i2o_proc_generic_iop_entries, c); - - list_for_each_entry(dev, &c->devices, list) - i2o_proc_device_add(iopdir, dev); - - return 0; -} - -/** - * i2o_proc_fs_create - Create the i2o proc fs. - * - * Iterate over each I2O controller and create the entries for it. - * - * Returns 0 on success or negative error code on failure. - */ -static int __init i2o_proc_fs_create(void) -{ - struct i2o_controller *c; - - i2o_proc_dir_root = proc_mkdir("i2o", NULL); - if (!i2o_proc_dir_root) - return -1; - - list_for_each_entry(c, &i2o_controllers, list) - i2o_proc_iop_add(i2o_proc_dir_root, c); - - return 0; -}; - -/** - * i2o_proc_fs_destroy - Cleanup the all i2o proc entries - * - * Iterate over each I2O controller and remove the entries for it. - * - * Returns 0 on success or negative error code on failure. - */ -static int __exit i2o_proc_fs_destroy(void) -{ - remove_proc_subtree("i2o", NULL); - - return 0; -}; - -/** - * i2o_proc_init - Init function for procfs - * - * Registers Proc OSM and creates procfs entries. - * - * Returns 0 on success or negative error code on failure. - */ -static int __init i2o_proc_init(void) -{ - int rc; - - printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); - - rc = i2o_driver_register(&i2o_proc_driver); - if (rc) - return rc; - - rc = i2o_proc_fs_create(); - if (rc) { - i2o_driver_unregister(&i2o_proc_driver); - return rc; - } - - return 0; -}; - -/** - * i2o_proc_exit - Exit function for procfs - * - * Unregisters Proc OSM and removes procfs entries. - */ -static void __exit i2o_proc_exit(void) -{ - i2o_driver_unregister(&i2o_proc_driver); - i2o_proc_fs_destroy(); -}; - -MODULE_AUTHOR("Deepak Saxena"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(OSM_DESCRIPTION); -MODULE_VERSION(OSM_VERSION); - -module_init(i2o_proc_init); -module_exit(i2o_proc_exit); diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c deleted file mode 100644 index 8152e9fa..0000000 --- a/drivers/message/i2o/i2o_scsi.c +++ /dev/null @@ -1,814 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * For the avoidance of doubt the "preferred form" of this code is one which - * is in an open non patent encumbered format. Where cryptographic key signing - * forms part of the process of creating an executable the information - * including keys needed to generate an equivalently functional executable - * are deemed to be part of the source code. - * - * Complications for I2O scsi - * - * o Each (bus,lun) is a logical device in I2O. We keep a map - * table. We spoof failed selection for unmapped units - * o Request sense buffers can come back for free. - * o Scatter gather is a bit dynamic. We have to investigate at - * setup time. - * o Some of our resources are dynamically shared. The i2o core - * needs a message reservation protocol to avoid swap v net - * deadlocking. We need to back off queue requests. - * - * In general the firmware wants to help. Where its help isn't performance - * useful we just ignore the aid. Its not worth the code in truth. - * - * Fixes/additions: - * Steve Ralston: - * Scatter gather now works - * Markus Lidel : - * Minor fixes for 2.6. - * - * To Do: - * 64bit cleanups - * Fix the resource management problems. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#define OSM_NAME "scsi-osm" -#define OSM_VERSION "1.316" -#define OSM_DESCRIPTION "I2O SCSI Peripheral OSM" - -static struct i2o_driver i2o_scsi_driver; - -static unsigned int i2o_scsi_max_id = 16; -static unsigned int i2o_scsi_max_lun = 255; - -struct i2o_scsi_host { - struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ - struct i2o_controller *iop; /* pointer to the I2O controller */ - u64 lun; /* lun's used for block devices */ - struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ -}; - -static struct scsi_host_template i2o_scsi_host_template; - -#define I2O_SCSI_CAN_QUEUE 4 - -/* SCSI OSM class handling definition */ -static struct i2o_class_id i2o_scsi_class_id[] = { - {I2O_CLASS_SCSI_PERIPHERAL}, - {I2O_CLASS_END} -}; - -static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) -{ - struct i2o_scsi_host *i2o_shost; - struct i2o_device *i2o_dev; - struct Scsi_Host *scsi_host; - int max_channel = 0; - u8 type; - int i; - size_t size; - u16 body_size = 6; - -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) - body_size = 8; -#endif - - list_for_each_entry(i2o_dev, &c->devices, list) - if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { - if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) - && (type == 0x01)) /* SCSI bus */ - max_channel++; - } - - if (!max_channel) { - osm_warn("no channels found on %s\n", c->name); - return ERR_PTR(-EFAULT); - } - - size = max_channel * sizeof(struct i2o_device *) - + sizeof(struct i2o_scsi_host); - - scsi_host = scsi_host_alloc(&i2o_scsi_host_template, size); - if (!scsi_host) { - osm_warn("Could not allocate SCSI host\n"); - return ERR_PTR(-ENOMEM); - } - - scsi_host->max_channel = max_channel - 1; - scsi_host->max_id = i2o_scsi_max_id; - scsi_host->max_lun = i2o_scsi_max_lun; - scsi_host->this_id = c->unit; - scsi_host->sg_tablesize = i2o_sg_tablesize(c, body_size); - - i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata; - i2o_shost->scsi_host = scsi_host; - i2o_shost->iop = c; - i2o_shost->lun = 1; - - i = 0; - list_for_each_entry(i2o_dev, &c->devices, list) - if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { - if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) - && (type == 0x01)) /* only SCSI bus */ - i2o_shost->channel[i++] = i2o_dev; - - if (i >= max_channel) - break; - } - - return i2o_shost; -}; - -/** - * i2o_scsi_get_host - Get an I2O SCSI host - * @c: I2O controller to for which to get the SCSI host - * - * If the I2O controller already exists as SCSI host, the SCSI host - * is returned, otherwise the I2O controller is added to the SCSI - * core. - * - * Returns pointer to the I2O SCSI host on success or NULL on failure. - */ -static struct i2o_scsi_host *i2o_scsi_get_host(struct i2o_controller *c) -{ - return c->driver_data[i2o_scsi_driver.context]; -}; - -/** - * i2o_scsi_remove - Remove I2O device from SCSI core - * @dev: device which should be removed - * - * Removes the I2O device from the SCSI core again. - * - * Returns 0 on success. - */ -static int i2o_scsi_remove(struct device *dev) -{ - struct i2o_device *i2o_dev = to_i2o_device(dev); - struct i2o_controller *c = i2o_dev->iop; - struct i2o_scsi_host *i2o_shost; - struct scsi_device *scsi_dev; - - osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid); - - i2o_shost = i2o_scsi_get_host(c); - - shost_for_each_device(scsi_dev, i2o_shost->scsi_host) - if (scsi_dev->hostdata == i2o_dev) { - sysfs_remove_link(&i2o_dev->device.kobj, "scsi"); - scsi_remove_device(scsi_dev); - scsi_device_put(scsi_dev); - break; - } - - return 0; -}; - -/** - * i2o_scsi_probe - verify if dev is a I2O SCSI device and install it - * @dev: device to verify if it is a I2O SCSI device - * - * Retrieve channel, id and lun for I2O device. If everything goes well - * register the I2O device as SCSI device on the I2O SCSI controller. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_scsi_probe(struct device *dev) -{ - struct i2o_device *i2o_dev = to_i2o_device(dev); - struct i2o_controller *c = i2o_dev->iop; - struct i2o_scsi_host *i2o_shost; - struct Scsi_Host *scsi_host; - struct i2o_device *parent; - struct scsi_device *scsi_dev; - u32 id = -1; - u64 lun = -1; - int channel = -1; - int i, rc; - - i2o_shost = i2o_scsi_get_host(c); - if (!i2o_shost) - return -EFAULT; - - scsi_host = i2o_shost->scsi_host; - - switch (i2o_dev->lct_data.class_id) { - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - case I2O_CLASS_EXECUTIVE: -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) { - u8 type; - struct i2o_device *d = i2o_shost->channel[0]; - - if (!i2o_parm_field_get(d, 0x0000, 0, &type, 1) - && (type == 0x01)) /* SCSI bus */ - if (!i2o_parm_field_get(d, 0x0200, 4, &id, 4)) { - channel = 0; - if (i2o_dev->lct_data.class_id == - I2O_CLASS_RANDOM_BLOCK_STORAGE) - lun = - cpu_to_le64(i2o_shost-> - lun++); - else - lun = 0; - } - } -#endif - break; - - case I2O_CLASS_SCSI_PERIPHERAL: - if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4)) - return -EFAULT; - - if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8)) - return -EFAULT; - - parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); - if (!parent) { - osm_warn("can not find parent of device %03x\n", - i2o_dev->lct_data.tid); - return -EFAULT; - } - - for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++) - if (i2o_shost->channel[i] == parent) - channel = i; - break; - - default: - return -EFAULT; - } - - if (channel == -1) { - osm_warn("can not find channel of device %03x\n", - i2o_dev->lct_data.tid); - return -EFAULT; - } - - if (le32_to_cpu(id) >= scsi_host->max_id) { - osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", - le32_to_cpu(id), scsi_host->max_id); - return -EFAULT; - } - - if (le64_to_cpu(lun) >= scsi_host->max_lun) { - osm_warn("SCSI device lun (%llu) >= max_lun of I2O host (%llu)", - le64_to_cpu(lun), scsi_host->max_lun); - return -EFAULT; - } - - scsi_dev = - __scsi_add_device(i2o_shost->scsi_host, channel, le32_to_cpu(id), - le64_to_cpu(lun), i2o_dev); - - if (IS_ERR(scsi_dev)) { - osm_warn("can not add SCSI device %03x\n", - i2o_dev->lct_data.tid); - return PTR_ERR(scsi_dev); - } - - rc = sysfs_create_link(&i2o_dev->device.kobj, - &scsi_dev->sdev_gendev.kobj, "scsi"); - if (rc) - goto err; - - osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %llu\n", - i2o_dev->lct_data.tid, channel, le32_to_cpu(id), - le64_to_cpu(lun)); - - return 0; - -err: - scsi_remove_device(scsi_dev); - return rc; -}; - -static const char *i2o_scsi_info(struct Scsi_Host *SChost) -{ - struct i2o_scsi_host *hostdata; - hostdata = (struct i2o_scsi_host *)SChost->hostdata; - return hostdata->iop->name; -} - -/** - * i2o_scsi_reply - SCSI OSM message reply handler - * @c: controller issuing the reply - * @m: message id for flushing - * @msg: the message from the controller - * - * Process reply messages (interrupts in normal scsi controller think). - * We can get a variety of messages to process. The normal path is - * scsi command completions. We must also deal with IOP failures, - * the reply to a bus reset and the reply to a LUN query. - * - * Returns 0 on success and if the reply should not be flushed or > 0 - * on success and if the reply should be flushed. Returns negative error - * code on failure and if the reply should be flushed. - */ -static int i2o_scsi_reply(struct i2o_controller *c, u32 m, - struct i2o_message *msg) -{ - struct scsi_cmnd *cmd; - u32 error; - struct device *dev; - - cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); - if (unlikely(!cmd)) { - osm_err("NULL reply received!\n"); - return -1; - } - - /* - * Low byte is device status, next is adapter status, - * (then one byte reserved), then request status. - */ - error = le32_to_cpu(msg->body[0]); - - osm_debug("Completed %0x%p\n", cmd); - - cmd->result = error & 0xff; - /* - * if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let - * the SCSI layer handle the error - */ - if (cmd->result) - memcpy(cmd->sense_buffer, &msg->body[3], - min(SCSI_SENSE_BUFFERSIZE, 40)); - - /* only output error code if AdapterStatus is not HBA_SUCCESS */ - if ((error >> 8) & 0xff) - osm_err("SCSI error %08x\n", error); - - dev = &c->pdev->dev; - - scsi_dma_unmap(cmd); - - cmd->scsi_done(cmd); - - return 1; -}; - -/** - * i2o_scsi_notify_device_add - Retrieve notifications of added devices - * @i2o_dev: the I2O device which was added - * - * If a I2O device is added we catch the notification, because I2O classes - * other than SCSI peripheral will not be received through - * i2o_scsi_probe(). - */ -static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev) -{ - switch (i2o_dev->lct_data.class_id) { - case I2O_CLASS_EXECUTIVE: - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - i2o_scsi_probe(&i2o_dev->device); - break; - - default: - break; - } -}; - -/** - * i2o_scsi_notify_device_remove - Retrieve notifications of removed devices - * @i2o_dev: the I2O device which was removed - * - * If a I2O device is removed, we catch the notification to remove the - * corresponding SCSI device. - */ -static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev) -{ - switch (i2o_dev->lct_data.class_id) { - case I2O_CLASS_EXECUTIVE: - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - i2o_scsi_remove(&i2o_dev->device); - break; - - default: - break; - } -}; - -/** - * i2o_scsi_notify_controller_add - Retrieve notifications of added controllers - * @c: the controller which was added - * - * If a I2O controller is added, we catch the notification to add a - * corresponding Scsi_Host. - */ -static void i2o_scsi_notify_controller_add(struct i2o_controller *c) -{ - struct i2o_scsi_host *i2o_shost; - int rc; - - i2o_shost = i2o_scsi_host_alloc(c); - if (IS_ERR(i2o_shost)) { - osm_err("Could not initialize SCSI host\n"); - return; - } - - rc = scsi_add_host(i2o_shost->scsi_host, &c->device); - if (rc) { - osm_err("Could not add SCSI host\n"); - scsi_host_put(i2o_shost->scsi_host); - return; - } - - c->driver_data[i2o_scsi_driver.context] = i2o_shost; - - osm_debug("new I2O SCSI host added\n"); -}; - -/** - * i2o_scsi_notify_controller_remove - Retrieve notifications of removed controllers - * @c: the controller which was removed - * - * If a I2O controller is removed, we catch the notification to remove the - * corresponding Scsi_Host. - */ -static void i2o_scsi_notify_controller_remove(struct i2o_controller *c) -{ - struct i2o_scsi_host *i2o_shost; - i2o_shost = i2o_scsi_get_host(c); - if (!i2o_shost) - return; - - c->driver_data[i2o_scsi_driver.context] = NULL; - - scsi_remove_host(i2o_shost->scsi_host); - scsi_host_put(i2o_shost->scsi_host); - osm_debug("I2O SCSI host removed\n"); -}; - -/* SCSI OSM driver struct */ -static struct i2o_driver i2o_scsi_driver = { - .name = OSM_NAME, - .reply = i2o_scsi_reply, - .classes = i2o_scsi_class_id, - .notify_device_add = i2o_scsi_notify_device_add, - .notify_device_remove = i2o_scsi_notify_device_remove, - .notify_controller_add = i2o_scsi_notify_controller_add, - .notify_controller_remove = i2o_scsi_notify_controller_remove, - .driver = { - .probe = i2o_scsi_probe, - .remove = i2o_scsi_remove, - }, -}; - -/** - * i2o_scsi_queuecommand - queue a SCSI command - * @SCpnt: scsi command pointer - * @done: callback for completion - * - * Issue a scsi command asynchronously. Return 0 on success or 1 if - * we hit an error (normally message queue congestion). The only - * minor complication here is that I2O deals with the device addressing - * so we have to map the bus/dev/lun back to an I2O handle as well - * as faking absent devices ourself. - * - * Locks: takes the controller lock on error path only - */ - -static int i2o_scsi_queuecommand_lck(struct scsi_cmnd *SCpnt, - void (*done) (struct scsi_cmnd *)) -{ - struct i2o_controller *c; - struct i2o_device *i2o_dev; - int tid; - struct i2o_message *msg; - /* - * ENABLE_DISCONNECT - * SIMPLE_TAG - * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME - */ - u32 scsi_flags = 0x20a00000; - u32 sgl_offset; - u32 *mptr; - u32 cmd = I2O_CMD_SCSI_EXEC << 24; - int rc = 0; - - /* - * Do the incoming paperwork - */ - i2o_dev = SCpnt->device->hostdata; - - SCpnt->scsi_done = done; - - if (unlikely(!i2o_dev)) { - osm_warn("no I2O device in request\n"); - SCpnt->result = DID_NO_CONNECT << 16; - done(SCpnt); - goto exit; - } - c = i2o_dev->iop; - tid = i2o_dev->lct_data.tid; - - osm_debug("qcmd: Tid = %03x\n", tid); - osm_debug("Real scsi messages.\n"); - - /* - * Put together a scsi execscb message - */ - switch (SCpnt->sc_data_direction) { - case PCI_DMA_NONE: - /* DATA NO XFER */ - sgl_offset = SGL_OFFSET_0; - break; - - case PCI_DMA_TODEVICE: - /* DATA OUT (iop-->dev) */ - scsi_flags |= 0x80000000; - sgl_offset = SGL_OFFSET_10; - break; - - case PCI_DMA_FROMDEVICE: - /* DATA IN (iop<--dev) */ - scsi_flags |= 0x40000000; - sgl_offset = SGL_OFFSET_10; - break; - - default: - /* Unknown - kill the command */ - SCpnt->result = DID_NO_CONNECT << 16; - done(SCpnt); - goto exit; - } - - /* - * Obtain an I2O message. If there are none free then - * throw it back to the scsi layer - */ - - msg = i2o_msg_get(c); - if (IS_ERR(msg)) { - rc = SCSI_MLQUEUE_HOST_BUSY; - goto exit; - } - - mptr = &msg->body[0]; - -#if 0 /* this code can't work */ -#ifdef CONFIG_I2O_EXT_ADAPTEC - if (c->adaptec) { - u32 adpt_flags = 0; - - if (SCpnt->sc_request && SCpnt->sc_request->upper_private_data) { - i2o_sg_io_hdr_t __user *usr_ptr = - ((Sg_request *) (SCpnt->sc_request-> - upper_private_data))->header. - usr_ptr; - - if (usr_ptr) - get_user(adpt_flags, &usr_ptr->flags); - } - - switch (i2o_dev->lct_data.class_id) { - case I2O_CLASS_EXECUTIVE: - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - /* interpret flag has to be set for executive */ - adpt_flags ^= I2O_DPT_SG_FLAG_INTERPRET; - break; - - default: - break; - } - - /* - * for Adaptec controllers we use the PRIVATE command, because - * the normal SCSI EXEC doesn't support all SCSI commands on - * all controllers (for example READ CAPACITY). - */ - if (sgl_offset == SGL_OFFSET_10) - sgl_offset = SGL_OFFSET_12; - cmd = I2O_CMD_PRIVATE << 24; - *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); - *mptr++ = cpu_to_le32(adpt_flags | tid); - } -#endif -#endif - - msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); - msg->u.s.icntxt = cpu_to_le32(i2o_scsi_driver.context); - - /* We want the SCSI control block back */ - msg->u.s.tcntxt = cpu_to_le32(i2o_cntxt_list_add(c, SCpnt)); - - /* LSI_920_PCI_QUIRK - * - * Intermittant observations of msg frame word data corruption - * observed on msg[4] after: - * WRITE, READ-MODIFY-WRITE - * operations. 19990606 -sralston - * - * (Hence we build this word via tag. Its good practice anyway - * we don't want fetches over PCI needlessly) - */ - - /* Attach tags to the devices */ - /* FIXME: implement - if(SCpnt->device->tagged_supported) { - if(SCpnt->tag == HEAD_OF_QUEUE_TAG) - scsi_flags |= 0x01000000; - else if(SCpnt->tag == ORDERED_QUEUE_TAG) - scsi_flags |= 0x01800000; - } - */ - - *mptr++ = cpu_to_le32(scsi_flags | SCpnt->cmd_len); - - /* Write SCSI command into the message - always 16 byte block */ - memcpy(mptr, SCpnt->cmnd, 16); - mptr += 4; - - if (sgl_offset != SGL_OFFSET_0) { - /* write size of data addressed by SGL */ - *mptr++ = cpu_to_le32(scsi_bufflen(SCpnt)); - - /* Now fill in the SGList and command */ - - if (scsi_sg_count(SCpnt)) { - if (!i2o_dma_map_sg(c, scsi_sglist(SCpnt), - scsi_sg_count(SCpnt), - SCpnt->sc_data_direction, &mptr)) - goto nomem; - } - } - - /* Stick the headers on */ - msg->u.head[0] = - cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset); - - /* Queue the message */ - i2o_msg_post(c, msg); - - osm_debug("Issued %0x%p\n", SCpnt); - - return 0; - - nomem: - rc = -ENOMEM; - i2o_msg_nop(c, msg); - - exit: - return rc; -} - -static DEF_SCSI_QCMD(i2o_scsi_queuecommand) - -/** - * i2o_scsi_abort - abort a running command - * @SCpnt: command to abort - * - * Ask the I2O controller to abort a command. This is an asynchrnous - * process and our callback handler will see the command complete with an - * aborted message if it succeeds. - * - * Returns 0 if the command is successfully aborted or negative error code - * on failure. - */ -static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) -{ - struct i2o_device *i2o_dev; - struct i2o_controller *c; - struct i2o_message *msg; - int tid; - int status = FAILED; - - osm_warn("Aborting command block.\n"); - - i2o_dev = SCpnt->device->hostdata; - c = i2o_dev->iop; - tid = i2o_dev->lct_data.tid; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return SCSI_MLQUEUE_HOST_BUSY; - - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid); - msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt)); - - if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT)) - status = SUCCESS; - - return status; -} - -/** - * i2o_scsi_bios_param - Invent disk geometry - * @sdev: scsi device - * @dev: block layer device - * @capacity: size in sectors - * @ip: geometry array - * - * This is anyone's guess quite frankly. We use the same rules everyone - * else appears to and hope. It seems to work. - */ - -static int i2o_scsi_bios_param(struct scsi_device *sdev, - struct block_device *dev, sector_t capacity, - int *ip) -{ - int size; - - size = capacity; - ip[0] = 64; /* heads */ - ip[1] = 32; /* sectors */ - if ((ip[2] = size >> 11) > 1024) { /* cylinders, test for big disk */ - ip[0] = 255; /* heads */ - ip[1] = 63; /* sectors */ - ip[2] = size / (255 * 63); /* cylinders */ - } - return 0; -} - -static struct scsi_host_template i2o_scsi_host_template = { - .proc_name = OSM_NAME, - .name = OSM_DESCRIPTION, - .info = i2o_scsi_info, - .queuecommand = i2o_scsi_queuecommand, - .eh_abort_handler = i2o_scsi_abort, - .bios_param = i2o_scsi_bios_param, - .can_queue = I2O_SCSI_CAN_QUEUE, - .sg_tablesize = 8, - .cmd_per_lun = 6, - .use_clustering = ENABLE_CLUSTERING, -}; - -/** - * i2o_scsi_init - SCSI OSM initialization function - * - * Register SCSI OSM into I2O core. - * - * Returns 0 on success or negative error code on failure. - */ -static int __init i2o_scsi_init(void) -{ - int rc; - - printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); - - /* Register SCSI OSM into I2O core */ - rc = i2o_driver_register(&i2o_scsi_driver); - if (rc) { - osm_err("Could not register SCSI driver\n"); - return rc; - } - - return 0; -}; - -/** - * i2o_scsi_exit - SCSI OSM exit function - * - * Unregisters SCSI OSM from I2O core. - */ -static void __exit i2o_scsi_exit(void) -{ - /* Unregister I2O SCSI OSM from I2O core */ - i2o_driver_unregister(&i2o_scsi_driver); -}; - -MODULE_AUTHOR("Red Hat Software"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(OSM_DESCRIPTION); -MODULE_VERSION(OSM_VERSION); - -module_init(i2o_scsi_init); -module_exit(i2o_scsi_exit); diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c deleted file mode 100644 index 92752fb..0000000 --- a/drivers/message/i2o/iop.c +++ /dev/null @@ -1,1247 +0,0 @@ -/* - * Functions to handle I2O controllers and I2O message handling - * - * Copyright (C) 1999-2002 Red Hat Software - * - * Written by Alan Cox, Building Number Three Ltd - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * A lot of the I2O message side code from this is taken from the - * Red Creek RCPCI45 adapter driver by Red Creek Communications - * - * Fixes/additions: - * Philipp Rumpf - * Juha Sievänen - * Auvo Häkkinen - * Deepak Saxena - * Boji T Kannanthanam - * Alan Cox : - * Ported to Linux 2.5. - * Markus Lidel : - * Minor fixes for 2.6. - */ - -#include -#include -#include -#include -#include -#include "core.h" - -#define OSM_NAME "i2o" -#define OSM_VERSION "1.325" -#define OSM_DESCRIPTION "I2O subsystem" - -/* global I2O controller list */ -LIST_HEAD(i2o_controllers); - -/* - * global I2O System Table. Contains information about all the IOPs in the - * system. Used to inform IOPs about each others existence. - */ -static struct i2o_dma i2o_systab; - -static int i2o_hrt_get(struct i2o_controller *c); - -/** - * i2o_msg_get_wait - obtain an I2O message from the IOP - * @c: I2O controller - * @wait: how long to wait until timeout - * - * This function waits up to wait seconds for a message slot to be - * available. - * - * On a success the message is returned and the pointer to the message is - * set in msg. The returned message is the physical page frame offset - * address from the read port (see the i2o spec). If no message is - * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. - */ -struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait) -{ - unsigned long timeout = jiffies + wait * HZ; - struct i2o_message *msg; - - while (IS_ERR(msg = i2o_msg_get(c))) { - if (time_after(jiffies, timeout)) { - osm_debug("%s: Timeout waiting for message frame.\n", - c->name); - return ERR_PTR(-ETIMEDOUT); - } - schedule_timeout_uninterruptible(1); - } - - return msg; -}; - -#if BITS_PER_LONG == 64 -/** - * i2o_cntxt_list_add - Append a pointer to context list and return a id - * @c: controller to which the context list belong - * @ptr: pointer to add to the context list - * - * Because the context field in I2O is only 32-bit large, on 64-bit the - * pointer is to large to fit in the context field. The i2o_cntxt_list - * functions therefore map pointers to context fields. - * - * Returns context id > 0 on success or 0 on failure. - */ -u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) -{ - struct i2o_context_list_element *entry; - unsigned long flags; - - if (!ptr) - osm_err("%s: couldn't add NULL pointer to context list!\n", - c->name); - - entry = kmalloc(sizeof(*entry), GFP_ATOMIC); - if (!entry) { - osm_err("%s: Could not allocate memory for context list element" - "\n", c->name); - return 0; - } - - entry->ptr = ptr; - entry->timestamp = jiffies; - INIT_LIST_HEAD(&entry->list); - - spin_lock_irqsave(&c->context_list_lock, flags); - - if (unlikely(atomic_inc_and_test(&c->context_list_counter))) - atomic_inc(&c->context_list_counter); - - entry->context = atomic_read(&c->context_list_counter); - - list_add(&entry->list, &c->context_list); - - spin_unlock_irqrestore(&c->context_list_lock, flags); - - osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context); - - return entry->context; -}; - -/** - * i2o_cntxt_list_remove - Remove a pointer from the context list - * @c: controller to which the context list belong - * @ptr: pointer which should be removed from the context list - * - * Removes a previously added pointer from the context list and returns - * the matching context id. - * - * Returns context id on success or 0 on failure. - */ -u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr) -{ - struct i2o_context_list_element *entry; - u32 context = 0; - unsigned long flags; - - spin_lock_irqsave(&c->context_list_lock, flags); - list_for_each_entry(entry, &c->context_list, list) - if (entry->ptr == ptr) { - list_del(&entry->list); - context = entry->context; - kfree(entry); - break; - } - spin_unlock_irqrestore(&c->context_list_lock, flags); - - if (!context) - osm_warn("%s: Could not remove nonexistent ptr %p\n", c->name, - ptr); - - osm_debug("%s: remove ptr from context list %d -> %p\n", c->name, - context, ptr); - - return context; -}; - -/** - * i2o_cntxt_list_get - Get a pointer from the context list and remove it - * @c: controller to which the context list belong - * @context: context id to which the pointer belong - * - * Returns pointer to the matching context id on success or NULL on - * failure. - */ -void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) -{ - struct i2o_context_list_element *entry; - unsigned long flags; - void *ptr = NULL; - - spin_lock_irqsave(&c->context_list_lock, flags); - list_for_each_entry(entry, &c->context_list, list) - if (entry->context == context) { - list_del(&entry->list); - ptr = entry->ptr; - kfree(entry); - break; - } - spin_unlock_irqrestore(&c->context_list_lock, flags); - - if (!ptr) - osm_warn("%s: context id %d not found\n", c->name, context); - - osm_debug("%s: get ptr from context list %d -> %p\n", c->name, context, - ptr); - - return ptr; -}; - -/** - * i2o_cntxt_list_get_ptr - Get a context id from the context list - * @c: controller to which the context list belong - * @ptr: pointer to which the context id should be fetched - * - * Returns context id which matches to the pointer on success or 0 on - * failure. - */ -u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr) -{ - struct i2o_context_list_element *entry; - u32 context = 0; - unsigned long flags; - - spin_lock_irqsave(&c->context_list_lock, flags); - list_for_each_entry(entry, &c->context_list, list) - if (entry->ptr == ptr) { - context = entry->context; - break; - } - spin_unlock_irqrestore(&c->context_list_lock, flags); - - if (!context) - osm_warn("%s: Could not find nonexistent ptr %p\n", c->name, - ptr); - - osm_debug("%s: get context id from context list %p -> %d\n", c->name, - ptr, context); - - return context; -}; -#endif - -/** - * i2o_iop_find - Find an I2O controller by id - * @unit: unit number of the I2O controller to search for - * - * Lookup the I2O controller on the controller list. - * - * Returns pointer to the I2O controller on success or NULL if not found. - */ -struct i2o_controller *i2o_find_iop(int unit) -{ - struct i2o_controller *c; - - list_for_each_entry(c, &i2o_controllers, list) { - if (c->unit == unit) - return c; - } - - return NULL; -}; - -/** - * i2o_iop_find_device - Find a I2O device on an I2O controller - * @c: I2O controller where the I2O device hangs on - * @tid: TID of the I2O device to search for - * - * Searches the devices of the I2O controller for a device with TID tid and - * returns it. - * - * Returns a pointer to the I2O device if found, otherwise NULL. - */ -struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid) -{ - struct i2o_device *dev; - - list_for_each_entry(dev, &c->devices, list) - if (dev->lct_data.tid == tid) - return dev; - - return NULL; -}; - -/** - * i2o_quiesce_controller - quiesce controller - * @c: controller - * - * Quiesce an IOP. Causes IOP to make external operation quiescent - * (i2o 'READY' state). Internal operation of the IOP continues normally. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_iop_quiesce(struct i2o_controller *c) -{ - struct i2o_message *msg; - i2o_status_block *sb = c->status_block.virt; - int rc; - - i2o_status_get(c); - - /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */ - if ((sb->iop_state != ADAPTER_STATE_READY) && - (sb->iop_state != ADAPTER_STATE_OPERATIONAL)) - return 0; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | - ADAPTER_TID); - - /* Long timeout needed for quiesce if lots of devices */ - if ((rc = i2o_msg_post_wait(c, msg, 240))) - osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc); - else - osm_debug("%s: Quiesced.\n", c->name); - - i2o_status_get(c); // Entered READY state - - return rc; -}; - -/** - * i2o_iop_enable - move controller from ready to OPERATIONAL - * @c: I2O controller - * - * Enable IOP. This allows the IOP to resume external operations and - * reverses the effect of a quiesce. Returns zero or an error code if - * an error occurs. - */ -static int i2o_iop_enable(struct i2o_controller *c) -{ - struct i2o_message *msg; - i2o_status_block *sb = c->status_block.virt; - int rc; - - i2o_status_get(c); - - /* Enable only allowed on READY state */ - if (sb->iop_state != ADAPTER_STATE_READY) - return -EINVAL; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | - ADAPTER_TID); - - /* How long of a timeout do we need? */ - if ((rc = i2o_msg_post_wait(c, msg, 240))) - osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc); - else - osm_debug("%s: Enabled.\n", c->name); - - i2o_status_get(c); // entered OPERATIONAL state - - return rc; -}; - -/** - * i2o_iop_quiesce_all - Quiesce all I2O controllers on the system - * - * Quiesce all I2O controllers which are connected to the system. - */ -static inline void i2o_iop_quiesce_all(void) -{ - struct i2o_controller *c, *tmp; - - list_for_each_entry_safe(c, tmp, &i2o_controllers, list) { - if (!c->no_quiesce) - i2o_iop_quiesce(c); - } -}; - -/** - * i2o_iop_enable_all - Enables all controllers on the system - * - * Enables all I2O controllers which are connected to the system. - */ -static inline void i2o_iop_enable_all(void) -{ - struct i2o_controller *c, *tmp; - - list_for_each_entry_safe(c, tmp, &i2o_controllers, list) - i2o_iop_enable(c); -}; - -/** - * i2o_clear_controller - Bring I2O controller into HOLD state - * @c: controller - * - * Clear an IOP to HOLD state, ie. terminate external operations, clear all - * input queues and prepare for a system restart. IOP's internal operation - * continues normally and the outbound queue is alive. The IOP is not - * expected to rebuild its LCT. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_iop_clear(struct i2o_controller *c) -{ - struct i2o_message *msg; - int rc; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - /* Quiesce all IOPs first */ - i2o_iop_quiesce_all(); - - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | - ADAPTER_TID); - - if ((rc = i2o_msg_post_wait(c, msg, 30))) - osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc); - else - osm_debug("%s: Cleared.\n", c->name); - - /* Enable all IOPs */ - i2o_iop_enable_all(); - - return rc; -} - -/** - * i2o_iop_init_outbound_queue - setup the outbound message queue - * @c: I2O controller - * - * Clear and (re)initialize IOP's outbound queue and post the message - * frames to the IOP. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_iop_init_outbound_queue(struct i2o_controller *c) -{ - u32 m; - volatile u8 *status = c->status.virt; - struct i2o_message *msg; - ulong timeout; - int i; - - osm_debug("%s: Initializing Outbound Queue...\n", c->name); - - memset(c->status.virt, 0, 4); - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); - msg->u.s.tcntxt = cpu_to_le32(0x00000000); - msg->body[0] = cpu_to_le32(PAGE_SIZE); - /* Outbound msg frame size in words and Initcode */ - msg->body[1] = cpu_to_le32(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80); - msg->body[2] = cpu_to_le32(0xd0000004); - msg->body[3] = cpu_to_le32(i2o_dma_low(c->status.phys)); - msg->body[4] = cpu_to_le32(i2o_dma_high(c->status.phys)); - - i2o_msg_post(c, msg); - - timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ; - while (*status <= I2O_CMD_IN_PROGRESS) { - if (time_after(jiffies, timeout)) { - osm_warn("%s: Timeout Initializing\n", c->name); - return -ETIMEDOUT; - } - schedule_timeout_uninterruptible(1); - } - - m = c->out_queue.phys; - - /* Post frames */ - for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) { - i2o_flush_reply(c, m); - udelay(1); /* Promise */ - m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32); - } - - return 0; -} - -/** - * i2o_iop_reset - reset an I2O controller - * @c: controller to reset - * - * Reset the IOP into INIT state and wait until IOP gets into RESET state. - * Terminate all external operations, clear IOP's inbound and outbound - * queues, terminate all DDMs, and reload the IOP's operating environment - * and all local DDMs. The IOP rebuilds its LCT. - */ -static int i2o_iop_reset(struct i2o_controller *c) -{ - volatile u8 *status = c->status.virt; - struct i2o_message *msg; - unsigned long timeout; - i2o_status_block *sb = c->status_block.virt; - int rc = 0; - - osm_debug("%s: Resetting controller\n", c->name); - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - memset(c->status_block.virt, 0, 8); - - /* Quiesce all IOPs first */ - i2o_iop_quiesce_all(); - - msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); - msg->u.s.tcntxt = cpu_to_le32(0x00000000); - msg->body[0] = cpu_to_le32(0x00000000); - msg->body[1] = cpu_to_le32(0x00000000); - msg->body[2] = cpu_to_le32(i2o_dma_low(c->status.phys)); - msg->body[3] = cpu_to_le32(i2o_dma_high(c->status.phys)); - - i2o_msg_post(c, msg); - - /* Wait for a reply */ - timeout = jiffies + I2O_TIMEOUT_RESET * HZ; - while (!*status) { - if (time_after(jiffies, timeout)) - break; - - schedule_timeout_uninterruptible(1); - } - - switch (*status) { - case I2O_CMD_REJECTED: - osm_warn("%s: IOP reset rejected\n", c->name); - rc = -EPERM; - break; - - case I2O_CMD_IN_PROGRESS: - /* - * Once the reset is sent, the IOP goes into the INIT state - * which is indeterminate. We need to wait until the IOP has - * rebooted before we can let the system talk to it. We read - * the inbound Free_List until a message is available. If we - * can't read one in the given amount of time, we assume the - * IOP could not reboot properly. - */ - osm_debug("%s: Reset in progress, waiting for reboot...\n", - c->name); - - while (IS_ERR(msg = i2o_msg_get_wait(c, I2O_TIMEOUT_RESET))) { - if (time_after(jiffies, timeout)) { - osm_err("%s: IOP reset timeout.\n", c->name); - rc = PTR_ERR(msg); - goto exit; - } - schedule_timeout_uninterruptible(1); - } - i2o_msg_nop(c, msg); - - /* from here all quiesce commands are safe */ - c->no_quiesce = 0; - - /* verify if controller is in state RESET */ - i2o_status_get(c); - - if (!c->promise && (sb->iop_state != ADAPTER_STATE_RESET)) - osm_warn("%s: reset completed, but adapter not in RESET" - " state.\n", c->name); - else - osm_debug("%s: reset completed.\n", c->name); - - break; - - default: - osm_err("%s: IOP reset timeout.\n", c->name); - rc = -ETIMEDOUT; - break; - } - - exit: - /* Enable all IOPs */ - i2o_iop_enable_all(); - - return rc; -}; - -/** - * i2o_iop_activate - Bring controller up to HOLD - * @c: controller - * - * This function brings an I2O controller into HOLD state. The adapter - * is reset if necessary and then the queues and resource table are read. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_iop_activate(struct i2o_controller *c) -{ - i2o_status_block *sb = c->status_block.virt; - int rc; - int state; - - /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */ - /* In READY state, Get status */ - - rc = i2o_status_get(c); - if (rc) { - osm_info("%s: Unable to obtain status, attempting a reset.\n", - c->name); - rc = i2o_iop_reset(c); - if (rc) - return rc; - } - - if (sb->i2o_version > I2OVER15) { - osm_err("%s: Not running version 1.5 of the I2O Specification." - "\n", c->name); - return -ENODEV; - } - - switch (sb->iop_state) { - case ADAPTER_STATE_FAULTED: - osm_err("%s: hardware fault\n", c->name); - return -EFAULT; - - case ADAPTER_STATE_READY: - case ADAPTER_STATE_OPERATIONAL: - case ADAPTER_STATE_HOLD: - case ADAPTER_STATE_FAILED: - osm_debug("%s: already running, trying to reset...\n", c->name); - rc = i2o_iop_reset(c); - if (rc) - return rc; - } - - /* preserve state */ - state = sb->iop_state; - - rc = i2o_iop_init_outbound_queue(c); - if (rc) - return rc; - - /* if adapter was not in RESET state clear now */ - if (state != ADAPTER_STATE_RESET) - i2o_iop_clear(c); - - i2o_status_get(c); - - if (sb->iop_state != ADAPTER_STATE_HOLD) { - osm_err("%s: failed to bring IOP into HOLD state\n", c->name); - return -EIO; - } - - return i2o_hrt_get(c); -}; - -static void i2o_res_alloc(struct i2o_controller *c, unsigned long flags) -{ - i2o_status_block *sb = c->status_block.virt; - struct resource *res = &c->mem_resource; - resource_size_t size, align; - int err; - - res->name = c->pdev->bus->name; - res->flags = flags; - res->start = 0; - res->end = 0; - osm_info("%s: requires private memory resources.\n", c->name); - - if (flags & IORESOURCE_MEM) { - size = sb->desired_mem_size; - align = 1 << 20; /* unspecified, use 1Mb and play safe */ - } else { - size = sb->desired_io_size; - align = 1 << 12; /* unspecified, use 4Kb and play safe */ - } - - err = pci_bus_alloc_resource(c->pdev->bus, res, size, align, 0, 0, - NULL, NULL); - if (err < 0) - return; - - if (flags & IORESOURCE_MEM) { - c->mem_alloc = 1; - sb->current_mem_size = resource_size(res); - sb->current_mem_base = res->start; - } else if (flags & IORESOURCE_IO) { - c->io_alloc = 1; - sb->current_io_size = resource_size(res); - sb->current_io_base = res->start; - } - osm_info("%s: allocated PCI space %pR\n", c->name, res); -} - -/** - * i2o_iop_systab_set - Set the I2O System Table of the specified IOP - * @c: I2O controller to which the system table should be send - * - * Before the systab could be set i2o_systab_build() must be called. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_iop_systab_set(struct i2o_controller *c) -{ - struct i2o_message *msg; - i2o_status_block *sb = c->status_block.virt; - struct device *dev = &c->pdev->dev; - int rc; - - if (sb->current_mem_size < sb->desired_mem_size) - i2o_res_alloc(c, IORESOURCE_MEM); - - if (sb->current_io_size < sb->desired_io_size) - i2o_res_alloc(c, IORESOURCE_IO); - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len, - PCI_DMA_TODEVICE); - if (!i2o_systab.phys) { - i2o_msg_nop(c, msg); - return -ENOMEM; - } - - msg->u.head[0] = cpu_to_le32(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | - ADAPTER_TID); - - /* - * Provide three SGL-elements: - * System table (SysTab), Private memory space declaration and - * Private i/o space declaration - */ - - msg->body[0] = cpu_to_le32(c->unit + 2); - msg->body[1] = cpu_to_le32(0x00000000); - msg->body[2] = cpu_to_le32(0x54000000 | i2o_systab.len); - msg->body[3] = cpu_to_le32(i2o_systab.phys); - msg->body[4] = cpu_to_le32(0x54000000 | sb->current_mem_size); - msg->body[5] = cpu_to_le32(sb->current_mem_base); - msg->body[6] = cpu_to_le32(0xd4000000 | sb->current_io_size); - msg->body[6] = cpu_to_le32(sb->current_io_base); - - rc = i2o_msg_post_wait(c, msg, 120); - - dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len, - PCI_DMA_TODEVICE); - - if (rc < 0) - osm_err("%s: Unable to set SysTab (status=%#x).\n", c->name, - -rc); - else - osm_debug("%s: SysTab set.\n", c->name); - - return rc; -} - -/** - * i2o_iop_online - Bring a controller online into OPERATIONAL state. - * @c: I2O controller - * - * Send the system table and enable the I2O controller. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_iop_online(struct i2o_controller *c) -{ - int rc; - - rc = i2o_iop_systab_set(c); - if (rc) - return rc; - - /* In READY state */ - osm_debug("%s: Attempting to enable...\n", c->name); - rc = i2o_iop_enable(c); - if (rc) - return rc; - - return 0; -}; - -/** - * i2o_iop_remove - Remove the I2O controller from the I2O core - * @c: I2O controller - * - * Remove the I2O controller from the I2O core. If devices are attached to - * the controller remove these also and finally reset the controller. - */ -void i2o_iop_remove(struct i2o_controller *c) -{ - struct i2o_device *dev, *tmp; - - osm_debug("%s: deleting controller\n", c->name); - - i2o_driver_notify_controller_remove_all(c); - - list_del(&c->list); - - list_for_each_entry_safe(dev, tmp, &c->devices, list) - i2o_device_remove(dev); - - device_del(&c->device); - - /* Ask the IOP to switch to RESET state */ - i2o_iop_reset(c); -} - -/** - * i2o_systab_build - Build system table - * - * The system table contains information about all the IOPs in the system - * (duh) and is used by the Executives on the IOPs to establish peer2peer - * connections. We're not supporting peer2peer at the moment, but this - * will be needed down the road for things like lan2lan forwarding. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_systab_build(void) -{ - struct i2o_controller *c, *tmp; - int num_controllers = 0; - u32 change_ind = 0; - int count = 0; - struct i2o_sys_tbl *systab = i2o_systab.virt; - - list_for_each_entry_safe(c, tmp, &i2o_controllers, list) - num_controllers++; - - if (systab) { - change_ind = systab->change_ind; - kfree(i2o_systab.virt); - } - - /* Header + IOPs */ - i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers * - sizeof(struct i2o_sys_tbl_entry); - - systab = i2o_systab.virt = kzalloc(i2o_systab.len, GFP_KERNEL); - if (!systab) { - osm_err("unable to allocate memory for System Table\n"); - return -ENOMEM; - } - - systab->version = I2OVERSION; - systab->change_ind = change_ind + 1; - - list_for_each_entry_safe(c, tmp, &i2o_controllers, list) { - i2o_status_block *sb; - - if (count >= num_controllers) { - osm_err("controller added while building system table" - "\n"); - break; - } - - sb = c->status_block.virt; - - /* - * Get updated IOP state so we have the latest information - * - * We should delete the controller at this point if it - * doesn't respond since if it's not on the system table - * it is techninically not part of the I2O subsystem... - */ - if (unlikely(i2o_status_get(c))) { - osm_err("%s: Deleting b/c could not get status while " - "attempting to build system table\n", c->name); - i2o_iop_remove(c); - continue; // try the next one - } - - systab->iops[count].org_id = sb->org_id; - systab->iops[count].iop_id = c->unit + 2; - systab->iops[count].seg_num = 0; - systab->iops[count].i2o_version = sb->i2o_version; - systab->iops[count].iop_state = sb->iop_state; - systab->iops[count].msg_type = sb->msg_type; - systab->iops[count].frame_size = sb->inbound_frame_size; - systab->iops[count].last_changed = change_ind; - systab->iops[count].iop_capabilities = sb->iop_capabilities; - systab->iops[count].inbound_low = - i2o_dma_low(c->base.phys + I2O_IN_PORT); - systab->iops[count].inbound_high = - i2o_dma_high(c->base.phys + I2O_IN_PORT); - - count++; - } - - systab->num_entries = count; - - return 0; -}; - -/** - * i2o_parse_hrt - Parse the hardware resource table. - * @c: I2O controller - * - * We don't do anything with it except dumping it (in debug mode). - * - * Returns 0. - */ -static int i2o_parse_hrt(struct i2o_controller *c) -{ - i2o_dump_hrt(c); - return 0; -}; - -/** - * i2o_status_get - Get the status block from the I2O controller - * @c: I2O controller - * - * Issue a status query on the controller. This updates the attached - * status block. The status block could then be accessed through - * c->status_block. - * - * Returns 0 on success or negative error code on failure. - */ -int i2o_status_get(struct i2o_controller *c) -{ - struct i2o_message *msg; - volatile u8 *status_block; - unsigned long timeout; - - status_block = (u8 *) c->status_block.virt; - memset(c->status_block.virt, 0, sizeof(i2o_status_block)); - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); - msg->u.s.tcntxt = cpu_to_le32(0x00000000); - msg->body[0] = cpu_to_le32(0x00000000); - msg->body[1] = cpu_to_le32(0x00000000); - msg->body[2] = cpu_to_le32(i2o_dma_low(c->status_block.phys)); - msg->body[3] = cpu_to_le32(i2o_dma_high(c->status_block.phys)); - msg->body[4] = cpu_to_le32(sizeof(i2o_status_block)); /* always 88 bytes */ - - i2o_msg_post(c, msg); - - /* Wait for a reply */ - timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ; - while (status_block[87] != 0xFF) { - if (time_after(jiffies, timeout)) { - osm_err("%s: Get status timeout.\n", c->name); - return -ETIMEDOUT; - } - - schedule_timeout_uninterruptible(1); - } - -#ifdef DEBUG - i2o_debug_state(c); -#endif - - return 0; -} - -/* - * i2o_hrt_get - Get the Hardware Resource Table from the I2O controller - * @c: I2O controller from which the HRT should be fetched - * - * The HRT contains information about possible hidden devices but is - * mostly useless to us. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_hrt_get(struct i2o_controller *c) -{ - int rc; - int i; - i2o_hrt *hrt = c->hrt.virt; - u32 size = sizeof(i2o_hrt); - struct device *dev = &c->pdev->dev; - - for (i = 0; i < I2O_HRT_GET_TRIES; i++) { - struct i2o_message *msg; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(SIX_WORD_MSG_SIZE | SGL_OFFSET_4); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->body[0] = cpu_to_le32(0xd0000000 | c->hrt.len); - msg->body[1] = cpu_to_le32(c->hrt.phys); - - rc = i2o_msg_post_wait_mem(c, msg, 20, &c->hrt); - - if (rc < 0) { - osm_err("%s: Unable to get HRT (status=%#x)\n", c->name, - -rc); - return rc; - } - - size = hrt->num_entries * hrt->entry_len << 2; - if (size > c->hrt.len) { - if (i2o_dma_realloc(dev, &c->hrt, size)) - return -ENOMEM; - else - hrt = c->hrt.virt; - } else - return i2o_parse_hrt(c); - } - - osm_err("%s: Unable to get HRT after %d tries, giving up\n", c->name, - I2O_HRT_GET_TRIES); - - return -EBUSY; -} - -/** - * i2o_iop_release - release the memory for a I2O controller - * @dev: I2O controller which should be released - * - * Release the allocated memory. This function is called if refcount of - * device reaches 0 automatically. - */ -static void i2o_iop_release(struct device *dev) -{ - struct i2o_controller *c = to_i2o_controller(dev); - - i2o_iop_free(c); -}; - -/** - * i2o_iop_alloc - Allocate and initialize a i2o_controller struct - * - * Allocate the necessary memory for a i2o_controller struct and - * initialize the lists and message mempool. - * - * Returns a pointer to the I2O controller or a negative error code on - * failure. - */ -struct i2o_controller *i2o_iop_alloc(void) -{ - static int unit = 0; /* 0 and 1 are NULL IOP and Local Host */ - struct i2o_controller *c; - char poolname[32]; - - c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) { - osm_err("i2o: Insufficient memory to allocate a I2O controller." - "\n"); - return ERR_PTR(-ENOMEM); - } - - c->unit = unit++; - sprintf(c->name, "iop%d", c->unit); - - snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name); - if (i2o_pool_alloc - (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32), - I2O_MSG_INPOOL_MIN)) { - kfree(c); - return ERR_PTR(-ENOMEM); - }; - - INIT_LIST_HEAD(&c->devices); - spin_lock_init(&c->lock); - mutex_init(&c->lct_lock); - - device_initialize(&c->device); - - c->device.release = &i2o_iop_release; - - dev_set_name(&c->device, "iop%d", c->unit); - -#if BITS_PER_LONG == 64 - spin_lock_init(&c->context_list_lock); - atomic_set(&c->context_list_counter, 0); - INIT_LIST_HEAD(&c->context_list); -#endif - - return c; -}; - -/** - * i2o_iop_add - Initialize the I2O controller and add him to the I2O core - * @c: controller - * - * Initialize the I2O controller and if no error occurs add him to the I2O - * core. - * - * Returns 0 on success or negative error code on failure. - */ -int i2o_iop_add(struct i2o_controller *c) -{ - int rc; - - if ((rc = device_add(&c->device))) { - osm_err("%s: could not add controller\n", c->name); - goto iop_reset; - } - - osm_info("%s: Activating I2O controller...\n", c->name); - osm_info("%s: This may take a few minutes if there are many devices\n", - c->name); - - if ((rc = i2o_iop_activate(c))) { - osm_err("%s: could not activate controller\n", c->name); - goto device_del; - } - - osm_debug("%s: building sys table...\n", c->name); - - if ((rc = i2o_systab_build())) - goto device_del; - - osm_debug("%s: online controller...\n", c->name); - - if ((rc = i2o_iop_online(c))) - goto device_del; - - osm_debug("%s: getting LCT...\n", c->name); - - if ((rc = i2o_exec_lct_get(c))) - goto device_del; - - list_add(&c->list, &i2o_controllers); - - i2o_driver_notify_controller_add_all(c); - - osm_info("%s: Controller added\n", c->name); - - return 0; - - device_del: - device_del(&c->device); - - iop_reset: - i2o_iop_reset(c); - - return rc; -}; - -/** - * i2o_event_register - Turn on/off event notification for a I2O device - * @dev: I2O device which should receive the event registration request - * @drv: driver which want to get notified - * @tcntxt: transaction context to use with this notifier - * @evt_mask: mask of events - * - * Create and posts an event registration message to the task. No reply - * is waited for, or expected. If you do not want further notifications, - * call the i2o_event_register again with a evt_mask of 0. - * - * Returns 0 on success or negative error code on failure. - */ -int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv, - int tcntxt, u32 evt_mask) -{ - struct i2o_controller *c = dev->iop; - struct i2o_message *msg; - - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev-> - lct_data.tid); - msg->u.s.icntxt = cpu_to_le32(drv->context); - msg->u.s.tcntxt = cpu_to_le32(tcntxt); - msg->body[0] = cpu_to_le32(evt_mask); - - i2o_msg_post(c, msg); - - return 0; -}; - -/** - * i2o_iop_init - I2O main initialization function - * - * Initialize the I2O drivers (OSM) functions, register the Executive OSM, - * initialize the I2O PCI part and finally initialize I2O device stuff. - * - * Returns 0 on success or negative error code on failure. - */ -static int __init i2o_iop_init(void) -{ - int rc = 0; - - printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); - - if ((rc = i2o_driver_init())) - goto exit; - - if ((rc = i2o_exec_init())) - goto driver_exit; - - if ((rc = i2o_pci_init())) - goto exec_exit; - - return 0; - - exec_exit: - i2o_exec_exit(); - - driver_exit: - i2o_driver_exit(); - - exit: - return rc; -} - -/** - * i2o_iop_exit - I2O main exit function - * - * Removes I2O controllers from PCI subsystem and shut down OSMs. - */ -static void __exit i2o_iop_exit(void) -{ - i2o_pci_exit(); - i2o_exec_exit(); - i2o_driver_exit(); -}; - -module_init(i2o_iop_init); -module_exit(i2o_iop_exit); - -MODULE_AUTHOR("Red Hat Software"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(OSM_DESCRIPTION); -MODULE_VERSION(OSM_VERSION); - -#if BITS_PER_LONG == 64 -EXPORT_SYMBOL(i2o_cntxt_list_add); -EXPORT_SYMBOL(i2o_cntxt_list_get); -EXPORT_SYMBOL(i2o_cntxt_list_remove); -EXPORT_SYMBOL(i2o_cntxt_list_get_ptr); -#endif -EXPORT_SYMBOL(i2o_msg_get_wait); -EXPORT_SYMBOL(i2o_find_iop); -EXPORT_SYMBOL(i2o_iop_find_device); -EXPORT_SYMBOL(i2o_event_register); -EXPORT_SYMBOL(i2o_status_get); -EXPORT_SYMBOL(i2o_controllers); diff --git a/drivers/message/i2o/memory.c b/drivers/message/i2o/memory.c deleted file mode 100644 index 292b41e..0000000 --- a/drivers/message/i2o/memory.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Functions to handle I2O memory - * - * Pulled from the inlines in i2o headers and uninlined - * - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include "core.h" - -/* Protects our 32/64bit mask switching */ -static DEFINE_MUTEX(mem_lock); - -/** - * i2o_sg_tablesize - Calculate the maximum number of elements in a SGL - * @c: I2O controller for which the calculation should be done - * @body_size: maximum body size used for message in 32-bit words. - * - * Return the maximum number of SG elements in a SG list. - */ -u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size) -{ - i2o_status_block *sb = c->status_block.virt; - u16 sg_count = - (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) - - body_size; - - if (c->pae_support) { - /* - * for 64-bit a SG attribute element must be added and each - * SG element needs 12 bytes instead of 8. - */ - sg_count -= 2; - sg_count /= 3; - } else - sg_count /= 2; - - if (c->short_req && (sg_count > 8)) - sg_count = 8; - - return sg_count; -} -EXPORT_SYMBOL_GPL(i2o_sg_tablesize); - - -/** - * i2o_dma_map_single - Map pointer to controller and fill in I2O message. - * @c: I2O controller - * @ptr: pointer to the data which should be mapped - * @size: size of data in bytes - * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE - * @sg_ptr: pointer to the SG list inside the I2O message - * - * This function does all necessary DMA handling and also writes the I2O - * SGL elements into the I2O message. For details on DMA handling see also - * dma_map_single(). The pointer sg_ptr will only be set to the end of the - * SG list if the allocation was successful. - * - * Returns DMA address which must be checked for failures using - * dma_mapping_error(). - */ -dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr, - size_t size, - enum dma_data_direction direction, - u32 ** sg_ptr) -{ - u32 sg_flags; - u32 *mptr = *sg_ptr; - dma_addr_t dma_addr; - - switch (direction) { - case DMA_TO_DEVICE: - sg_flags = 0xd4000000; - break; - case DMA_FROM_DEVICE: - sg_flags = 0xd0000000; - break; - default: - return 0; - } - - dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction); - if (!dma_mapping_error(&c->pdev->dev, dma_addr)) { -#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 - if ((sizeof(dma_addr_t) > 4) && c->pae_support) { - *mptr++ = cpu_to_le32(0x7C020002); - *mptr++ = cpu_to_le32(PAGE_SIZE); - } -#endif - - *mptr++ = cpu_to_le32(sg_flags | size); - *mptr++ = cpu_to_le32(i2o_dma_low(dma_addr)); -#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 - if ((sizeof(dma_addr_t) > 4) && c->pae_support) - *mptr++ = cpu_to_le32(i2o_dma_high(dma_addr)); -#endif - *sg_ptr = mptr; - } - return dma_addr; -} -EXPORT_SYMBOL_GPL(i2o_dma_map_single); - -/** - * i2o_dma_map_sg - Map a SG List to controller and fill in I2O message. - * @c: I2O controller - * @sg: SG list to be mapped - * @sg_count: number of elements in the SG list - * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE - * @sg_ptr: pointer to the SG list inside the I2O message - * - * This function does all necessary DMA handling and also writes the I2O - * SGL elements into the I2O message. For details on DMA handling see also - * dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG - * list if the allocation was successful. - * - * Returns 0 on failure or 1 on success. - */ -int i2o_dma_map_sg(struct i2o_controller *c, struct scatterlist *sg, - int sg_count, enum dma_data_direction direction, u32 ** sg_ptr) -{ - u32 sg_flags; - u32 *mptr = *sg_ptr; - - switch (direction) { - case DMA_TO_DEVICE: - sg_flags = 0x14000000; - break; - case DMA_FROM_DEVICE: - sg_flags = 0x10000000; - break; - default: - return 0; - } - - sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction); - if (!sg_count) - return 0; - -#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 - if ((sizeof(dma_addr_t) > 4) && c->pae_support) { - *mptr++ = cpu_to_le32(0x7C020002); - *mptr++ = cpu_to_le32(PAGE_SIZE); - } -#endif - - while (sg_count-- > 0) { - if (!sg_count) - sg_flags |= 0xC0000000; - *mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg)); - *mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg))); -#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 - if ((sizeof(dma_addr_t) > 4) && c->pae_support) - *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg))); -#endif - sg = sg_next(sg); - } - *sg_ptr = mptr; - - return 1; -} -EXPORT_SYMBOL_GPL(i2o_dma_map_sg); - -/** - * i2o_dma_alloc - Allocate DMA memory - * @dev: struct device pointer to the PCI device of the I2O controller - * @addr: i2o_dma struct which should get the DMA buffer - * @len: length of the new DMA memory - * - * Allocate a coherent DMA memory and write the pointers into addr. - * - * Returns 0 on success or -ENOMEM on failure. - */ -int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len) -{ - struct pci_dev *pdev = to_pci_dev(dev); - int dma_64 = 0; - - mutex_lock(&mem_lock); - if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_BIT_MASK(64))) { - dma_64 = 1; - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - mutex_unlock(&mem_lock); - return -ENOMEM; - } - } - - addr->virt = dma_alloc_coherent(dev, len, &addr->phys, GFP_KERNEL); - - if ((sizeof(dma_addr_t) > 4) && dma_64) - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) - printk(KERN_WARNING "i2o: unable to set 64-bit DMA"); - mutex_unlock(&mem_lock); - - if (!addr->virt) - return -ENOMEM; - - memset(addr->virt, 0, len); - addr->len = len; - - return 0; -} -EXPORT_SYMBOL_GPL(i2o_dma_alloc); - - -/** - * i2o_dma_free - Free DMA memory - * @dev: struct device pointer to the PCI device of the I2O controller - * @addr: i2o_dma struct which contains the DMA buffer - * - * Free a coherent DMA memory and set virtual address of addr to NULL. - */ -void i2o_dma_free(struct device *dev, struct i2o_dma *addr) -{ - if (addr->virt) { - if (addr->phys) - dma_free_coherent(dev, addr->len, addr->virt, - addr->phys); - else - kfree(addr->virt); - addr->virt = NULL; - } -} -EXPORT_SYMBOL_GPL(i2o_dma_free); - - -/** - * i2o_dma_realloc - Realloc DMA memory - * @dev: struct device pointer to the PCI device of the I2O controller - * @addr: pointer to a i2o_dma struct DMA buffer - * @len: new length of memory - * - * If there was something allocated in the addr, free it first. If len > 0 - * than try to allocate it and write the addresses back to the addr - * structure. If len == 0 set the virtual address to NULL. - * - * Returns the 0 on success or negative error code on failure. - */ -int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len) -{ - i2o_dma_free(dev, addr); - - if (len) - return i2o_dma_alloc(dev, addr, len); - - return 0; -} -EXPORT_SYMBOL_GPL(i2o_dma_realloc); - -/* - * i2o_pool_alloc - Allocate an slab cache and mempool - * @mempool: pointer to struct i2o_pool to write data into. - * @name: name which is used to identify cache - * @size: size of each object - * @min_nr: minimum number of objects - * - * First allocates a slab cache with name and size. Then allocates a - * mempool which uses the slab cache for allocation and freeing. - * - * Returns 0 on success or negative error code on failure. - */ -int i2o_pool_alloc(struct i2o_pool *pool, const char *name, - size_t size, int min_nr) -{ - pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL); - if (!pool->name) - goto exit; - strcpy(pool->name, name); - - pool->slab = - kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL); - if (!pool->slab) - goto free_name; - - pool->mempool = mempool_create_slab_pool(min_nr, pool->slab); - if (!pool->mempool) - goto free_slab; - - return 0; - -free_slab: - kmem_cache_destroy(pool->slab); - -free_name: - kfree(pool->name); - -exit: - return -ENOMEM; -} -EXPORT_SYMBOL_GPL(i2o_pool_alloc); - -/* - * i2o_pool_free - Free slab cache and mempool again - * @mempool: pointer to struct i2o_pool which should be freed - * - * Note that you have to return all objects to the mempool again before - * calling i2o_pool_free(). - */ -void i2o_pool_free(struct i2o_pool *pool) -{ - mempool_destroy(pool->mempool); - kmem_cache_destroy(pool->slab); - kfree(pool->name); -}; -EXPORT_SYMBOL_GPL(i2o_pool_free); diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c deleted file mode 100644 index 0f9f3e1..0000000 --- a/drivers/message/i2o/pci.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * PCI handling of I2O controller - * - * Copyright (C) 1999-2002 Red Hat Software - * - * Written by Alan Cox, Building Number Three Ltd - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * A lot of the I2O message side code from this is taken from the Red - * Creek RCPCI45 adapter driver by Red Creek Communications - * - * Fixes/additions: - * Philipp Rumpf - * Juha Sievänen - * Auvo Häkkinen - * Deepak Saxena - * Boji T Kannanthanam - * Alan Cox : - * Ported to Linux 2.5. - * Markus Lidel : - * Minor fixes for 2.6. - * Markus Lidel : - * Support for sysfs included. - */ - -#include -#include -#include -#include -#include -#include "core.h" - -#define OSM_DESCRIPTION "I2O-subsystem" - -/* PCI device id table for all I2O controllers */ -static struct pci_device_id i2o_pci_ids[] = { - {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, - {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)}, - {.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962, - .subvendor = PCI_VENDOR_ID_PROMISE,.subdevice = PCI_ANY_ID}, - {0} -}; - -/** - * i2o_pci_free - Frees the DMA memory for the I2O controller - * @c: I2O controller to free - * - * Remove all allocated DMA memory and unmap memory IO regions. If MTRR - * is enabled, also remove it again. - */ -static void i2o_pci_free(struct i2o_controller *c) -{ - struct device *dev; - - dev = &c->pdev->dev; - - i2o_dma_free(dev, &c->out_queue); - i2o_dma_free(dev, &c->status_block); - kfree(c->lct); - i2o_dma_free(dev, &c->dlct); - i2o_dma_free(dev, &c->hrt); - i2o_dma_free(dev, &c->status); - - if (c->raptor && c->in_queue.virt) - iounmap(c->in_queue.virt); - - if (c->base.virt) - iounmap(c->base.virt); - - pci_release_regions(c->pdev); -} - -/** - * i2o_pci_alloc - Allocate DMA memory, map IO memory for I2O controller - * @c: I2O controller - * - * Allocate DMA memory for a PCI (or in theory AGP) I2O controller. All - * IO mappings are also done here. If MTRR is enabled, also do add memory - * regions here. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_pci_alloc(struct i2o_controller *c) -{ - struct pci_dev *pdev = c->pdev; - struct device *dev = &pdev->dev; - int i; - - if (pci_request_regions(pdev, OSM_DESCRIPTION)) { - printk(KERN_ERR "%s: device already claimed\n", c->name); - return -ENODEV; - } - - for (i = 0; i < 6; i++) { - /* Skip I/O spaces */ - if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { - if (!c->base.phys) { - c->base.phys = pci_resource_start(pdev, i); - c->base.len = pci_resource_len(pdev, i); - - /* - * If we know what card it is, set the size - * correctly. Code is taken from dpt_i2o.c - */ - if (pdev->device == 0xa501) { - if (pdev->subsystem_device >= 0xc032 && - pdev->subsystem_device <= 0xc03b) { - if (c->base.len > 0x400000) - c->base.len = 0x400000; - } else { - if (c->base.len > 0x100000) - c->base.len = 0x100000; - } - } - if (!c->raptor) - break; - } else { - c->in_queue.phys = pci_resource_start(pdev, i); - c->in_queue.len = pci_resource_len(pdev, i); - break; - } - } - } - - if (i == 6) { - printk(KERN_ERR "%s: I2O controller has no memory regions" - " defined.\n", c->name); - i2o_pci_free(c); - return -EINVAL; - } - - /* Map the I2O controller */ - if (c->raptor) { - printk(KERN_INFO "%s: PCI I2O controller\n", c->name); - printk(KERN_INFO " BAR0 at 0x%08lX size=%ld\n", - (unsigned long)c->base.phys, (unsigned long)c->base.len); - printk(KERN_INFO " BAR1 at 0x%08lX size=%ld\n", - (unsigned long)c->in_queue.phys, - (unsigned long)c->in_queue.len); - } else - printk(KERN_INFO "%s: PCI I2O controller at %08lX size=%ld\n", - c->name, (unsigned long)c->base.phys, - (unsigned long)c->base.len); - - c->base.virt = ioremap_nocache(c->base.phys, c->base.len); - if (!c->base.virt) { - printk(KERN_ERR "%s: Unable to map controller.\n", c->name); - i2o_pci_free(c); - return -ENOMEM; - } - - if (c->raptor) { - c->in_queue.virt = - ioremap_nocache(c->in_queue.phys, c->in_queue.len); - if (!c->in_queue.virt) { - printk(KERN_ERR "%s: Unable to map controller.\n", - c->name); - i2o_pci_free(c); - return -ENOMEM; - } - } else - c->in_queue = c->base; - - c->irq_status = c->base.virt + I2O_IRQ_STATUS; - c->irq_mask = c->base.virt + I2O_IRQ_MASK; - c->in_port = c->base.virt + I2O_IN_PORT; - c->out_port = c->base.virt + I2O_OUT_PORT; - - /* Motorola/Freescale chip does not follow spec */ - if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) { - /* Check if CPU is enabled */ - if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) { - printk(KERN_INFO "%s: MPC82XX needs CPU running to " - "service I2O.\n", c->name); - i2o_pci_free(c); - return -ENODEV; - } else { - c->irq_status += I2O_MOTOROLA_PORT_OFFSET; - c->irq_mask += I2O_MOTOROLA_PORT_OFFSET; - c->in_port += I2O_MOTOROLA_PORT_OFFSET; - c->out_port += I2O_MOTOROLA_PORT_OFFSET; - printk(KERN_INFO "%s: MPC82XX workarounds activated.\n", - c->name); - } - } - - if (i2o_dma_alloc(dev, &c->status, 8)) { - i2o_pci_free(c); - return -ENOMEM; - } - - if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt))) { - i2o_pci_free(c); - return -ENOMEM; - } - - if (i2o_dma_alloc(dev, &c->dlct, 8192)) { - i2o_pci_free(c); - return -ENOMEM; - } - - if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block))) { - i2o_pci_free(c); - return -ENOMEM; - } - - if (i2o_dma_alloc(dev, &c->out_queue, - I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE * - sizeof(u32))) { - i2o_pci_free(c); - return -ENOMEM; - } - - pci_set_drvdata(pdev, c); - - return 0; -} - -/** - * i2o_pci_interrupt - Interrupt handler for I2O controller - * @irq: interrupt line - * @dev_id: pointer to the I2O controller - * - * Handle an interrupt from a PCI based I2O controller. This turns out - * to be rather simple. We keep the controller pointer in the cookie. - */ -static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id) -{ - struct i2o_controller *c = dev_id; - u32 m; - irqreturn_t rc = IRQ_NONE; - - while (readl(c->irq_status) & I2O_IRQ_OUTBOUND_POST) { - m = readl(c->out_port); - if (m == I2O_QUEUE_EMPTY) { - /* - * Old 960 steppings had a bug in the I2O unit that - * caused the queue to appear empty when it wasn't. - */ - m = readl(c->out_port); - if (unlikely(m == I2O_QUEUE_EMPTY)) - break; - } - - /* dispatch it */ - if (i2o_driver_dispatch(c, m)) - /* flush it if result != 0 */ - i2o_flush_reply(c, m); - - rc = IRQ_HANDLED; - } - - return rc; -} - -/** - * i2o_pci_irq_enable - Allocate interrupt for I2O controller - * @c: i2o_controller that the request is for - * - * Allocate an interrupt for the I2O controller, and activate interrupts - * on the I2O controller. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_pci_irq_enable(struct i2o_controller *c) -{ - struct pci_dev *pdev = c->pdev; - int rc; - - writel(0xffffffff, c->irq_mask); - - if (pdev->irq) { - rc = request_irq(pdev->irq, i2o_pci_interrupt, IRQF_SHARED, - c->name, c); - if (rc < 0) { - printk(KERN_ERR "%s: unable to allocate interrupt %d." - "\n", c->name, pdev->irq); - return rc; - } - } - - writel(0x00000000, c->irq_mask); - - printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq); - - return 0; -} - -/** - * i2o_pci_irq_disable - Free interrupt for I2O controller - * @c: I2O controller - * - * Disable interrupts in I2O controller and then free interrupt. - */ -static void i2o_pci_irq_disable(struct i2o_controller *c) -{ - writel(0xffffffff, c->irq_mask); - - if (c->pdev->irq > 0) - free_irq(c->pdev->irq, c); -} - -/** - * i2o_pci_probe - Probe the PCI device for an I2O controller - * @pdev: PCI device to test - * @id: id which matched with the PCI device id table - * - * Probe the PCI device for any device which is a memory of the - * Intelligent, I2O class or an Adaptec Zero Channel Controller. We - * attempt to set up each such device and register it with the core. - * - * Returns 0 on success or negative error code on failure. - */ -static int i2o_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct i2o_controller *c; - int rc; - struct pci_dev *i960 = NULL; - - printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); - - if ((pdev->class & 0xff) > 1) { - printk(KERN_WARNING "i2o: %s does not support I2O 1.5 " - "(skipping).\n", pci_name(pdev)); - return -ENODEV; - } - - if ((rc = pci_enable_device(pdev))) { - printk(KERN_WARNING "i2o: couldn't enable device %s\n", - pci_name(pdev)); - return rc; - } - - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", - pci_name(pdev)); - rc = -ENODEV; - goto disable; - } - - pci_set_master(pdev); - - c = i2o_iop_alloc(); - if (IS_ERR(c)) { - printk(KERN_ERR "i2o: couldn't allocate memory for %s\n", - pci_name(pdev)); - rc = PTR_ERR(c); - goto disable; - } else - printk(KERN_INFO "%s: controller found (%s)\n", c->name, - pci_name(pdev)); - - c->pdev = pdev; - c->device.parent = &pdev->dev; - - /* Cards that fall apart if you hit them with large I/O loads... */ - if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) { - c->short_req = 1; - printk(KERN_INFO "%s: Symbios FC920 workarounds activated.\n", - c->name); - } - - if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) { - /* - * Expose the ship behind i960 for initialization, or it will - * failed - */ - i960 = pci_get_slot(c->pdev->bus, - PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0)); - - if (i960) { - pci_write_config_word(i960, 0x42, 0); - pci_dev_put(i960); - } - - c->promise = 1; - c->limit_sectors = 1; - } - - if (pdev->subsystem_vendor == PCI_VENDOR_ID_DPT) - c->adaptec = 1; - - /* Cards that go bananas if you quiesce them before you reset them. */ - if (pdev->vendor == PCI_VENDOR_ID_DPT) { - c->no_quiesce = 1; - if (pdev->device == 0xa511) - c->raptor = 1; - - if (pdev->subsystem_device == 0xc05a) { - c->limit_sectors = 1; - printk(KERN_INFO - "%s: limit sectors per request to %d\n", c->name, - I2O_MAX_SECTORS_LIMITED); - } -#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 - if (sizeof(dma_addr_t) > 4) { - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) - printk(KERN_INFO "%s: 64-bit DMA unavailable\n", - c->name); - else { - c->pae_support = 1; - printk(KERN_INFO "%s: using 64-bit DMA\n", - c->name); - } - } -#endif - } - - if ((rc = i2o_pci_alloc(c))) { - printk(KERN_ERR "%s: DMA / IO allocation for I2O controller " - "failed\n", c->name); - goto free_controller; - } - - if (i2o_pci_irq_enable(c)) { - printk(KERN_ERR "%s: unable to enable interrupts for I2O " - "controller\n", c->name); - goto free_pci; - } - - if ((rc = i2o_iop_add(c))) - goto uninstall; - - if (i960) - pci_write_config_word(i960, 0x42, 0x03ff); - - return 0; - - uninstall: - i2o_pci_irq_disable(c); - - free_pci: - i2o_pci_free(c); - - free_controller: - i2o_iop_free(c); - - disable: - pci_disable_device(pdev); - - return rc; -} - -/** - * i2o_pci_remove - Removes a I2O controller from the system - * @pdev: I2O controller which should be removed - * - * Reset the I2O controller, disable interrupts and remove all allocated - * resources. - */ -static void i2o_pci_remove(struct pci_dev *pdev) -{ - struct i2o_controller *c; - c = pci_get_drvdata(pdev); - - i2o_iop_remove(c); - i2o_pci_irq_disable(c); - i2o_pci_free(c); - - pci_disable_device(pdev); - - printk(KERN_INFO "%s: Controller removed.\n", c->name); - - put_device(&c->device); -}; - -/* PCI driver for I2O controller */ -static struct pci_driver i2o_pci_driver = { - .name = "PCI_I2O", - .id_table = i2o_pci_ids, - .probe = i2o_pci_probe, - .remove = i2o_pci_remove, -}; - -/** - * i2o_pci_init - registers I2O PCI driver in PCI subsystem - * - * Returns > 0 on success or negative error code on failure. - */ -int __init i2o_pci_init(void) -{ - return pci_register_driver(&i2o_pci_driver); -}; - -/** - * i2o_pci_exit - unregisters I2O PCI driver from PCI subsystem - */ -void __exit i2o_pci_exit(void) -{ - pci_unregister_driver(&i2o_pci_driver); -}; - -MODULE_DEVICE_TABLE(pci, i2o_pci_ids); diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 071ac11..9e52bcd 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -110,4 +110,6 @@ source "drivers/staging/clocking-wizard/Kconfig" source "drivers/staging/fbtft/Kconfig" +source "drivers/staging/i2o/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index b65ca37..6e0ac52 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -47,3 +47,4 @@ obj-$(CONFIG_CRYPTO_SKEIN) += skein/ obj-$(CONFIG_UNISYSSPAR) += unisys/ obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ obj-$(CONFIG_FB_TFT) += fbtft/ +obj-$(CONFIG_I2O) += i2o/ diff --git a/drivers/staging/i2o/Kconfig b/drivers/staging/i2o/Kconfig new file mode 100644 index 0000000..286c53f --- /dev/null +++ b/drivers/staging/i2o/Kconfig @@ -0,0 +1,120 @@ +menuconfig I2O + tristate "I2O device support" + depends on PCI + ---help--- + The Intelligent Input/Output (I2O) architecture allows hardware + drivers to be split into two parts: an operating system specific + module called the OSM and an hardware specific module called the + HDM. The OSM can talk to a whole range of HDM's, and ideally the + HDM's are not OS dependent. This allows for the same HDM driver to + be used under different operating systems if the relevant OSM is in + place. In order for this to work, you need to have an I2O interface + adapter card in your computer. This card contains a special I/O + processor (IOP), thus allowing high speeds since the CPU does not + have to deal with I/O. + + If you say Y here, you will get a choice of interface adapter + drivers and OSM's with the following questions. + + To compile this support as a module, choose M here: the + modules will be called i2o_core. + + If unsure, say N. + +if I2O + +config I2O_LCT_NOTIFY_ON_CHANGES + bool "Enable LCT notification" + default y + ---help--- + Only say N here if you have a I2O controller from SUN. The SUN + firmware doesn't support LCT notification on changes. If this option + is enabled on such a controller the driver will hang up in a endless + loop. On all other controllers say Y. + + If unsure, say Y. + +config I2O_EXT_ADAPTEC + bool "Enable Adaptec extensions" + default y + ---help--- + Say Y for support of raidutils for Adaptec I2O controllers. You also + have to say Y to "I2O Configuration support", "I2O SCSI OSM" below + and to "SCSI generic support" under "SCSI device configuration". + +config I2O_EXT_ADAPTEC_DMA64 + bool "Enable 64-bit DMA" + depends on I2O_EXT_ADAPTEC && ( 64BIT || HIGHMEM64G ) + default y + ---help--- + Say Y for support of 64-bit DMA transfer mode on Adaptec I2O + controllers. + Note: You need at least firmware version 3709. + +config I2O_CONFIG + tristate "I2O Configuration support" + depends on VIRT_TO_BUS + ---help--- + Say Y for support of the configuration interface for the I2O adapters. + If you have a RAID controller from Adaptec and you want to use the + raidutils to manage your RAID array, you have to say Y here. + + To compile this support as a module, choose M here: the + module will be called i2o_config. + + Note: If you want to use the new API you have to download the + i2o_config patch from http://i2o.shadowconnect.com/ + +config I2O_CONFIG_OLD_IOCTL + bool "Enable ioctls (OBSOLETE)" + depends on I2O_CONFIG + default y + ---help--- + Enables old ioctls. + +config I2O_BUS + tristate "I2O Bus Adapter OSM" + ---help--- + Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM + provides access to the busses on the I2O controller. The main purpose + is to rescan the bus to find new devices. + + To compile this support as a module, choose M here: the + module will be called i2o_bus. + +config I2O_BLOCK + tristate "I2O Block OSM" + depends on BLOCK + ---help--- + Include support for the I2O Block OSM. The Block OSM presents disk + and other structured block devices to the operating system. If you + are using an RAID controller, you could access the array only by + the Block OSM driver. But it is possible to access the single disks + by the SCSI OSM driver, for example to monitor the disks. + + To compile this support as a module, choose M here: the + module will be called i2o_block. + +config I2O_SCSI + tristate "I2O SCSI OSM" + depends on SCSI + ---help--- + Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel + I2O controller. You can use both the SCSI and Block OSM together if + you wish. To access a RAID array, you must use the Block OSM driver. + But you could use the SCSI OSM driver to monitor the single disks. + + To compile this support as a module, choose M here: the + module will be called i2o_scsi. + +config I2O_PROC + tristate "I2O /proc support" + ---help--- + If you say Y here and to "/proc file system support", you will be + able to read I2O related information from the virtual directory + /proc/i2o. + + To compile this support as a module, choose M here: the + module will be called i2o_proc. + +endif # I2O diff --git a/drivers/staging/i2o/Makefile b/drivers/staging/i2o/Makefile new file mode 100644 index 0000000..b0982da --- /dev/null +++ b/drivers/staging/i2o/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for the kernel I2O OSM. +# +# Note : at this point, these files are compiled on all systems. +# In the future, some of these should be built conditionally. +# + +i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o memory.o +i2o_bus-y += bus-osm.o +i2o_config-y += config-osm.o +obj-$(CONFIG_I2O) += i2o_core.o +obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o +obj-$(CONFIG_I2O_BUS) += i2o_bus.o +obj-$(CONFIG_I2O_BLOCK) += i2o_block.o +obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o +obj-$(CONFIG_I2O_PROC) += i2o_proc.o diff --git a/drivers/staging/i2o/README b/drivers/staging/i2o/README new file mode 100644 index 0000000..f072a8e --- /dev/null +++ b/drivers/staging/i2o/README @@ -0,0 +1,98 @@ + + Linux I2O Support (c) Copyright 1999 Red Hat Software + and others. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version + 2 of the License, or (at your option) any later version. + +AUTHORS (so far) + +Alan Cox, Building Number Three Ltd. + Core code, SCSI and Block OSMs + +Steve Ralston, LSI Logic Corp. + Debugging SCSI and Block OSM + +Deepak Saxena, Intel Corp. + Various core/block extensions + /proc interface, bug fixes + Ioctl interfaces for control + Debugging LAN OSM + +Philip Rumpf + Fixed assorted dumb SMP locking bugs + +Juha Sievanen, University of Helsinki Finland + LAN OSM code + /proc interface to LAN class + Bug fixes + Core code extensions + +Auvo Häkkinen, University of Helsinki Finland + LAN OSM code + /Proc interface to LAN class + Bug fixes + Core code extensions + +Taneli Vähäkangas, University of Helsinki Finland + Fixes to i2o_config + +CREDITS + + This work was made possible by + +Red Hat Software + Funding for the Building #3 part of the project + +Symbios Logic (Now LSI) + Host adapters, hints, known to work platforms when I hit + compatibility problems + +BoxHill Corporation + Loan of initial FibreChannel disk array used for development work. + +European Commission + Funding the work done by the University of Helsinki + +SysKonnect + Loan of FDDI and Gigabit Ethernet cards + +ASUSTeK + Loan of I2O motherboard + +STATUS: + +o The core setup works within limits. +o The scsi layer seems to almost work. + I'm still chasing down the hang bug. +o The block OSM is mostly functional +o LAN OSM works with FDDI and Ethernet cards. + +TO DO: + +General: +o Provide hidden address space if asked +o Long term message flow control +o PCI IOP's without interrupts are not supported yet +o Push FAIL handling into the core +o DDM control interfaces for module load etc +o Add I2O 2.0 support (Deffered to 2.5 kernel) + +Block: +o Multiple major numbers +o Read ahead and cache handling stuff. Talk to Ingo and people +o Power management +o Finish Media changers + +SCSI: +o Find the right way to associate drives/luns/busses + +Lan: +o Performance tuning +o Test Fibre Channel code + +Tape: +o Anyone seen anything implementing this ? + (D.S: Will attempt to do so if spare cycles permit) diff --git a/drivers/staging/i2o/README.ioctl b/drivers/staging/i2o/README.ioctl new file mode 100644 index 0000000..4a7d2eb --- /dev/null +++ b/drivers/staging/i2o/README.ioctl @@ -0,0 +1,394 @@ + +Linux I2O User Space Interface +rev 0.3 - 04/20/99 + +============================================================================= +Originally written by Deepak Saxena(deepak@plexity.net) +Currently maintained by Deepak Saxena(deepak@plexity.net) +============================================================================= + +I. Introduction + +The Linux I2O subsystem provides a set of ioctl() commands that can be +utilized by user space applications to communicate with IOPs and devices +on individual IOPs. This document defines the specific ioctl() commands +that are available to the user and provides examples of their uses. + +This document assumes the reader is familiar with or has access to the +I2O specification as no I2O message parameters are outlined. For information +on the specification, see http://www.i2osig.org + +This document and the I2O user space interface are currently maintained +by Deepak Saxena. Please send all comments, errata, and bug fixes to +deepak@csociety.purdue.edu + +II. IOP Access + +Access to the I2O subsystem is provided through the device file named +/dev/i2o/ctl. This file is a character file with major number 10 and minor +number 166. It can be created through the following command: + + mknod /dev/i2o/ctl c 10 166 + +III. Determining the IOP Count + + SYNOPSIS + + ioctl(fd, I2OGETIOPS, int *count); + + u8 count[MAX_I2O_CONTROLLERS]; + + DESCRIPTION + + This function returns the system's active IOP table. count should + point to a buffer containing MAX_I2O_CONTROLLERS entries. Upon + returning, each entry will contain a non-zero value if the given + IOP unit is active, and NULL if it is inactive or non-existent. + + RETURN VALUE. + + Returns 0 if no errors occur, and -1 otherwise. If an error occurs, + errno is set appropriately: + + EFAULT Invalid user space pointer was passed + +IV. Getting Hardware Resource Table + + SYNOPSIS + + ioctl(fd, I2OHRTGET, struct i2o_cmd_hrt *hrt); + + struct i2o_cmd_hrtlct + { + u32 iop; /* IOP unit number */ + void *resbuf; /* Buffer for result */ + u32 *reslen; /* Buffer length in bytes */ + }; + + DESCRIPTION + + This function returns the Hardware Resource Table of the IOP specified + by hrt->iop in the buffer pointed to by hrt->resbuf. The actual size of + the data is written into *(hrt->reslen). + + RETURNS + + This function returns 0 if no errors occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ENOBUFS Buffer not large enough. If this occurs, the required + buffer length is written into *(hrt->reslen) + +V. Getting Logical Configuration Table + + SYNOPSIS + + ioctl(fd, I2OLCTGET, struct i2o_cmd_lct *lct); + + struct i2o_cmd_hrtlct + { + u32 iop; /* IOP unit number */ + void *resbuf; /* Buffer for result */ + u32 *reslen; /* Buffer length in bytes */ + }; + + DESCRIPTION + + This function returns the Logical Configuration Table of the IOP specified + by lct->iop in the buffer pointed to by lct->resbuf. The actual size of + the data is written into *(lct->reslen). + + RETURNS + + This function returns 0 if no errors occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ENOBUFS Buffer not large enough. If this occurs, the required + buffer length is written into *(lct->reslen) + +VI. Setting Parameters + + SYNOPSIS + + ioctl(fd, I2OPARMSET, struct i2o_parm_setget *ops); + + struct i2o_cmd_psetget + { + u32 iop; /* IOP unit number */ + u32 tid; /* Target device TID */ + void *opbuf; /* Operation List buffer */ + u32 oplen; /* Operation List buffer length in bytes */ + void *resbuf; /* Result List buffer */ + u32 *reslen; /* Result List buffer length in bytes */ + }; + + DESCRIPTION + + This function posts a UtilParamsSet message to the device identified + by ops->iop and ops->tid. The operation list for the message is + sent through the ops->opbuf buffer, and the result list is written + into the buffer pointed to by ops->resbuf. The number of bytes + written is placed into *(ops->reslen). + + RETURNS + + The return value is the size in bytes of the data written into + ops->resbuf if no errors occur. If an error occurs, -1 is returned + and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ENOBUFS Buffer not large enough. If this occurs, the required + buffer length is written into *(ops->reslen) + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + + A return value of 0 does not mean that the value was actually + changed properly on the IOP. The user should check the result + list to determine the specific status of the transaction. + +VII. Getting Parameters + + SYNOPSIS + + ioctl(fd, I2OPARMGET, struct i2o_parm_setget *ops); + + struct i2o_parm_setget + { + u32 iop; /* IOP unit number */ + u32 tid; /* Target device TID */ + void *opbuf; /* Operation List buffer */ + u32 oplen; /* Operation List buffer length in bytes */ + void *resbuf; /* Result List buffer */ + u32 *reslen; /* Result List buffer length in bytes */ + }; + + DESCRIPTION + + This function posts a UtilParamsGet message to the device identified + by ops->iop and ops->tid. The operation list for the message is + sent through the ops->opbuf buffer, and the result list is written + into the buffer pointed to by ops->resbuf. The actual size of data + written is placed into *(ops->reslen). + + RETURNS + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ENOBUFS Buffer not large enough. If this occurs, the required + buffer length is written into *(ops->reslen) + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + + A return value of 0 does not mean that the value was actually + properly retrieved. The user should check the result list + to determine the specific status of the transaction. + +VIII. Downloading Software + + SYNOPSIS + + ioctl(fd, I2OSWDL, struct i2o_sw_xfer *sw); + + struct i2o_sw_xfer + { + u32 iop; /* IOP unit number */ + u8 flags; /* DownloadFlags field */ + u8 sw_type; /* Software type */ + u32 sw_id; /* Software ID */ + void *buf; /* Pointer to software buffer */ + u32 *swlen; /* Length of software buffer */ + u32 *maxfrag; /* Number of fragments */ + u32 *curfrag; /* Current fragment number */ + }; + + DESCRIPTION + + This function downloads a software fragment pointed by sw->buf + to the iop identified by sw->iop. The DownloadFlags, SwID, SwType + and SwSize fields of the ExecSwDownload message are filled in with + the values of sw->flags, sw->sw_id, sw->sw_type and *(sw->swlen). + + The fragments _must_ be sent in order and be 8K in size. The last + fragment _may_ be shorter, however. The kernel will compute its + size based on information in the sw->swlen field. + + Please note that SW transfers can take a long time. + + RETURNS + + This function returns 0 no errors occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + +IX. Uploading Software + + SYNOPSIS + + ioctl(fd, I2OSWUL, struct i2o_sw_xfer *sw); + + struct i2o_sw_xfer + { + u32 iop; /* IOP unit number */ + u8 flags; /* UploadFlags */ + u8 sw_type; /* Software type */ + u32 sw_id; /* Software ID */ + void *buf; /* Pointer to software buffer */ + u32 *swlen; /* Length of software buffer */ + u32 *maxfrag; /* Number of fragments */ + u32 *curfrag; /* Current fragment number */ + }; + + DESCRIPTION + + This function uploads a software fragment from the IOP identified + by sw->iop, sw->sw_type, sw->sw_id and optionally sw->swlen fields. + The UploadFlags, SwID, SwType and SwSize fields of the ExecSwUpload + message are filled in with the values of sw->flags, sw->sw_id, + sw->sw_type and *(sw->swlen). + + The fragments _must_ be requested in order and be 8K in size. The + user is responsible for allocating memory pointed by sw->buf. The + last fragment _may_ be shorter. + + Please note that SW transfers can take a long time. + + RETURNS + + This function returns 0 if no errors occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + +X. Removing Software + + SYNOPSIS + + ioctl(fd, I2OSWDEL, struct i2o_sw_xfer *sw); + + struct i2o_sw_xfer + { + u32 iop; /* IOP unit number */ + u8 flags; /* RemoveFlags */ + u8 sw_type; /* Software type */ + u32 sw_id; /* Software ID */ + void *buf; /* Unused */ + u32 *swlen; /* Length of the software data */ + u32 *maxfrag; /* Unused */ + u32 *curfrag; /* Unused */ + }; + + DESCRIPTION + + This function removes software from the IOP identified by sw->iop. + The RemoveFlags, SwID, SwType and SwSize fields of the ExecSwRemove message + are filled in with the values of sw->flags, sw->sw_id, sw->sw_type and + *(sw->swlen). Give zero in *(sw->len) if the value is unknown. IOP uses + *(sw->swlen) value to verify correct identication of the module to remove. + The actual size of the module is written into *(sw->swlen). + + RETURNS + + This function returns 0 if no errors occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + +X. Validating Configuration + + SYNOPSIS + + ioctl(fd, I2OVALIDATE, int *iop); + u32 iop; + + DESCRIPTION + + This function posts an ExecConfigValidate message to the controller + identified by iop. This message indicates that the current + configuration is accepted. The iop changes the status of suspect drivers + to valid and may delete old drivers from its store. + + RETURNS + + This function returns 0 if no erro occur. If an error occurs, -1 is + returned and errno is set appropriately: + + ETIMEDOUT Timeout waiting for reply message + ENXIO Invalid IOP number + +XI. Configuration Dialog + + SYNOPSIS + + ioctl(fd, I2OHTML, struct i2o_html *htquery); + struct i2o_html + { + u32 iop; /* IOP unit number */ + u32 tid; /* Target device ID */ + u32 page; /* HTML page */ + void *resbuf; /* Buffer for reply HTML page */ + u32 *reslen; /* Length in bytes of reply buffer */ + void *qbuf; /* Pointer to HTTP query string */ + u32 qlen; /* Length in bytes of query string buffer */ + }; + + DESCRIPTION + + This function posts an UtilConfigDialog message to the device identified + by htquery->iop and htquery->tid. The requested HTML page number is + provided by the htquery->page field, and the resultant data is stored + in the buffer pointed to by htquery->resbuf. If there is an HTTP query + string that is to be sent to the device, it should be sent in the buffer + pointed to by htquery->qbuf. If there is no query string, this field + should be set to NULL. The actual size of the reply received is written + into *(htquery->reslen). + + RETURNS + + This function returns 0 if no error occur. If an error occurs, -1 + is returned and errno is set appropriately: + + EFAULT Invalid user space pointer was passed + ENXIO Invalid IOP number + ENOBUFS Buffer not large enough. If this occurs, the required + buffer length is written into *(ops->reslen) + ETIMEDOUT Timeout waiting for reply message + ENOMEM Kernel memory allocation error + +XII. Events + + In the process of determining this. Current idea is to have use + the select() interface to allow user apps to periodically poll + the /dev/i2o/ctl device for events. When select() notifies the user + that an event is available, the user would call read() to retrieve + a list of all the events that are pending for the specific device. + +============================================================================= +Revision History +============================================================================= + +Rev 0.1 - 04/01/99 +- Initial revision + +Rev 0.2 - 04/06/99 +- Changed return values to match UNIX ioctl() standard. Only return values + are 0 and -1. All errors are reported through errno. +- Added summary of proposed possible event interfaces + +Rev 0.3 - 04/20/99 +- Changed all ioctls() to use pointers to user data instead of actual data +- Updated error values to match the code diff --git a/drivers/staging/i2o/bus-osm.c b/drivers/staging/i2o/bus-osm.c new file mode 100644 index 0000000..7aa0339 --- /dev/null +++ b/drivers/staging/i2o/bus-osm.c @@ -0,0 +1,176 @@ +/* + * Bus Adapter OSM + * + * Copyright (C) 2005 Markus Lidel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Fixes/additions: + * Markus Lidel + * initial version. + */ + +#include +#include "i2o.h" + +#define OSM_NAME "bus-osm" +#define OSM_VERSION "1.317" +#define OSM_DESCRIPTION "I2O Bus Adapter OSM" + +static struct i2o_driver i2o_bus_driver; + +/* Bus OSM class handling definition */ +static struct i2o_class_id i2o_bus_class_id[] = { + {I2O_CLASS_BUS_ADAPTER}, + {I2O_CLASS_END} +}; + +/** + * i2o_bus_scan - Scan the bus for new devices + * @dev: I2O device of the bus, which should be scanned + * + * Scans the bus dev for new / removed devices. After the scan a new LCT + * will be fetched automatically. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_bus_scan(struct i2o_device *dev) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return -ETIMEDOUT; + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data. + tid); + + return i2o_msg_post_wait(dev->iop, msg, 60); +}; + +/** + * i2o_bus_store_scan - Scan the I2O Bus Adapter + * @d: device which should be scanned + * @attr: device_attribute + * @buf: output buffer + * @count: buffer size + * + * Returns count. + */ +static ssize_t i2o_bus_store_scan(struct device *d, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2o_device *i2o_dev = to_i2o_device(d); + int rc; + + if ((rc = i2o_bus_scan(i2o_dev))) + osm_warn("bus scan failed %d\n", rc); + + return count; +} + +/* Bus Adapter OSM device attributes */ +static DEVICE_ATTR(scan, S_IWUSR, NULL, i2o_bus_store_scan); + +/** + * i2o_bus_probe - verify if dev is a I2O Bus Adapter device and install it + * @dev: device to verify if it is a I2O Bus Adapter device + * + * Because we want all Bus Adapters always return 0. + * Except when we fail. Then we are sad. + * + * Returns 0, except when we fail to excel. + */ +static int i2o_bus_probe(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(get_device(dev)); + int rc; + + rc = device_create_file(dev, &dev_attr_scan); + if (rc) + goto err_out; + + osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid); + + return 0; + +err_out: + put_device(dev); + return rc; +}; + +/** + * i2o_bus_remove - remove the I2O Bus Adapter device from the system again + * @dev: I2O Bus Adapter device which should be removed + * + * Always returns 0. + */ +static int i2o_bus_remove(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + + device_remove_file(dev, &dev_attr_scan); + + put_device(dev); + + osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid); + + return 0; +}; + +/* Bus Adapter OSM driver struct */ +static struct i2o_driver i2o_bus_driver = { + .name = OSM_NAME, + .classes = i2o_bus_class_id, + .driver = { + .probe = i2o_bus_probe, + .remove = i2o_bus_remove, + }, +}; + +/** + * i2o_bus_init - Bus Adapter OSM initialization function + * + * Only register the Bus Adapter OSM in the I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_bus_init(void) +{ + int rc; + + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + /* Register Bus Adapter OSM into I2O core */ + rc = i2o_driver_register(&i2o_bus_driver); + if (rc) { + osm_err("Could not register Bus Adapter OSM\n"); + return rc; + } + + return 0; +}; + +/** + * i2o_bus_exit - Bus Adapter OSM exit function + * + * Unregisters Bus Adapter OSM from I2O core. + */ +static void __exit i2o_bus_exit(void) +{ + i2o_driver_unregister(&i2o_bus_driver); +}; + +MODULE_AUTHOR("Markus Lidel "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_bus_init); +module_exit(i2o_bus_exit); diff --git a/drivers/staging/i2o/config-osm.c b/drivers/staging/i2o/config-osm.c new file mode 100644 index 0000000..519f52f --- /dev/null +++ b/drivers/staging/i2o/config-osm.c @@ -0,0 +1,90 @@ +/* + * Configuration OSM + * + * Copyright (C) 2005 Markus Lidel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Fixes/additions: + * Markus Lidel + * initial version. + */ + +#include +#include "i2o.h" +#include +#include +#include + +#include + +#define OSM_NAME "config-osm" +#define OSM_VERSION "1.323" +#define OSM_DESCRIPTION "I2O Configuration OSM" + +/* access mode user rw */ +#define S_IWRSR (S_IRUSR | S_IWUSR) + +static struct i2o_driver i2o_config_driver; + +/* Config OSM driver struct */ +static struct i2o_driver i2o_config_driver = { + .name = OSM_NAME, +}; + +#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL +#include "i2o_config.c" +#endif + +/** + * i2o_config_init - Configuration OSM initialization function + * + * Registers Configuration OSM in the I2O core and if old ioctl's are + * compiled in initialize them. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_config_init(void) +{ + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + if (i2o_driver_register(&i2o_config_driver)) { + osm_err("handler register failed.\n"); + return -EBUSY; + } +#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL + if (i2o_config_old_init()) { + osm_err("old config handler initialization failed\n"); + i2o_driver_unregister(&i2o_config_driver); + return -EBUSY; + } +#endif + + return 0; +} + +/** + * i2o_config_exit - Configuration OSM exit function + * + * If old ioctl's are compiled in exit remove them and unregisters + * Configuration OSM from I2O core. + */ +static void i2o_config_exit(void) +{ +#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL + i2o_config_old_exit(); +#endif + + i2o_driver_unregister(&i2o_config_driver); +} + +MODULE_AUTHOR("Markus Lidel "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_config_init); +module_exit(i2o_config_exit); diff --git a/drivers/staging/i2o/core.h b/drivers/staging/i2o/core.h new file mode 100644 index 0000000..91614f1 --- /dev/null +++ b/drivers/staging/i2o/core.h @@ -0,0 +1,69 @@ +/* + * I2O core internal declarations + * + * Copyright (C) 2005 Markus Lidel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Fixes/additions: + * Markus Lidel + * initial version. + */ + +/* Exec-OSM */ +extern struct i2o_driver i2o_exec_driver; +extern int i2o_exec_lct_get(struct i2o_controller *); + +extern int __init i2o_exec_init(void); +extern void i2o_exec_exit(void); + +/* driver */ +extern struct bus_type i2o_bus_type; + +extern int i2o_driver_dispatch(struct i2o_controller *, u32); + +extern int __init i2o_driver_init(void); +extern void i2o_driver_exit(void); + +/* PCI */ +extern int __init i2o_pci_init(void); +extern void __exit i2o_pci_exit(void); + +/* device */ +extern const struct attribute_group *i2o_device_groups[]; + +extern void i2o_device_remove(struct i2o_device *); +extern int i2o_device_parse_lct(struct i2o_controller *); + +int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, + int oplen, void *reslist, int reslen); + +/* IOP */ +extern struct i2o_controller *i2o_iop_alloc(void); + +/** + * i2o_iop_free - Free the i2o_controller struct + * @c: I2O controller to free + */ +static inline void i2o_iop_free(struct i2o_controller *c) +{ + i2o_pool_free(&c->in_msg); + kfree(c); +} + +extern int i2o_iop_add(struct i2o_controller *); +extern void i2o_iop_remove(struct i2o_controller *); + +/* control registers relative to c->base */ +#define I2O_IRQ_STATUS 0x30 +#define I2O_IRQ_MASK 0x34 +#define I2O_IN_PORT 0x40 +#define I2O_OUT_PORT 0x44 + +/* Motorola/Freescale specific register offset */ +#define I2O_MOTOROLA_PORT_OFFSET 0x10400 + +#define I2O_IRQ_OUTBOUND_POST 0x00000008 diff --git a/drivers/staging/i2o/debug.c b/drivers/staging/i2o/debug.c new file mode 100644 index 0000000..7a16114 --- /dev/null +++ b/drivers/staging/i2o/debug.c @@ -0,0 +1,472 @@ +#include +#include +#include +#include "i2o.h" + +static void i2o_report_util_cmd(u8 cmd); +static void i2o_report_exec_cmd(u8 cmd); +static void i2o_report_fail_status(u8 req_status, u32 * msg); +static void i2o_report_common_status(u8 req_status); +static void i2o_report_common_dsc(u16 detailed_status); + +/* + * Used for error reporting/debugging purposes. + * Report Cmd name, Request status, Detailed Status. + */ +void i2o_report_status(const char *severity, const char *str, + struct i2o_message *m) +{ + u32 *msg = (u32 *) m; + u8 cmd = (msg[1] >> 24) & 0xFF; + u8 req_status = (msg[4] >> 24) & 0xFF; + u16 detailed_status = msg[4] & 0xFFFF; + + if (cmd == I2O_CMD_UTIL_EVT_REGISTER) + return; // No status in this reply + + printk("%s%s: ", severity, str); + + if (cmd < 0x1F) // Utility cmd + i2o_report_util_cmd(cmd); + + else if (cmd >= 0xA0 && cmd <= 0xEF) // Executive cmd + i2o_report_exec_cmd(cmd); + else + printk("Cmd = %0#2x, ", cmd); // Other cmds + + if (msg[0] & MSG_FAIL) { + i2o_report_fail_status(req_status, msg); + return; + } + + i2o_report_common_status(req_status); + + if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF)) + i2o_report_common_dsc(detailed_status); + else + printk(" / DetailedStatus = %0#4x.\n", + detailed_status); +} + +/* Used to dump a message to syslog during debugging */ +void i2o_dump_message(struct i2o_message *m) +{ +#ifdef DEBUG + u32 *msg = (u32 *) m; + int i; + printk(KERN_INFO "Dumping I2O message size %d @ %p\n", + msg[0] >> 16 & 0xffff, msg); + for (i = 0; i < ((msg[0] >> 16) & 0xffff); i++) + printk(KERN_INFO " msg[%d] = %0#10x\n", i, msg[i]); +#endif +} + +/* + * Used for error reporting/debugging purposes. + * Following fail status are common to all classes. + * The preserved message must be handled in the reply handler. + */ +static void i2o_report_fail_status(u8 req_status, u32 * msg) +{ + static char *FAIL_STATUS[] = { + "0x80", /* not used */ + "SERVICE_SUSPENDED", /* 0x81 */ + "SERVICE_TERMINATED", /* 0x82 */ + "CONGESTION", + "FAILURE", + "STATE_ERROR", + "TIME_OUT", + "ROUTING_FAILURE", + "INVALID_VERSION", + "INVALID_OFFSET", + "INVALID_MSG_FLAGS", + "FRAME_TOO_SMALL", + "FRAME_TOO_LARGE", + "INVALID_TARGET_ID", + "INVALID_INITIATOR_ID", + "INVALID_INITIATOR_CONTEX", /* 0x8F */ + "UNKNOWN_FAILURE" /* 0xFF */ + }; + + if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE) + printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n", + req_status); + else + printk("TRANSPORT_%s.\n", + FAIL_STATUS[req_status & 0x0F]); + + /* Dump some details */ + + printk(KERN_ERR " InitiatorId = %d, TargetId = %d\n", + (msg[1] >> 12) & 0xFFF, msg[1] & 0xFFF); + printk(KERN_ERR " LowestVersion = 0x%02X, HighestVersion = 0x%02X\n", + (msg[4] >> 8) & 0xFF, msg[4] & 0xFF); + printk(KERN_ERR " FailingHostUnit = 0x%04X, FailingIOP = 0x%03X\n", + msg[5] >> 16, msg[5] & 0xFFF); + + printk(KERN_ERR " Severity: 0x%02X\n", (msg[4] >> 16) & 0xFF); + if (msg[4] & (1 << 16)) + printk(KERN_DEBUG "(FormatError), " + "this msg can never be delivered/processed.\n"); + if (msg[4] & (1 << 17)) + printk(KERN_DEBUG "(PathError), " + "this msg can no longer be delivered/processed.\n"); + if (msg[4] & (1 << 18)) + printk(KERN_DEBUG "(PathState), " + "the system state does not allow delivery.\n"); + if (msg[4] & (1 << 19)) + printk(KERN_DEBUG + "(Congestion), resources temporarily not available;" + "do not retry immediately.\n"); +} + +/* + * Used for error reporting/debugging purposes. + * Following reply status are common to all classes. + */ +static void i2o_report_common_status(u8 req_status) +{ + static char *REPLY_STATUS[] = { + "SUCCESS", + "ABORT_DIRTY", + "ABORT_NO_DATA_TRANSFER", + "ABORT_PARTIAL_TRANSFER", + "ERROR_DIRTY", + "ERROR_NO_DATA_TRANSFER", + "ERROR_PARTIAL_TRANSFER", + "PROCESS_ABORT_DIRTY", + "PROCESS_ABORT_NO_DATA_TRANSFER", + "PROCESS_ABORT_PARTIAL_TRANSFER", + "TRANSACTION_ERROR", + "PROGRESS_REPORT" + }; + + if (req_status >= ARRAY_SIZE(REPLY_STATUS)) + printk("RequestStatus = %0#2x", req_status); + else + printk("%s", REPLY_STATUS[req_status]); +} + +/* + * Used for error reporting/debugging purposes. + * Following detailed status are valid for executive class, + * utility class, DDM class and for transaction error replies. + */ +static void i2o_report_common_dsc(u16 detailed_status) +{ + static char *COMMON_DSC[] = { + "SUCCESS", + "0x01", // not used + "BAD_KEY", + "TCL_ERROR", + "REPLY_BUFFER_FULL", + "NO_SUCH_PAGE", + "INSUFFICIENT_RESOURCE_SOFT", + "INSUFFICIENT_RESOURCE_HARD", + "0x08", // not used + "CHAIN_BUFFER_TOO_LARGE", + "UNSUPPORTED_FUNCTION", + "DEVICE_LOCKED", + "DEVICE_RESET", + "INAPPROPRIATE_FUNCTION", + "INVALID_INITIATOR_ADDRESS", + "INVALID_MESSAGE_FLAGS", + "INVALID_OFFSET", + "INVALID_PARAMETER", + "INVALID_REQUEST", + "INVALID_TARGET_ADDRESS", + "MESSAGE_TOO_LARGE", + "MESSAGE_TOO_SMALL", + "MISSING_PARAMETER", + "TIMEOUT", + "UNKNOWN_ERROR", + "UNKNOWN_FUNCTION", + "UNSUPPORTED_VERSION", + "DEVICE_BUSY", + "DEVICE_NOT_AVAILABLE" + }; + + if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE) + printk(" / DetailedStatus = %0#4x.\n", + detailed_status); + else + printk(" / %s.\n", COMMON_DSC[detailed_status]); +} + +/* + * Used for error reporting/debugging purposes + */ +static void i2o_report_util_cmd(u8 cmd) +{ + switch (cmd) { + case I2O_CMD_UTIL_NOP: + printk("UTIL_NOP, "); + break; + case I2O_CMD_UTIL_ABORT: + printk("UTIL_ABORT, "); + break; + case I2O_CMD_UTIL_CLAIM: + printk("UTIL_CLAIM, "); + break; + case I2O_CMD_UTIL_RELEASE: + printk("UTIL_CLAIM_RELEASE, "); + break; + case I2O_CMD_UTIL_CONFIG_DIALOG: + printk("UTIL_CONFIG_DIALOG, "); + break; + case I2O_CMD_UTIL_DEVICE_RESERVE: + printk("UTIL_DEVICE_RESERVE, "); + break; + case I2O_CMD_UTIL_DEVICE_RELEASE: + printk("UTIL_DEVICE_RELEASE, "); + break; + case I2O_CMD_UTIL_EVT_ACK: + printk("UTIL_EVENT_ACKNOWLEDGE, "); + break; + case I2O_CMD_UTIL_EVT_REGISTER: + printk("UTIL_EVENT_REGISTER, "); + break; + case I2O_CMD_UTIL_LOCK: + printk("UTIL_LOCK, "); + break; + case I2O_CMD_UTIL_LOCK_RELEASE: + printk("UTIL_LOCK_RELEASE, "); + break; + case I2O_CMD_UTIL_PARAMS_GET: + printk("UTIL_PARAMS_GET, "); + break; + case I2O_CMD_UTIL_PARAMS_SET: + printk("UTIL_PARAMS_SET, "); + break; + case I2O_CMD_UTIL_REPLY_FAULT_NOTIFY: + printk("UTIL_REPLY_FAULT_NOTIFY, "); + break; + default: + printk("Cmd = %0#2x, ", cmd); + } +} + +/* + * Used for error reporting/debugging purposes + */ +static void i2o_report_exec_cmd(u8 cmd) +{ + switch (cmd) { + case I2O_CMD_ADAPTER_ASSIGN: + printk("EXEC_ADAPTER_ASSIGN, "); + break; + case I2O_CMD_ADAPTER_READ: + printk("EXEC_ADAPTER_READ, "); + break; + case I2O_CMD_ADAPTER_RELEASE: + printk("EXEC_ADAPTER_RELEASE, "); + break; + case I2O_CMD_BIOS_INFO_SET: + printk("EXEC_BIOS_INFO_SET, "); + break; + case I2O_CMD_BOOT_DEVICE_SET: + printk("EXEC_BOOT_DEVICE_SET, "); + break; + case I2O_CMD_CONFIG_VALIDATE: + printk("EXEC_CONFIG_VALIDATE, "); + break; + case I2O_CMD_CONN_SETUP: + printk("EXEC_CONN_SETUP, "); + break; + case I2O_CMD_DDM_DESTROY: + printk("EXEC_DDM_DESTROY, "); + break; + case I2O_CMD_DDM_ENABLE: + printk("EXEC_DDM_ENABLE, "); + break; + case I2O_CMD_DDM_QUIESCE: + printk("EXEC_DDM_QUIESCE, "); + break; + case I2O_CMD_DDM_RESET: + printk("EXEC_DDM_RESET, "); + break; + case I2O_CMD_DDM_SUSPEND: + printk("EXEC_DDM_SUSPEND, "); + break; + case I2O_CMD_DEVICE_ASSIGN: + printk("EXEC_DEVICE_ASSIGN, "); + break; + case I2O_CMD_DEVICE_RELEASE: + printk("EXEC_DEVICE_RELEASE, "); + break; + case I2O_CMD_HRT_GET: + printk("EXEC_HRT_GET, "); + break; + case I2O_CMD_ADAPTER_CLEAR: + printk("EXEC_IOP_CLEAR, "); + break; + case I2O_CMD_ADAPTER_CONNECT: + printk("EXEC_IOP_CONNECT, "); + break; + case I2O_CMD_ADAPTER_RESET: + printk("EXEC_IOP_RESET, "); + break; + case I2O_CMD_LCT_NOTIFY: + printk("EXEC_LCT_NOTIFY, "); + break; + case I2O_CMD_OUTBOUND_INIT: + printk("EXEC_OUTBOUND_INIT, "); + break; + case I2O_CMD_PATH_ENABLE: + printk("EXEC_PATH_ENABLE, "); + break; + case I2O_CMD_PATH_QUIESCE: + printk("EXEC_PATH_QUIESCE, "); + break; + case I2O_CMD_PATH_RESET: + printk("EXEC_PATH_RESET, "); + break; + case I2O_CMD_STATIC_MF_CREATE: + printk("EXEC_STATIC_MF_CREATE, "); + break; + case I2O_CMD_STATIC_MF_RELEASE: + printk("EXEC_STATIC_MF_RELEASE, "); + break; + case I2O_CMD_STATUS_GET: + printk("EXEC_STATUS_GET, "); + break; + case I2O_CMD_SW_DOWNLOAD: + printk("EXEC_SW_DOWNLOAD, "); + break; + case I2O_CMD_SW_UPLOAD: + printk("EXEC_SW_UPLOAD, "); + break; + case I2O_CMD_SW_REMOVE: + printk("EXEC_SW_REMOVE, "); + break; + case I2O_CMD_SYS_ENABLE: + printk("EXEC_SYS_ENABLE, "); + break; + case I2O_CMD_SYS_MODIFY: + printk("EXEC_SYS_MODIFY, "); + break; + case I2O_CMD_SYS_QUIESCE: + printk("EXEC_SYS_QUIESCE, "); + break; + case I2O_CMD_SYS_TAB_SET: + printk("EXEC_SYS_TAB_SET, "); + break; + default: + printk("Cmd = %#02x, ", cmd); + } +} + +void i2o_debug_state(struct i2o_controller *c) +{ + printk(KERN_INFO "%s: State = ", c->name); + switch (((i2o_status_block *) c->status_block.virt)->iop_state) { + case 0x01: + printk("INIT\n"); + break; + case 0x02: + printk("RESET\n"); + break; + case 0x04: + printk("HOLD\n"); + break; + case 0x05: + printk("READY\n"); + break; + case 0x08: + printk("OPERATIONAL\n"); + break; + case 0x10: + printk("FAILED\n"); + break; + case 0x11: + printk("FAULTED\n"); + break; + default: + printk("%x (unknown !!)\n", + ((i2o_status_block *) c->status_block.virt)->iop_state); + } +}; + +void i2o_dump_hrt(struct i2o_controller *c) +{ + u32 *rows = (u32 *) c->hrt.virt; + u8 *p = (u8 *) c->hrt.virt; + u8 *d; + int count; + int length; + int i; + int state; + + if (p[3] != 0) { + printk(KERN_ERR + "%s: HRT table for controller is too new a version.\n", + c->name); + return; + } + + count = p[0] | (p[1] << 8); + length = p[2]; + + printk(KERN_INFO "%s: HRT has %d entries of %d bytes each.\n", + c->name, count, length << 2); + + rows += 2; + + for (i = 0; i < count; i++) { + printk(KERN_INFO "Adapter %08X: ", rows[0]); + p = (u8 *) (rows + 1); + d = (u8 *) (rows + 2); + state = p[1] << 8 | p[0]; + + printk("TID %04X:[", state & 0xFFF); + state >>= 12; + if (state & (1 << 0)) + printk("H"); /* Hidden */ + if (state & (1 << 2)) { + printk("P"); /* Present */ + if (state & (1 << 1)) + printk("C"); /* Controlled */ + } + if (state > 9) + printk("*"); /* Hard */ + + printk("]:"); + + switch (p[3] & 0xFFFF) { + case 0: + /* Adapter private bus - easy */ + printk("Local bus %d: I/O at 0x%04X Mem 0x%08X", p[2], + d[1] << 8 | d[0], *(u32 *) (d + 4)); + break; + case 1: + /* ISA bus */ + printk("ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", p[2], + d[2], d[1] << 8 | d[0], *(u32 *) (d + 4)); + break; + + case 2: /* EISA bus */ + printk("EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X", + p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); + break; + + case 3: /* MCA bus */ + printk("MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2], + d[3], d[1] << 8 | d[0], *(u32 *) (d + 4)); + break; + + case 4: /* PCI bus */ + printk("PCI %d: Bus %d Device %d Function %d", p[2], + d[2], d[1], d[0]); + break; + + case 0x80: /* Other */ + default: + printk("Unsupported bus type."); + break; + } + printk("\n"); + rows += length; + } +} + +EXPORT_SYMBOL(i2o_dump_message); diff --git a/drivers/staging/i2o/device.c b/drivers/staging/i2o/device.c new file mode 100644 index 0000000..2af2255 --- /dev/null +++ b/drivers/staging/i2o/device.c @@ -0,0 +1,594 @@ +/* + * Functions to handle I2O devices + * + * Copyright (C) 2004 Markus Lidel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Fixes/additions: + * Markus Lidel + * initial version. + */ + +#include +#include "i2o.h" +#include +#include +#include +#include "core.h" + +/** + * i2o_device_issue_claim - claim or release a device + * @dev: I2O device to claim or release + * @cmd: claim or release command + * @type: type of claim + * + * Issue I2O UTIL_CLAIM or UTIL_RELEASE messages. The message to be sent + * is set by cmd. dev is the I2O device which should be claim or + * released and the type is the claim type (see the I2O spec). + * + * Returs 0 on success or negative error code on failure. + */ +static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, + u32 type) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid); + msg->body[0] = cpu_to_le32(type); + + return i2o_msg_post_wait(dev->iop, msg, 60); +} + +/** + * i2o_device_claim - claim a device for use by an OSM + * @dev: I2O device to claim + * + * Do the leg work to assign a device to a given OSM. If the claim succeeds, + * the owner is the primary. If the attempt fails a negative errno code + * is returned. On success zero is returned. + */ +int i2o_device_claim(struct i2o_device *dev) +{ + int rc = 0; + + mutex_lock(&dev->lock); + + rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY); + if (!rc) + pr_debug("i2o: claim of device %d succeeded\n", + dev->lct_data.tid); + else + pr_debug("i2o: claim of device %d failed %d\n", + dev->lct_data.tid, rc); + + mutex_unlock(&dev->lock); + + return rc; +} + +/** + * i2o_device_claim_release - release a device that the OSM is using + * @dev: device to release + * + * Drop a claim by an OSM on a given I2O device. + * + * AC - some devices seem to want to refuse an unclaim until they have + * finished internal processing. It makes sense since you don't want a + * new device to go reconfiguring the entire system until you are done. + * Thus we are prepared to wait briefly. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_device_claim_release(struct i2o_device *dev) +{ + int tries; + int rc = 0; + + mutex_lock(&dev->lock); + + /* + * If the controller takes a nonblocking approach to + * releases we have to sleep/poll for a few times. + */ + for (tries = 0; tries < 10; tries++) { + rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_RELEASE, + I2O_CLAIM_PRIMARY); + if (!rc) + break; + + ssleep(1); + } + + if (!rc) + pr_debug("i2o: claim release of device %d succeeded\n", + dev->lct_data.tid); + else + pr_debug("i2o: claim release of device %d failed %d\n", + dev->lct_data.tid, rc); + + mutex_unlock(&dev->lock); + + return rc; +} + +/** + * i2o_device_release - release the memory for a I2O device + * @dev: I2O device which should be released + * + * Release the allocated memory. This function is called if refcount of + * device reaches 0 automatically. + */ +static void i2o_device_release(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + + pr_debug("i2o: device %s released\n", dev_name(dev)); + + kfree(i2o_dev); +} + +/** + * class_id_show - Displays class id of I2O device + * @dev: device of which the class id should be displayed + * @attr: pointer to device attribute + * @buf: buffer into which the class id should be printed + * + * Returns the number of bytes which are printed into the buffer. + */ +static ssize_t class_id_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + + sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id); + return strlen(buf) + 1; +} +static DEVICE_ATTR_RO(class_id); + +/** + * tid_show - Displays TID of I2O device + * @dev: device of which the TID should be displayed + * @attr: pointer to device attribute + * @buf: buffer into which the TID should be printed + * + * Returns the number of bytes which are printed into the buffer. + */ +static ssize_t tid_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + + sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid); + return strlen(buf) + 1; +} +static DEVICE_ATTR_RO(tid); + +/* I2O device attributes */ +static struct attribute *i2o_device_attrs[] = { + &dev_attr_class_id.attr, + &dev_attr_tid.attr, + NULL, +}; + +static const struct attribute_group i2o_device_group = { + .attrs = i2o_device_attrs, +}; + +const struct attribute_group *i2o_device_groups[] = { + &i2o_device_group, + NULL, +}; + +/** + * i2o_device_alloc - Allocate a I2O device and initialize it + * + * Allocate the memory for a I2O device and initialize locks and lists + * + * Returns the allocated I2O device or a negative error code if the device + * could not be allocated. + */ +static struct i2o_device *i2o_device_alloc(void) +{ + struct i2o_device *dev; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&dev->list); + mutex_init(&dev->lock); + + dev->device.bus = &i2o_bus_type; + dev->device.release = &i2o_device_release; + + return dev; +} + +/** + * i2o_device_add - allocate a new I2O device and add it to the IOP + * @c: I2O controller that the device is on + * @entry: LCT entry of the I2O device + * + * Allocate a new I2O device and initialize it with the LCT entry. The + * device is appended to the device list of the controller. + * + * Returns zero on success, or a -ve errno. + */ +static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry) +{ + struct i2o_device *i2o_dev, *tmp; + int rc; + + i2o_dev = i2o_device_alloc(); + if (IS_ERR(i2o_dev)) { + printk(KERN_ERR "i2o: unable to allocate i2o device\n"); + return PTR_ERR(i2o_dev); + } + + i2o_dev->lct_data = *entry; + + dev_set_name(&i2o_dev->device, "%d:%03x", c->unit, + i2o_dev->lct_data.tid); + + i2o_dev->iop = c; + i2o_dev->device.parent = &c->device; + + rc = device_register(&i2o_dev->device); + if (rc) + goto err; + + list_add_tail(&i2o_dev->list, &c->devices); + + /* create user entries for this device */ + tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); + if (tmp && (tmp != i2o_dev)) { + rc = sysfs_create_link(&i2o_dev->device.kobj, + &tmp->device.kobj, "user"); + if (rc) + goto unreg_dev; + } + + /* create user entries referring to this device */ + list_for_each_entry(tmp, &c->devices, list) + if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) + && (tmp != i2o_dev)) { + rc = sysfs_create_link(&tmp->device.kobj, + &i2o_dev->device.kobj, "user"); + if (rc) + goto rmlink1; + } + + /* create parent entries for this device */ + tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); + if (tmp && (tmp != i2o_dev)) { + rc = sysfs_create_link(&i2o_dev->device.kobj, + &tmp->device.kobj, "parent"); + if (rc) + goto rmlink1; + } + + /* create parent entries referring to this device */ + list_for_each_entry(tmp, &c->devices, list) + if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) + && (tmp != i2o_dev)) { + rc = sysfs_create_link(&tmp->device.kobj, + &i2o_dev->device.kobj, "parent"); + if (rc) + goto rmlink2; + } + + i2o_driver_notify_device_add_all(i2o_dev); + + pr_debug("i2o: device %s added\n", dev_name(&i2o_dev->device)); + + return 0; + +rmlink2: + /* If link creating failed halfway, we loop whole list to cleanup. + * And we don't care wrong removing of link, because sysfs_remove_link + * will take care of it. + */ + list_for_each_entry(tmp, &c->devices, list) { + if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "parent"); + } + sysfs_remove_link(&i2o_dev->device.kobj, "parent"); +rmlink1: + list_for_each_entry(tmp, &c->devices, list) + if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "user"); + sysfs_remove_link(&i2o_dev->device.kobj, "user"); +unreg_dev: + list_del(&i2o_dev->list); + device_unregister(&i2o_dev->device); +err: + kfree(i2o_dev); + return rc; +} + +/** + * i2o_device_remove - remove an I2O device from the I2O core + * @i2o_dev: I2O device which should be released + * + * Is used on I2O controller removal or LCT modification, when the device + * is removed from the system. Note that the device could still hang + * around until the refcount reaches 0. + */ +void i2o_device_remove(struct i2o_device *i2o_dev) +{ + struct i2o_device *tmp; + struct i2o_controller *c = i2o_dev->iop; + + i2o_driver_notify_device_remove_all(i2o_dev); + + sysfs_remove_link(&i2o_dev->device.kobj, "parent"); + sysfs_remove_link(&i2o_dev->device.kobj, "user"); + + list_for_each_entry(tmp, &c->devices, list) { + if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "parent"); + if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "user"); + } + list_del(&i2o_dev->list); + + device_unregister(&i2o_dev->device); +} + +/** + * i2o_device_parse_lct - Parse a previously fetched LCT and create devices + * @c: I2O controller from which the LCT should be parsed. + * + * The Logical Configuration Table tells us what we can talk to on the + * board. For every entry we create an I2O device, which is registered in + * the I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_device_parse_lct(struct i2o_controller *c) +{ + struct i2o_device *dev, *tmp; + i2o_lct *lct; + u32 *dlct = c->dlct.virt; + int max = 0, i = 0; + u16 table_size; + u32 buf; + + mutex_lock(&c->lct_lock); + + kfree(c->lct); + + buf = le32_to_cpu(*dlct++); + table_size = buf & 0xffff; + + lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL); + if (!lct) { + mutex_unlock(&c->lct_lock); + return -ENOMEM; + } + + lct->lct_ver = buf >> 28; + lct->boot_tid = buf >> 16 & 0xfff; + lct->table_size = table_size; + lct->change_ind = le32_to_cpu(*dlct++); + lct->iop_flags = le32_to_cpu(*dlct++); + + table_size -= 3; + + pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max, + lct->table_size); + + while (table_size > 0) { + i2o_lct_entry *entry = &lct->lct_entry[max]; + int found = 0; + + buf = le32_to_cpu(*dlct++); + entry->entry_size = buf & 0xffff; + entry->tid = buf >> 16 & 0xfff; + + entry->change_ind = le32_to_cpu(*dlct++); + entry->device_flags = le32_to_cpu(*dlct++); + + buf = le32_to_cpu(*dlct++); + entry->class_id = buf & 0xfff; + entry->version = buf >> 12 & 0xf; + entry->vendor_id = buf >> 16; + + entry->sub_class = le32_to_cpu(*dlct++); + + buf = le32_to_cpu(*dlct++); + entry->user_tid = buf & 0xfff; + entry->parent_tid = buf >> 12 & 0xfff; + entry->bios_info = buf >> 24; + + memcpy(&entry->identity_tag, dlct, 8); + dlct += 2; + + entry->event_capabilities = le32_to_cpu(*dlct++); + + /* add new devices, which are new in the LCT */ + list_for_each_entry_safe(dev, tmp, &c->devices, list) { + if (entry->tid == dev->lct_data.tid) { + found = 1; + break; + } + } + + if (!found) + i2o_device_add(c, entry); + + table_size -= 9; + max++; + } + + /* remove devices, which are not in the LCT anymore */ + list_for_each_entry_safe(dev, tmp, &c->devices, list) { + int found = 0; + + for (i = 0; i < max; i++) { + if (lct->lct_entry[i].tid == dev->lct_data.tid) { + found = 1; + break; + } + } + + if (!found) + i2o_device_remove(dev); + } + + mutex_unlock(&c->lct_lock); + + return 0; +} + +/* + * Run time support routines + */ + +/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET + * + * This function can be used for all UtilParamsGet/Set operations. + * The OperationList is given in oplist-buffer, + * and results are returned in reslist-buffer. + * Note that the minimum sized reslist is 8 bytes and contains + * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. + */ +int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, + int oplen, void *reslist, int reslen) +{ + struct i2o_message *msg; + int i = 0; + int rc; + struct i2o_dma res; + struct i2o_controller *c = i2o_dev->iop; + struct device *dev = &c->pdev->dev; + + res.virt = NULL; + + if (i2o_dma_alloc(dev, &res, reslen)) + return -ENOMEM; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) { + i2o_dma_free(dev, &res); + return PTR_ERR(msg); + } + + i = 0; + msg->u.head[1] = + cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid); + msg->body[i++] = cpu_to_le32(0x00000000); + msg->body[i++] = cpu_to_le32(0x4C000000 | oplen); /* OperationList */ + memcpy(&msg->body[i], oplist, oplen); + i += (oplen / 4 + (oplen % 4 ? 1 : 0)); + msg->body[i++] = cpu_to_le32(0xD0000000 | res.len); /* ResultList */ + msg->body[i++] = cpu_to_le32(res.phys); + + msg->u.head[0] = + cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) | + SGL_OFFSET_5); + + rc = i2o_msg_post_wait_mem(c, msg, 10, &res); + + /* This only looks like a memory leak - don't "fix" it. */ + if (rc == -ETIMEDOUT) + return rc; + + memcpy(reslist, res.virt, res.len); + i2o_dma_free(dev, &res); + + return rc; +} + +/* + * Query one field group value or a whole scalar group. + */ +int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, + void *buf, int buflen) +{ + u32 opblk[] = { cpu_to_le32(0x00000001), + cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET), + cpu_to_le32((s16) field << 16 | 0x00000001) + }; + u8 *resblk; /* 8 bytes for header */ + int rc; + + resblk = kmalloc(buflen + 8, GFP_KERNEL); + if (!resblk) + return -ENOMEM; + + rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, + sizeof(opblk), resblk, buflen + 8); + + memcpy(buf, resblk + 8, buflen); /* cut off header */ + + kfree(resblk); + + return rc; +} + +/* + * if oper == I2O_PARAMS_TABLE_GET, get from all rows + * if fieldcount == -1 return all fields + * ibuf and ibuflen are unused (use NULL, 0) + * else return specific fields + * ibuf contains fieldindexes + * + * if oper == I2O_PARAMS_LIST_GET, get from specific rows + * if fieldcount == -1 return all fields + * ibuf contains rowcount, keyvalues + * else return specific fields + * fieldcount is # of fieldindexes + * ibuf contains fieldindexes, rowcount, keyvalues + * + * You could also use directly function i2o_issue_params(). + */ +int i2o_parm_table_get(struct i2o_device *dev, int oper, int group, + int fieldcount, void *ibuf, int ibuflen, void *resblk, + int reslen) +{ + u16 *opblk; + int size; + + size = 10 + ibuflen; + if (size % 4) + size += 4 - size % 4; + + opblk = kmalloc(size, GFP_KERNEL); + if (opblk == NULL) { + printk(KERN_ERR "i2o: no memory for query buffer.\n"); + return -ENOMEM; + } + + opblk[0] = 1; /* operation count */ + opblk[1] = 0; /* pad */ + opblk[2] = oper; + opblk[3] = group; + opblk[4] = fieldcount; + memcpy(opblk + 5, ibuf, ibuflen); /* other params */ + + size = i2o_parm_issue(dev, I2O_CMD_UTIL_PARAMS_GET, opblk, + size, resblk, reslen); + + kfree(opblk); + if (size > reslen) + return reslen; + + return size; +} + +EXPORT_SYMBOL(i2o_device_claim); +EXPORT_SYMBOL(i2o_device_claim_release); +EXPORT_SYMBOL(i2o_parm_field_get); +EXPORT_SYMBOL(i2o_parm_table_get); +EXPORT_SYMBOL(i2o_parm_issue); diff --git a/drivers/staging/i2o/driver.c b/drivers/staging/i2o/driver.c new file mode 100644 index 0000000..111c3ed --- /dev/null +++ b/drivers/staging/i2o/driver.c @@ -0,0 +1,382 @@ +/* + * Functions to handle I2O drivers (OSMs) and I2O bus type for sysfs + * + * Copyright (C) 2004 Markus Lidel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Fixes/additions: + * Markus Lidel + * initial version. + */ + +#include +#include +#include +#include "i2o.h" +#include +#include +#include +#include "core.h" + +#define OSM_NAME "i2o" + +/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ +static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; +module_param_named(max_drivers, i2o_max_drivers, uint, 0); +MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support"); + +/* I2O drivers lock and array */ +static spinlock_t i2o_drivers_lock; +static struct i2o_driver **i2o_drivers; + +/** + * i2o_bus_match - Tell if I2O device class id matches the class ids of the I2O driver (OSM) + * @dev: device which should be verified + * @drv: the driver to match against + * + * Used by the bus to check if the driver wants to handle the device. + * + * Returns 1 if the class ids of the driver match the class id of the + * device, otherwise 0. + */ +static int i2o_bus_match(struct device *dev, struct device_driver *drv) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_driver *i2o_drv = to_i2o_driver(drv); + struct i2o_class_id *ids = i2o_drv->classes; + + if (ids) + while (ids->class_id != I2O_CLASS_END) { + if (ids->class_id == i2o_dev->lct_data.class_id) + return 1; + ids++; + } + return 0; +}; + +/* I2O bus type */ +struct bus_type i2o_bus_type = { + .name = "i2o", + .match = i2o_bus_match, + .dev_groups = i2o_device_groups, +}; + +/** + * i2o_driver_register - Register a I2O driver (OSM) in the I2O core + * @drv: I2O driver which should be registered + * + * Registers the OSM drv in the I2O core and creates an event queues if + * necessary. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_driver_register(struct i2o_driver *drv) +{ + struct i2o_controller *c; + int i; + int rc = 0; + unsigned long flags; + + osm_debug("Register driver %s\n", drv->name); + + if (drv->event) { + drv->event_queue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, + drv->name); + if (!drv->event_queue) { + osm_err("Could not initialize event queue for driver " + "%s\n", drv->name); + return -EFAULT; + } + osm_debug("Event queue initialized for driver %s\n", drv->name); + } else + drv->event_queue = NULL; + + drv->driver.name = drv->name; + drv->driver.bus = &i2o_bus_type; + + spin_lock_irqsave(&i2o_drivers_lock, flags); + + for (i = 0; i2o_drivers[i]; i++) + if (i >= i2o_max_drivers) { + osm_err("too many drivers registered, increase " + "max_drivers\n"); + spin_unlock_irqrestore(&i2o_drivers_lock, flags); + rc = -EFAULT; + goto out; + } + + drv->context = i; + i2o_drivers[i] = drv; + + spin_unlock_irqrestore(&i2o_drivers_lock, flags); + + osm_debug("driver %s gets context id %d\n", drv->name, drv->context); + + list_for_each_entry(c, &i2o_controllers, list) { + struct i2o_device *i2o_dev; + + i2o_driver_notify_controller_add(drv, c); + list_for_each_entry(i2o_dev, &c->devices, list) + i2o_driver_notify_device_add(drv, i2o_dev); + } + + rc = driver_register(&drv->driver); + if (rc) + goto out; + + return 0; +out: + if (drv->event_queue) { + destroy_workqueue(drv->event_queue); + drv->event_queue = NULL; + } + + return rc; +}; + +/** + * i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core + * @drv: I2O driver which should be unregistered + * + * Unregisters the OSM drv from the I2O core and cleanup event queues if + * necessary. + */ +void i2o_driver_unregister(struct i2o_driver *drv) +{ + struct i2o_controller *c; + unsigned long flags; + + osm_debug("unregister driver %s\n", drv->name); + + driver_unregister(&drv->driver); + + list_for_each_entry(c, &i2o_controllers, list) { + struct i2o_device *i2o_dev; + + list_for_each_entry(i2o_dev, &c->devices, list) + i2o_driver_notify_device_remove(drv, i2o_dev); + + i2o_driver_notify_controller_remove(drv, c); + } + + spin_lock_irqsave(&i2o_drivers_lock, flags); + i2o_drivers[drv->context] = NULL; + spin_unlock_irqrestore(&i2o_drivers_lock, flags); + + if (drv->event_queue) { + destroy_workqueue(drv->event_queue); + drv->event_queue = NULL; + osm_debug("event queue removed for %s\n", drv->name); + } +}; + +/** + * i2o_driver_dispatch - dispatch an I2O reply message + * @c: I2O controller of the message + * @m: I2O message number + * + * The reply is delivered to the driver from which the original message + * was. This function is only called from interrupt context. + * + * Returns 0 on success and the message should not be flushed. Returns > 0 + * on success and if the message should be flushed afterwords. Returns + * negative error code on failure (the message will be flushed too). + */ +int i2o_driver_dispatch(struct i2o_controller *c, u32 m) +{ + struct i2o_driver *drv; + struct i2o_message *msg = i2o_msg_out_to_virt(c, m); + u32 context = le32_to_cpu(msg->u.s.icntxt); + unsigned long flags; + + if (unlikely(context >= i2o_max_drivers)) { + osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, + context); + return -EIO; + } + + spin_lock_irqsave(&i2o_drivers_lock, flags); + drv = i2o_drivers[context]; + spin_unlock_irqrestore(&i2o_drivers_lock, flags); + + if (unlikely(!drv)) { + osm_warn("%s: Spurious reply to unknown driver %d\n", c->name, + context); + return -EIO; + } + + if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { + struct i2o_device *dev, *tmp; + struct i2o_event *evt; + u16 size; + u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff; + + osm_debug("event received from device %d\n", tid); + + if (!drv->event) + return -EIO; + + /* cut of header from message size (in 32-bit words) */ + size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5; + + evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); + if (!evt) + return -ENOMEM; + + evt->size = size; + evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt); + evt->event_indicator = le32_to_cpu(msg->body[0]); + memcpy(&evt->data, &msg->body[1], size * 4); + + list_for_each_entry_safe(dev, tmp, &c->devices, list) + if (dev->lct_data.tid == tid) { + evt->i2o_dev = dev; + break; + } + + INIT_WORK(&evt->work, drv->event); + queue_work(drv->event_queue, &evt->work); + return 1; + } + + if (unlikely(!drv->reply)) { + osm_debug("%s: Reply to driver %s, but no reply function" + " defined!\n", c->name, drv->name); + return -EIO; + } + + return drv->reply(c, m, msg); +} + +/** + * i2o_driver_notify_controller_add_all - Send notify of added controller + * @c: newly added controller + * + * Send notifications to all registered drivers that a new controller was + * added. + */ +void i2o_driver_notify_controller_add_all(struct i2o_controller *c) +{ + int i; + struct i2o_driver *drv; + + for (i = 0; i < i2o_max_drivers; i++) { + drv = i2o_drivers[i]; + + if (drv) + i2o_driver_notify_controller_add(drv, c); + } +} + +/** + * i2o_driver_notify_controller_remove_all - Send notify of removed controller + * @c: controller that is being removed + * + * Send notifications to all registered drivers that a controller was + * removed. + */ +void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) +{ + int i; + struct i2o_driver *drv; + + for (i = 0; i < i2o_max_drivers; i++) { + drv = i2o_drivers[i]; + + if (drv) + i2o_driver_notify_controller_remove(drv, c); + } +} + +/** + * i2o_driver_notify_device_add_all - Send notify of added device + * @i2o_dev: newly added I2O device + * + * Send notifications to all registered drivers that a device was added. + */ +void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) +{ + int i; + struct i2o_driver *drv; + + for (i = 0; i < i2o_max_drivers; i++) { + drv = i2o_drivers[i]; + + if (drv) + i2o_driver_notify_device_add(drv, i2o_dev); + } +} + +/** + * i2o_driver_notify_device_remove_all - Send notify of removed device + * @i2o_dev: device that is being removed + * + * Send notifications to all registered drivers that a device was removed. + */ +void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev) +{ + int i; + struct i2o_driver *drv; + + for (i = 0; i < i2o_max_drivers; i++) { + drv = i2o_drivers[i]; + + if (drv) + i2o_driver_notify_device_remove(drv, i2o_dev); + } +} + +/** + * i2o_driver_init - initialize I2O drivers (OSMs) + * + * Registers the I2O bus and allocate memory for the array of OSMs. + * + * Returns 0 on success or negative error code on failure. + */ +int __init i2o_driver_init(void) +{ + int rc = 0; + + spin_lock_init(&i2o_drivers_lock); + + if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64)) { + osm_warn("max_drivers set to %d, but must be >=2 and <= 64\n", + i2o_max_drivers); + i2o_max_drivers = I2O_MAX_DRIVERS; + } + osm_info("max drivers = %d\n", i2o_max_drivers); + + i2o_drivers = + kcalloc(i2o_max_drivers, sizeof(*i2o_drivers), GFP_KERNEL); + if (!i2o_drivers) + return -ENOMEM; + + rc = bus_register(&i2o_bus_type); + + if (rc < 0) + kfree(i2o_drivers); + + return rc; +}; + +/** + * i2o_driver_exit - clean up I2O drivers (OSMs) + * + * Unregisters the I2O bus and frees driver array. + */ +void i2o_driver_exit(void) +{ + bus_unregister(&i2o_bus_type); + kfree(i2o_drivers); +}; + +EXPORT_SYMBOL(i2o_driver_register); +EXPORT_SYMBOL(i2o_driver_unregister); +EXPORT_SYMBOL(i2o_driver_notify_controller_add_all); +EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all); +EXPORT_SYMBOL(i2o_driver_notify_device_add_all); +EXPORT_SYMBOL(i2o_driver_notify_device_remove_all); diff --git a/drivers/staging/i2o/exec-osm.c b/drivers/staging/i2o/exec-osm.c new file mode 100644 index 0000000..16d857d --- /dev/null +++ b/drivers/staging/i2o/exec-osm.c @@ -0,0 +1,612 @@ +/* + * Executive OSM + * + * Copyright (C) 1999-2002 Red Hat Software + * + * Written by Alan Cox, Building Number Three Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * A lot of the I2O message side code from this is taken from the Red + * Creek RCPCI45 adapter driver by Red Creek Communications + * + * Fixes/additions: + * Philipp Rumpf + * Juha Sievänen + * Auvo Häkkinen + * Deepak Saxena + * Boji T Kannanthanam + * Alan Cox : + * Ported to Linux 2.5. + * Markus Lidel : + * Minor fixes for 2.6. + * Markus Lidel : + * Support for sysfs included. + */ + +#include +#include "i2o.h" +#include +#include +#include +#include +#include /* wait_event_interruptible_timeout() needs this */ +#include /* HZ */ +#include "core.h" + +#define OSM_NAME "exec-osm" + +struct i2o_driver i2o_exec_driver; + +/* global wait list for POST WAIT */ +static LIST_HEAD(i2o_exec_wait_list); + +/* Wait struct needed for POST WAIT */ +struct i2o_exec_wait { + wait_queue_head_t *wq; /* Pointer to Wait queue */ + struct i2o_dma dma; /* DMA buffers to free on failure */ + u32 tcntxt; /* transaction context from reply */ + int complete; /* 1 if reply received otherwise 0 */ + u32 m; /* message id */ + struct i2o_message *msg; /* pointer to the reply message */ + struct list_head list; /* node in global wait list */ + spinlock_t lock; /* lock before modifying */ +}; + +/* Work struct needed to handle LCT NOTIFY replies */ +struct i2o_exec_lct_notify_work { + struct work_struct work; /* work struct */ + struct i2o_controller *c; /* controller on which the LCT NOTIFY + was received */ +}; + +/* Exec OSM class handling definition */ +static struct i2o_class_id i2o_exec_class_id[] = { + {I2O_CLASS_EXECUTIVE}, + {I2O_CLASS_END} +}; + +/** + * i2o_exec_wait_alloc - Allocate a i2o_exec_wait struct an initialize it + * + * Allocate the i2o_exec_wait struct and initialize the wait. + * + * Returns i2o_exec_wait pointer on success or negative error code on + * failure. + */ +static struct i2o_exec_wait *i2o_exec_wait_alloc(void) +{ + struct i2o_exec_wait *wait; + + wait = kzalloc(sizeof(*wait), GFP_KERNEL); + if (!wait) + return NULL; + + INIT_LIST_HEAD(&wait->list); + spin_lock_init(&wait->lock); + + return wait; +}; + +/** + * i2o_exec_wait_free - Free an i2o_exec_wait struct + * @wait: I2O wait data which should be cleaned up + */ +static void i2o_exec_wait_free(struct i2o_exec_wait *wait) +{ + kfree(wait); +}; + +/** + * i2o_msg_post_wait_mem - Post and wait a message with DMA buffers + * @c: controller + * @msg: message to post + * @timeout: time in seconds to wait + * @dma: i2o_dma struct of the DMA buffer to free on failure + * + * This API allows an OSM to post a message and then be told whether or + * not the system received a successful reply. If the message times out + * then the value '-ETIMEDOUT' is returned. This is a special case. In + * this situation the message may (should) complete at an indefinite time + * in the future. When it completes it will use the memory buffer + * attached to the request. If -ETIMEDOUT is returned then the memory + * buffer must not be freed. Instead the event completion will free them + * for you. In all other cases the buffer are your problem. + * + * Returns 0 on success, negative error code on timeout or positive error + * code from reply. + */ +int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, + unsigned long timeout, struct i2o_dma *dma) +{ + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); + struct i2o_exec_wait *wait; + static u32 tcntxt = 0x80000000; + unsigned long flags; + int rc = 0; + + wait = i2o_exec_wait_alloc(); + if (!wait) { + i2o_msg_nop(c, msg); + return -ENOMEM; + } + + if (tcntxt == 0xffffffff) + tcntxt = 0x80000000; + + if (dma) + wait->dma = *dma; + + /* + * Fill in the message initiator context and transaction context. + * We will only use transaction contexts >= 0x80000000 for POST WAIT, + * so we could find a POST WAIT reply easier in the reply handler. + */ + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + wait->tcntxt = tcntxt++; + msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt); + + wait->wq = &wq; + /* + * we add elements to the head, because if a entry in the list will + * never be removed, we have to iterate over it every time + */ + list_add(&wait->list, &i2o_exec_wait_list); + + /* + * Post the message to the controller. At some point later it will + * return. If we time out before it returns then complete will be zero. + */ + i2o_msg_post(c, msg); + + wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ); + + spin_lock_irqsave(&wait->lock, flags); + + wait->wq = NULL; + + if (wait->complete) + rc = le32_to_cpu(wait->msg->body[0]) >> 24; + else { + /* + * We cannot remove it now. This is important. When it does + * terminate (which it must do if the controller has not + * died...) then it will otherwise scribble on stuff. + * + * FIXME: try abort message + */ + if (dma) + dma->virt = NULL; + + rc = -ETIMEDOUT; + } + + spin_unlock_irqrestore(&wait->lock, flags); + + if (rc != -ETIMEDOUT) { + i2o_flush_reply(c, wait->m); + i2o_exec_wait_free(wait); + } + + return rc; +}; + +/** + * i2o_msg_post_wait_complete - Reply to a i2o_msg_post request from IOP + * @c: I2O controller which answers + * @m: message id + * @msg: pointer to the I2O reply message + * @context: transaction context of request + * + * This function is called in interrupt context only. If the reply reached + * before the timeout, the i2o_exec_wait struct is filled with the message + * and the task will be waked up. The task is now responsible for returning + * the message m back to the controller! If the message reaches us after + * the timeout clean up the i2o_exec_wait struct (including allocated + * DMA buffer). + * + * Return 0 on success and if the message m should not be given back to the + * I2O controller, or >0 on success and if the message should be given back + * afterwords. Returns negative error code on failure. In this case the + * message must also be given back to the controller. + */ +static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, + struct i2o_message *msg, u32 context) +{ + struct i2o_exec_wait *wait, *tmp; + unsigned long flags; + int rc = 1; + + /* + * We need to search through the i2o_exec_wait_list to see if the given + * message is still outstanding. If not, it means that the IOP took + * longer to respond to the message than we had allowed and timer has + * already expired. Not much we can do about that except log it for + * debug purposes, increase timeout, and recompile. + */ + list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) { + if (wait->tcntxt == context) { + spin_lock_irqsave(&wait->lock, flags); + + list_del(&wait->list); + + wait->m = m; + wait->msg = msg; + wait->complete = 1; + + if (wait->wq) + rc = 0; + else + rc = -1; + + spin_unlock_irqrestore(&wait->lock, flags); + + if (rc) { + struct device *dev; + + dev = &c->pdev->dev; + + pr_debug("%s: timedout reply received!\n", + c->name); + i2o_dma_free(dev, &wait->dma); + i2o_exec_wait_free(wait); + } else + wake_up_interruptible(wait->wq); + + return rc; + } + } + + osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name, + context); + + return -1; +}; + +/** + * i2o_exec_show_vendor_id - Displays Vendor ID of controller + * @d: device of which the Vendor ID should be displayed + * @attr: device_attribute to display + * @buf: buffer into which the Vendor ID should be printed + * + * Returns number of bytes printed into buffer. + */ +static ssize_t i2o_exec_show_vendor_id(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct i2o_device *dev = to_i2o_device(d); + u16 id; + + if (!i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) { + sprintf(buf, "0x%04x", le16_to_cpu(id)); + return strlen(buf) + 1; + } + + return 0; +}; + +/** + * i2o_exec_show_product_id - Displays Product ID of controller + * @d: device of which the Product ID should be displayed + * @attr: device_attribute to display + * @buf: buffer into which the Product ID should be printed + * + * Returns number of bytes printed into buffer. + */ +static ssize_t i2o_exec_show_product_id(struct device *d, + struct device_attribute *attr, + char *buf) +{ + struct i2o_device *dev = to_i2o_device(d); + u16 id; + + if (!i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) { + sprintf(buf, "0x%04x", le16_to_cpu(id)); + return strlen(buf) + 1; + } + + return 0; +}; + +/* Exec-OSM device attributes */ +static DEVICE_ATTR(vendor_id, S_IRUGO, i2o_exec_show_vendor_id, NULL); +static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL); + +/** + * i2o_exec_probe - Called if a new I2O device (executive class) appears + * @dev: I2O device which should be probed + * + * Registers event notification for every event from Executive device. The + * return is always 0, because we want all devices of class Executive. + * + * Returns 0 on success. + */ +static int i2o_exec_probe(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + int rc; + + rc = i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); + if (rc) goto err_out; + + rc = device_create_file(dev, &dev_attr_vendor_id); + if (rc) goto err_evtreg; + rc = device_create_file(dev, &dev_attr_product_id); + if (rc) goto err_vid; + + i2o_dev->iop->exec = i2o_dev; + + return 0; + +err_vid: + device_remove_file(dev, &dev_attr_vendor_id); +err_evtreg: + i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); +err_out: + return rc; +}; + +/** + * i2o_exec_remove - Called on I2O device removal + * @dev: I2O device which was removed + * + * Unregisters event notification from Executive I2O device. + * + * Returns 0 on success. + */ +static int i2o_exec_remove(struct device *dev) +{ + device_remove_file(dev, &dev_attr_product_id); + device_remove_file(dev, &dev_attr_vendor_id); + + i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); + + return 0; +}; + +#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES +/** + * i2o_exec_lct_notify - Send a asynchronus LCT NOTIFY request + * @c: I2O controller to which the request should be send + * @change_ind: change indicator + * + * This function sends a LCT NOTIFY request to the I2O controller with + * the change indicator change_ind. If the change_ind == 0 the controller + * replies immediately after the request. If change_ind > 0 the reply is + * send after change indicator of the LCT is > change_ind. + */ +static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) +{ + i2o_status_block *sb = c->status_block.virt; + struct device *dev; + struct i2o_message *msg; + + mutex_lock(&c->lct_lock); + + dev = &c->pdev->dev; + + if (i2o_dma_realloc(dev, &c->dlct, + le32_to_cpu(sb->expected_lct_size))) { + mutex_unlock(&c->lct_lock); + return -ENOMEM; + } + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) { + mutex_unlock(&c->lct_lock); + return PTR_ERR(msg); + } + + msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); + msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(0xffffffff); + msg->body[1] = cpu_to_le32(change_ind); + msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len); + msg->body[3] = cpu_to_le32(c->dlct.phys); + + i2o_msg_post(c, msg); + + mutex_unlock(&c->lct_lock); + + return 0; +} +#endif + +/** + * i2o_exec_lct_modified - Called on LCT NOTIFY reply + * @_work: work struct for a specific controller + * + * This function handles asynchronus LCT NOTIFY replies. It parses the + * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY + * again, otherwise send LCT NOTIFY to get informed on next LCT change. + */ +static void i2o_exec_lct_modified(struct work_struct *_work) +{ + struct i2o_exec_lct_notify_work *work = + container_of(_work, struct i2o_exec_lct_notify_work, work); + u32 change_ind = 0; + struct i2o_controller *c = work->c; + + kfree(work); + + if (i2o_device_parse_lct(c) != -EAGAIN) + change_ind = c->lct->change_ind + 1; + +#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES + i2o_exec_lct_notify(c, change_ind); +#endif +}; + +/** + * i2o_exec_reply - I2O Executive reply handler + * @c: I2O controller from which the reply comes + * @m: message id + * @msg: pointer to the I2O reply message + * + * This function is always called from interrupt context. If a POST WAIT + * reply was received, pass it to the complete function. If a LCT NOTIFY + * reply was received, a new event is created to handle the update. + * + * Returns 0 on success and if the reply should not be flushed or > 0 + * on success and if the reply should be flushed. Returns negative error + * code on failure and if the reply should be flushed. + */ +static int i2o_exec_reply(struct i2o_controller *c, u32 m, + struct i2o_message *msg) +{ + u32 context; + + if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { + struct i2o_message __iomem *pmsg; + u32 pm; + + /* + * If Fail bit is set we must take the transaction context of + * the preserved message to find the right request again. + */ + + pm = le32_to_cpu(msg->body[3]); + pmsg = i2o_msg_in_to_virt(c, pm); + context = readl(&pmsg->u.s.tcntxt); + + i2o_report_status(KERN_INFO, "i2o_core", msg); + + /* Release the preserved msg */ + i2o_msg_nop_mfa(c, pm); + } else + context = le32_to_cpu(msg->u.s.tcntxt); + + if (context & 0x80000000) + return i2o_msg_post_wait_complete(c, m, msg, context); + + if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) { + struct i2o_exec_lct_notify_work *work; + + pr_debug("%s: LCT notify received\n", c->name); + + work = kmalloc(sizeof(*work), GFP_ATOMIC); + if (!work) + return -ENOMEM; + + work->c = c; + + INIT_WORK(&work->work, i2o_exec_lct_modified); + queue_work(i2o_exec_driver.event_queue, &work->work); + return 1; + } + + /* + * If this happens, we want to dump the message to the syslog so + * it can be sent back to the card manufacturer by the end user + * to aid in debugging. + * + */ + printk(KERN_WARNING "%s: Unsolicited message reply sent to core!" + "Message dumped to syslog\n", c->name); + i2o_dump_message(msg); + + return -EFAULT; +} + +/** + * i2o_exec_event - Event handling function + * @work: Work item in occurring event + * + * Handles events send by the Executive device. At the moment does not do + * anything useful. + */ +static void i2o_exec_event(struct work_struct *work) +{ + struct i2o_event *evt = container_of(work, struct i2o_event, work); + + if (likely(evt->i2o_dev)) + osm_debug("Event received from device: %d\n", + evt->i2o_dev->lct_data.tid); + kfree(evt); +}; + +/** + * i2o_exec_lct_get - Get the IOP's Logical Configuration Table + * @c: I2O controller from which the LCT should be fetched + * + * Send a LCT NOTIFY request to the controller, and wait + * I2O_TIMEOUT_LCT_GET seconds until arrival of response. If the LCT is + * to large, retry it. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_exec_lct_get(struct i2o_controller *c) +{ + struct i2o_message *msg; + int i = 0; + int rc = -EAGAIN; + + for (i = 1; i <= I2O_LCT_GET_TRIES; i++) { + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = + cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->body[0] = cpu_to_le32(0xffffffff); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len); + msg->body[3] = cpu_to_le32(c->dlct.phys); + + rc = i2o_msg_post_wait(c, msg, I2O_TIMEOUT_LCT_GET); + if (rc < 0) + break; + + rc = i2o_device_parse_lct(c); + if (rc != -EAGAIN) + break; + } + + return rc; +} + +/* Exec OSM driver struct */ +struct i2o_driver i2o_exec_driver = { + .name = OSM_NAME, + .reply = i2o_exec_reply, + .event = i2o_exec_event, + .classes = i2o_exec_class_id, + .driver = { + .probe = i2o_exec_probe, + .remove = i2o_exec_remove, + }, +}; + +/** + * i2o_exec_init - Registers the Exec OSM + * + * Registers the Exec OSM in the I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +int __init i2o_exec_init(void) +{ + return i2o_driver_register(&i2o_exec_driver); +}; + +/** + * i2o_exec_exit - Removes the Exec OSM + * + * Unregisters the Exec OSM from the I2O core. + */ +void i2o_exec_exit(void) +{ + i2o_driver_unregister(&i2o_exec_driver); +}; + +EXPORT_SYMBOL(i2o_msg_post_wait_mem); +EXPORT_SYMBOL(i2o_exec_lct_get); diff --git a/drivers/staging/i2o/i2o.h b/drivers/staging/i2o/i2o.h new file mode 100644 index 0000000..d23c3c2 --- /dev/null +++ b/drivers/staging/i2o/i2o.h @@ -0,0 +1,988 @@ +/* + * I2O kernel space accessible structures/APIs + * + * (c) Copyright 1999, 2000 Red Hat Software + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + ************************************************************************* + * + * This header file defined the I2O APIs/structures for use by + * the I2O kernel modules. + * + */ + +#ifndef _I2O_H +#define _I2O_H + +#include + +/* How many different OSM's are we allowing */ +#define I2O_MAX_DRIVERS 8 + +#include +#include +#include +#include +#include +#include /* work_struct */ +#include +#include +#include +#include /* Needed for MUTEX init macros */ + +#include + +/* message queue empty */ +#define I2O_QUEUE_EMPTY 0xffffffff + +/* + * Cache strategies + */ + +/* The NULL strategy leaves everything up to the controller. This tends to be a + * pessimal but functional choice. + */ +#define CACHE_NULL 0 +/* Prefetch data when reading. We continually attempt to load the next 32 sectors + * into the controller cache. + */ +#define CACHE_PREFETCH 1 +/* Prefetch data when reading. We sometimes attempt to load the next 32 sectors + * into the controller cache. When an I/O is less <= 8K we assume its probably + * not sequential and don't prefetch (default) + */ +#define CACHE_SMARTFETCH 2 +/* Data is written to the cache and then out on to the disk. The I/O must be + * physically on the medium before the write is acknowledged (default without + * NVRAM) + */ +#define CACHE_WRITETHROUGH 17 +/* Data is written to the cache and then out on to the disk. The controller + * is permitted to write back the cache any way it wants. (default if battery + * backed NVRAM is present). It can be useful to set this for swap regardless of + * battery state. + */ +#define CACHE_WRITEBACK 18 +/* Optimise for under powered controllers, especially on RAID1 and RAID0. We + * write large I/O's directly to disk bypassing the cache to avoid the extra + * memory copy hits. Small writes are writeback cached + */ +#define CACHE_SMARTBACK 19 +/* Optimise for under powered controllers, especially on RAID1 and RAID0. We + * write large I/O's directly to disk bypassing the cache to avoid the extra + * memory copy hits. Small writes are writethrough cached. Suitable for devices + * lacking battery backup + */ +#define CACHE_SMARTTHROUGH 20 + +/* + * Ioctl structures + */ + +#define BLKI2OGRSTRAT _IOR('2', 1, int) +#define BLKI2OGWSTRAT _IOR('2', 2, int) +#define BLKI2OSRSTRAT _IOW('2', 3, int) +#define BLKI2OSWSTRAT _IOW('2', 4, int) + +/* + * I2O Function codes + */ + +/* + * Executive Class + */ +#define I2O_CMD_ADAPTER_ASSIGN 0xB3 +#define I2O_CMD_ADAPTER_READ 0xB2 +#define I2O_CMD_ADAPTER_RELEASE 0xB5 +#define I2O_CMD_BIOS_INFO_SET 0xA5 +#define I2O_CMD_BOOT_DEVICE_SET 0xA7 +#define I2O_CMD_CONFIG_VALIDATE 0xBB +#define I2O_CMD_CONN_SETUP 0xCA +#define I2O_CMD_DDM_DESTROY 0xB1 +#define I2O_CMD_DDM_ENABLE 0xD5 +#define I2O_CMD_DDM_QUIESCE 0xC7 +#define I2O_CMD_DDM_RESET 0xD9 +#define I2O_CMD_DDM_SUSPEND 0xAF +#define I2O_CMD_DEVICE_ASSIGN 0xB7 +#define I2O_CMD_DEVICE_RELEASE 0xB9 +#define I2O_CMD_HRT_GET 0xA8 +#define I2O_CMD_ADAPTER_CLEAR 0xBE +#define I2O_CMD_ADAPTER_CONNECT 0xC9 +#define I2O_CMD_ADAPTER_RESET 0xBD +#define I2O_CMD_LCT_NOTIFY 0xA2 +#define I2O_CMD_OUTBOUND_INIT 0xA1 +#define I2O_CMD_PATH_ENABLE 0xD3 +#define I2O_CMD_PATH_QUIESCE 0xC5 +#define I2O_CMD_PATH_RESET 0xD7 +#define I2O_CMD_STATIC_MF_CREATE 0xDD +#define I2O_CMD_STATIC_MF_RELEASE 0xDF +#define I2O_CMD_STATUS_GET 0xA0 +#define I2O_CMD_SW_DOWNLOAD 0xA9 +#define I2O_CMD_SW_UPLOAD 0xAB +#define I2O_CMD_SW_REMOVE 0xAD +#define I2O_CMD_SYS_ENABLE 0xD1 +#define I2O_CMD_SYS_MODIFY 0xC1 +#define I2O_CMD_SYS_QUIESCE 0xC3 +#define I2O_CMD_SYS_TAB_SET 0xA3 + +/* + * Utility Class + */ +#define I2O_CMD_UTIL_NOP 0x00 +#define I2O_CMD_UTIL_ABORT 0x01 +#define I2O_CMD_UTIL_CLAIM 0x09 +#define I2O_CMD_UTIL_RELEASE 0x0B +#define I2O_CMD_UTIL_PARAMS_GET 0x06 +#define I2O_CMD_UTIL_PARAMS_SET 0x05 +#define I2O_CMD_UTIL_EVT_REGISTER 0x13 +#define I2O_CMD_UTIL_EVT_ACK 0x14 +#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10 +#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D +#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F +#define I2O_CMD_UTIL_LOCK 0x17 +#define I2O_CMD_UTIL_LOCK_RELEASE 0x19 +#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15 + +/* + * SCSI Host Bus Adapter Class + */ +#define I2O_CMD_SCSI_EXEC 0x81 +#define I2O_CMD_SCSI_ABORT 0x83 +#define I2O_CMD_SCSI_BUSRESET 0x27 + +/* + * Bus Adapter Class + */ +#define I2O_CMD_BUS_ADAPTER_RESET 0x85 +#define I2O_CMD_BUS_RESET 0x87 +#define I2O_CMD_BUS_SCAN 0x89 +#define I2O_CMD_BUS_QUIESCE 0x8b + +/* + * Random Block Storage Class + */ +#define I2O_CMD_BLOCK_READ 0x30 +#define I2O_CMD_BLOCK_WRITE 0x31 +#define I2O_CMD_BLOCK_CFLUSH 0x37 +#define I2O_CMD_BLOCK_MLOCK 0x49 +#define I2O_CMD_BLOCK_MUNLOCK 0x4B +#define I2O_CMD_BLOCK_MMOUNT 0x41 +#define I2O_CMD_BLOCK_MEJECT 0x43 +#define I2O_CMD_BLOCK_POWER 0x70 + +#define I2O_CMD_PRIVATE 0xFF + +/* Command status values */ + +#define I2O_CMD_IN_PROGRESS 0x01 +#define I2O_CMD_REJECTED 0x02 +#define I2O_CMD_FAILED 0x03 +#define I2O_CMD_COMPLETED 0x04 + +/* I2O API function return values */ + +#define I2O_RTN_NO_ERROR 0 +#define I2O_RTN_NOT_INIT 1 +#define I2O_RTN_FREE_Q_EMPTY 2 +#define I2O_RTN_TCB_ERROR 3 +#define I2O_RTN_TRANSACTION_ERROR 4 +#define I2O_RTN_ADAPTER_ALREADY_INIT 5 +#define I2O_RTN_MALLOC_ERROR 6 +#define I2O_RTN_ADPTR_NOT_REGISTERED 7 +#define I2O_RTN_MSG_REPLY_TIMEOUT 8 +#define I2O_RTN_NO_STATUS 9 +#define I2O_RTN_NO_FIRM_VER 10 +#define I2O_RTN_NO_LINK_SPEED 11 + +/* Reply message status defines for all messages */ + +#define I2O_REPLY_STATUS_SUCCESS 0x00 +#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 +#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 +#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 +#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 +#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 +#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 +#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 +#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 +#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A +#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B +#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 + +/* Status codes and Error Information for Parameter functions */ + +#define I2O_PARAMS_STATUS_SUCCESS 0x00 +#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01 +#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02 +#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03 +#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04 +#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05 +#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06 +#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07 +#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08 +#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09 +#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A +#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B +#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C +#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D +#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E +#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F +#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10 + +/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error + * messages: Table 3-2 Detailed Status Codes.*/ + +#define I2O_DSC_SUCCESS 0x0000 +#define I2O_DSC_BAD_KEY 0x0002 +#define I2O_DSC_TCL_ERROR 0x0003 +#define I2O_DSC_REPLY_BUFFER_FULL 0x0004 +#define I2O_DSC_NO_SUCH_PAGE 0x0005 +#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006 +#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007 +#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009 +#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A +#define I2O_DSC_DEVICE_LOCKED 0x000B +#define I2O_DSC_DEVICE_RESET 0x000C +#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D +#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E +#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F +#define I2O_DSC_INVALID_OFFSET 0x0010 +#define I2O_DSC_INVALID_PARAMETER 0x0011 +#define I2O_DSC_INVALID_REQUEST 0x0012 +#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013 +#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014 +#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015 +#define I2O_DSC_MISSING_PARAMETER 0x0016 +#define I2O_DSC_TIMEOUT 0x0017 +#define I2O_DSC_UNKNOWN_ERROR 0x0018 +#define I2O_DSC_UNKNOWN_FUNCTION 0x0019 +#define I2O_DSC_UNSUPPORTED_VERSION 0x001A +#define I2O_DSC_DEVICE_BUSY 0x001B +#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C + +/* DetailedStatusCode defines for Block Storage Operation: Table 6-7 Detailed + Status Codes.*/ + +#define I2O_BSA_DSC_SUCCESS 0x0000 +#define I2O_BSA_DSC_MEDIA_ERROR 0x0001 +#define I2O_BSA_DSC_ACCESS_ERROR 0x0002 +#define I2O_BSA_DSC_DEVICE_FAILURE 0x0003 +#define I2O_BSA_DSC_DEVICE_NOT_READY 0x0004 +#define I2O_BSA_DSC_MEDIA_NOT_PRESENT 0x0005 +#define I2O_BSA_DSC_MEDIA_LOCKED 0x0006 +#define I2O_BSA_DSC_MEDIA_FAILURE 0x0007 +#define I2O_BSA_DSC_PROTOCOL_FAILURE 0x0008 +#define I2O_BSA_DSC_BUS_FAILURE 0x0009 +#define I2O_BSA_DSC_ACCESS_VIOLATION 0x000A +#define I2O_BSA_DSC_WRITE_PROTECTED 0x000B +#define I2O_BSA_DSC_DEVICE_RESET 0x000C +#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D +#define I2O_BSA_DSC_TIMEOUT 0x000E + +/* FailureStatusCodes, Table 3-3 Message Failure Codes */ + +#define I2O_FSC_TRANSPORT_SERVICE_SUSPENDED 0x81 +#define I2O_FSC_TRANSPORT_SERVICE_TERMINATED 0x82 +#define I2O_FSC_TRANSPORT_CONGESTION 0x83 +#define I2O_FSC_TRANSPORT_FAILURE 0x84 +#define I2O_FSC_TRANSPORT_STATE_ERROR 0x85 +#define I2O_FSC_TRANSPORT_TIME_OUT 0x86 +#define I2O_FSC_TRANSPORT_ROUTING_FAILURE 0x87 +#define I2O_FSC_TRANSPORT_INVALID_VERSION 0x88 +#define I2O_FSC_TRANSPORT_INVALID_OFFSET 0x89 +#define I2O_FSC_TRANSPORT_INVALID_MSG_FLAGS 0x8A +#define I2O_FSC_TRANSPORT_FRAME_TOO_SMALL 0x8B +#define I2O_FSC_TRANSPORT_FRAME_TOO_LARGE 0x8C +#define I2O_FSC_TRANSPORT_INVALID_TARGET_ID 0x8D +#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_ID 0x8E +#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_CONTEXT 0x8F +#define I2O_FSC_TRANSPORT_UNKNOWN_FAILURE 0xFF + +/* Device Claim Types */ +#define I2O_CLAIM_PRIMARY 0x01000000 +#define I2O_CLAIM_MANAGEMENT 0x02000000 +#define I2O_CLAIM_AUTHORIZED 0x03000000 +#define I2O_CLAIM_SECONDARY 0x04000000 + +/* Message header defines for VersionOffset */ +#define I2OVER15 0x0001 +#define I2OVER20 0x0002 + +/* Default is 1.5 */ +#define I2OVERSION I2OVER15 + +#define SGL_OFFSET_0 I2OVERSION +#define SGL_OFFSET_4 (0x0040 | I2OVERSION) +#define SGL_OFFSET_5 (0x0050 | I2OVERSION) +#define SGL_OFFSET_6 (0x0060 | I2OVERSION) +#define SGL_OFFSET_7 (0x0070 | I2OVERSION) +#define SGL_OFFSET_8 (0x0080 | I2OVERSION) +#define SGL_OFFSET_9 (0x0090 | I2OVERSION) +#define SGL_OFFSET_10 (0x00A0 | I2OVERSION) +#define SGL_OFFSET_11 (0x00B0 | I2OVERSION) +#define SGL_OFFSET_12 (0x00C0 | I2OVERSION) +#define SGL_OFFSET(x) (((x)<<4) | I2OVERSION) + +/* Transaction Reply Lists (TRL) Control Word structure */ +#define TRL_SINGLE_FIXED_LENGTH 0x00 +#define TRL_SINGLE_VARIABLE_LENGTH 0x40 +#define TRL_MULTIPLE_FIXED_LENGTH 0x80 + + /* msg header defines for MsgFlags */ +#define MSG_STATIC 0x0100 +#define MSG_64BIT_CNTXT 0x0200 +#define MSG_MULTI_TRANS 0x1000 +#define MSG_FAIL 0x2000 +#define MSG_FINAL 0x4000 +#define MSG_REPLY 0x8000 + + /* minimum size msg */ +#define THREE_WORD_MSG_SIZE 0x00030000 +#define FOUR_WORD_MSG_SIZE 0x00040000 +#define FIVE_WORD_MSG_SIZE 0x00050000 +#define SIX_WORD_MSG_SIZE 0x00060000 +#define SEVEN_WORD_MSG_SIZE 0x00070000 +#define EIGHT_WORD_MSG_SIZE 0x00080000 +#define NINE_WORD_MSG_SIZE 0x00090000 +#define TEN_WORD_MSG_SIZE 0x000A0000 +#define ELEVEN_WORD_MSG_SIZE 0x000B0000 +#define I2O_MESSAGE_SIZE(x) ((x)<<16) + +/* special TID assignments */ +#define ADAPTER_TID 0 +#define HOST_TID 1 + +/* outbound queue defines */ +#define I2O_MAX_OUTBOUND_MSG_FRAMES 128 +#define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */ + +/* inbound queue definitions */ +#define I2O_MSG_INPOOL_MIN 32 +#define I2O_INBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */ + +#define I2O_POST_WAIT_OK 0 +#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT + +#define I2O_CONTEXT_LIST_MIN_LENGTH 15 +#define I2O_CONTEXT_LIST_USED 0x01 +#define I2O_CONTEXT_LIST_DELETED 0x02 + +/* timeouts */ +#define I2O_TIMEOUT_INIT_OUTBOUND_QUEUE 15 +#define I2O_TIMEOUT_MESSAGE_GET 5 +#define I2O_TIMEOUT_RESET 30 +#define I2O_TIMEOUT_STATUS_GET 5 +#define I2O_TIMEOUT_LCT_GET 360 +#define I2O_TIMEOUT_SCSI_SCB_ABORT 240 + +/* retries */ +#define I2O_HRT_GET_TRIES 3 +#define I2O_LCT_GET_TRIES 3 + +/* defines for max_sectors and max_phys_segments */ +#define I2O_MAX_SECTORS 1024 +#define I2O_MAX_SECTORS_LIMITED 128 +#define I2O_MAX_PHYS_SEGMENTS BLK_MAX_SEGMENTS + +/* + * Message structures + */ +struct i2o_message { + union { + struct { + u8 version_offset; + u8 flags; + u16 size; + u32 target_tid:12; + u32 init_tid:12; + u32 function:8; + u32 icntxt; /* initiator context */ + u32 tcntxt; /* transaction context */ + } s; + u32 head[4]; + } u; + /* List follows */ + u32 body[0]; +}; + +/* MFA and I2O message used by mempool */ +struct i2o_msg_mfa { + u32 mfa; /* MFA returned by the controller */ + struct i2o_message msg; /* I2O message */ +}; + +/* + * Each I2O device entity has one of these. There is one per device. + */ +struct i2o_device { + i2o_lct_entry lct_data; /* Device LCT information */ + + struct i2o_controller *iop; /* Controlling IOP */ + struct list_head list; /* node in IOP devices list */ + + struct device device; + + struct mutex lock; /* device lock */ +}; + +/* + * Event structure provided to the event handling function + */ +struct i2o_event { + struct work_struct work; + struct i2o_device *i2o_dev; /* I2O device pointer from which the + event reply was initiated */ + u16 size; /* Size of data in 32-bit words */ + u32 tcntxt; /* Transaction context used at + registration */ + u32 event_indicator; /* Event indicator from reply */ + u32 data[0]; /* Event data from reply */ +}; + +/* + * I2O classes which could be handled by the OSM + */ +struct i2o_class_id { + u16 class_id:12; +}; + +/* + * I2O driver structure for OSMs + */ +struct i2o_driver { + char *name; /* OSM name */ + int context; /* Low 8 bits of the transaction info */ + struct i2o_class_id *classes; /* I2O classes that this OSM handles */ + + /* Message reply handler */ + int (*reply) (struct i2o_controller *, u32, struct i2o_message *); + + /* Event handler */ + work_func_t event; + + struct workqueue_struct *event_queue; /* Event queue */ + + struct device_driver driver; + + /* notification of changes */ + void (*notify_controller_add) (struct i2o_controller *); + void (*notify_controller_remove) (struct i2o_controller *); + void (*notify_device_add) (struct i2o_device *); + void (*notify_device_remove) (struct i2o_device *); + + struct semaphore lock; +}; + +/* + * Contains DMA mapped address information + */ +struct i2o_dma { + void *virt; + dma_addr_t phys; + size_t len; +}; + +/* + * Contains slab cache and mempool information + */ +struct i2o_pool { + char *name; + struct kmem_cache *slab; + mempool_t *mempool; +}; + +/* + * Contains IO mapped address information + */ +struct i2o_io { + void __iomem *virt; + unsigned long phys; + unsigned long len; +}; + +/* + * Context queue entry, used for 32-bit context on 64-bit systems + */ +struct i2o_context_list_element { + struct list_head list; + u32 context; + void *ptr; + unsigned long timestamp; +}; + +/* + * Each I2O controller has one of these objects + */ +struct i2o_controller { + char name[16]; + int unit; + int type; + + struct pci_dev *pdev; /* PCI device */ + + unsigned int promise:1; /* Promise controller */ + unsigned int adaptec:1; /* DPT / Adaptec controller */ + unsigned int raptor:1; /* split bar */ + unsigned int no_quiesce:1; /* dont quiesce before reset */ + unsigned int short_req:1; /* use small block sizes */ + unsigned int limit_sectors:1; /* limit number of sectors / request */ + unsigned int pae_support:1; /* controller has 64-bit SGL support */ + + struct list_head devices; /* list of I2O devices */ + struct list_head list; /* Controller list */ + + void __iomem *in_port; /* Inbout port address */ + void __iomem *out_port; /* Outbound port address */ + void __iomem *irq_status; /* Interrupt status register address */ + void __iomem *irq_mask; /* Interrupt mask register address */ + + struct i2o_dma status; /* IOP status block */ + + struct i2o_dma hrt; /* HW Resource Table */ + i2o_lct *lct; /* Logical Config Table */ + struct i2o_dma dlct; /* Temp LCT */ + struct mutex lct_lock; /* Lock for LCT updates */ + struct i2o_dma status_block; /* IOP status block */ + + struct i2o_io base; /* controller messaging unit */ + struct i2o_io in_queue; /* inbound message queue Host->IOP */ + struct i2o_dma out_queue; /* outbound message queue IOP->Host */ + + struct i2o_pool in_msg; /* mempool for inbound messages */ + + unsigned int battery:1; /* Has a battery backup */ + unsigned int io_alloc:1; /* An I/O resource was allocated */ + unsigned int mem_alloc:1; /* A memory resource was allocated */ + + struct resource io_resource; /* I/O resource allocated to the IOP */ + struct resource mem_resource; /* Mem resource allocated to the IOP */ + + struct device device; + struct i2o_device *exec; /* Executive */ +#if BITS_PER_LONG == 64 + spinlock_t context_list_lock; /* lock for context_list */ + atomic_t context_list_counter; /* needed for unique contexts */ + struct list_head context_list; /* list of context id's + and pointers */ +#endif + spinlock_t lock; /* lock for controller + configuration */ + void *driver_data[I2O_MAX_DRIVERS]; /* storage for drivers */ +}; + +/* + * I2O System table entry + * + * The system table contains information about all the IOPs in the + * system. It is sent to all IOPs so that they can create peer2peer + * connections between them. + */ +struct i2o_sys_tbl_entry { + u16 org_id; + u16 reserved1; + u32 iop_id:12; + u32 reserved2:20; + u16 seg_num:12; + u16 i2o_version:4; + u8 iop_state; + u8 msg_type; + u16 frame_size; + u16 reserved3; + u32 last_changed; + u32 iop_capabilities; + u32 inbound_low; + u32 inbound_high; +}; + +struct i2o_sys_tbl { + u8 num_entries; + u8 version; + u16 reserved1; + u32 change_ind; + u32 reserved2; + u32 reserved3; + struct i2o_sys_tbl_entry iops[0]; +}; + +extern struct list_head i2o_controllers; + +/* Message functions */ +extern struct i2o_message *i2o_msg_get_wait(struct i2o_controller *, int); +extern int i2o_msg_post_wait_mem(struct i2o_controller *, struct i2o_message *, + unsigned long, struct i2o_dma *); + +/* IOP functions */ +extern int i2o_status_get(struct i2o_controller *); + +extern int i2o_event_register(struct i2o_device *, struct i2o_driver *, int, + u32); +extern struct i2o_device *i2o_iop_find_device(struct i2o_controller *, u16); +extern struct i2o_controller *i2o_find_iop(int); + +/* Functions needed for handling 64-bit pointers in 32-bit context */ +#if BITS_PER_LONG == 64 +extern u32 i2o_cntxt_list_add(struct i2o_controller *, void *); +extern void *i2o_cntxt_list_get(struct i2o_controller *, u32); +extern u32 i2o_cntxt_list_remove(struct i2o_controller *, void *); +extern u32 i2o_cntxt_list_get_ptr(struct i2o_controller *, void *); + +static inline u32 i2o_ptr_low(void *ptr) +{ + return (u32) (u64) ptr; +}; + +static inline u32 i2o_ptr_high(void *ptr) +{ + return (u32) ((u64) ptr >> 32); +}; + +static inline u32 i2o_dma_low(dma_addr_t dma_addr) +{ + return (u32) (u64) dma_addr; +}; + +static inline u32 i2o_dma_high(dma_addr_t dma_addr) +{ + return (u32) ((u64) dma_addr >> 32); +}; +#else +static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr) +{ + return (u32) ptr; +}; + +static inline void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) +{ + return (void *)context; +}; + +static inline u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr) +{ + return (u32) ptr; +}; + +static inline u32 i2o_cntxt_list_get_ptr(struct i2o_controller *c, void *ptr) +{ + return (u32) ptr; +}; + +static inline u32 i2o_ptr_low(void *ptr) +{ + return (u32) ptr; +}; + +static inline u32 i2o_ptr_high(void *ptr) +{ + return 0; +}; + +static inline u32 i2o_dma_low(dma_addr_t dma_addr) +{ + return (u32) dma_addr; +}; + +static inline u32 i2o_dma_high(dma_addr_t dma_addr) +{ + return 0; +}; +#endif + +extern u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size); +extern dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr, + size_t size, + enum dma_data_direction direction, + u32 ** sg_ptr); +extern int i2o_dma_map_sg(struct i2o_controller *c, + struct scatterlist *sg, int sg_count, + enum dma_data_direction direction, + u32 ** sg_ptr); +extern int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len); +extern void i2o_dma_free(struct device *dev, struct i2o_dma *addr); +extern int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, + size_t len); +extern int i2o_pool_alloc(struct i2o_pool *pool, const char *name, + size_t size, int min_nr); +extern void i2o_pool_free(struct i2o_pool *pool); +/* I2O driver (OSM) functions */ +extern int i2o_driver_register(struct i2o_driver *); +extern void i2o_driver_unregister(struct i2o_driver *); + +/** + * i2o_driver_notify_controller_add - Send notification of added controller + * @drv: I2O driver + * @c: I2O controller + * + * Send notification of added controller to a single registered driver. + */ +static inline void i2o_driver_notify_controller_add(struct i2o_driver *drv, + struct i2o_controller *c) +{ + if (drv->notify_controller_add) + drv->notify_controller_add(c); +}; + +/** + * i2o_driver_notify_controller_remove - Send notification of removed controller + * @drv: I2O driver + * @c: I2O controller + * + * Send notification of removed controller to a single registered driver. + */ +static inline void i2o_driver_notify_controller_remove(struct i2o_driver *drv, + struct i2o_controller *c) +{ + if (drv->notify_controller_remove) + drv->notify_controller_remove(c); +}; + +/** + * i2o_driver_notify_device_add - Send notification of added device + * @drv: I2O driver + * @i2o_dev: the added i2o_device + * + * Send notification of added device to a single registered driver. + */ +static inline void i2o_driver_notify_device_add(struct i2o_driver *drv, + struct i2o_device *i2o_dev) +{ + if (drv->notify_device_add) + drv->notify_device_add(i2o_dev); +}; + +/** + * i2o_driver_notify_device_remove - Send notification of removed device + * @drv: I2O driver + * @i2o_dev: the added i2o_device + * + * Send notification of removed device to a single registered driver. + */ +static inline void i2o_driver_notify_device_remove(struct i2o_driver *drv, + struct i2o_device *i2o_dev) +{ + if (drv->notify_device_remove) + drv->notify_device_remove(i2o_dev); +}; + +extern void i2o_driver_notify_controller_add_all(struct i2o_controller *); +extern void i2o_driver_notify_controller_remove_all(struct i2o_controller *); +extern void i2o_driver_notify_device_add_all(struct i2o_device *); +extern void i2o_driver_notify_device_remove_all(struct i2o_device *); + +/* I2O device functions */ +extern int i2o_device_claim(struct i2o_device *); +extern int i2o_device_claim_release(struct i2o_device *); + +/* Exec OSM functions */ +extern int i2o_exec_lct_get(struct i2o_controller *); + +/* device / driver / kobject conversion functions */ +#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver) +#define to_i2o_device(dev) container_of(dev, struct i2o_device, device) +#define to_i2o_controller(dev) container_of(dev, struct i2o_controller, device) + +/** + * i2o_out_to_virt - Turn an I2O message to a virtual address + * @c: controller + * @m: message engine value + * + * Turn a receive message from an I2O controller bus address into + * a Linux virtual address. The shared page frame is a linear block + * so we simply have to shift the offset. This function does not + * work for sender side messages as they are ioremap objects + * provided by the I2O controller. + */ +static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c, + u32 m) +{ + BUG_ON(m < c->out_queue.phys + || m >= c->out_queue.phys + c->out_queue.len); + + return c->out_queue.virt + (m - c->out_queue.phys); +}; + +/** + * i2o_msg_in_to_virt - Turn an I2O message to a virtual address + * @c: controller + * @m: message engine value + * + * Turn a send message from an I2O controller bus address into + * a Linux virtual address. The shared page frame is a linear block + * so we simply have to shift the offset. This function does not + * work for receive side messages as they are kmalloc objects + * in a different pool. + */ +static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct + i2o_controller *c, + u32 m) +{ + return c->in_queue.virt + m; +}; + +/** + * i2o_msg_get - obtain an I2O message from the IOP + * @c: I2O controller + * + * This function tries to get a message frame. If no message frame is + * available do not wait until one is available (see also i2o_msg_get_wait). + * The returned pointer to the message frame is not in I/O memory, it is + * allocated from a mempool. But because a MFA is allocated from the + * controller too it is guaranteed that i2o_msg_post() will never fail. + * + * On a success a pointer to the message frame is returned. If the message + * queue is empty -EBUSY is returned and if no memory is available -ENOMEM + * is returned. + */ +static inline struct i2o_message *i2o_msg_get(struct i2o_controller *c) +{ + struct i2o_msg_mfa *mmsg = mempool_alloc(c->in_msg.mempool, GFP_ATOMIC); + if (!mmsg) + return ERR_PTR(-ENOMEM); + + mmsg->mfa = readl(c->in_port); + if (unlikely(mmsg->mfa >= c->in_queue.len)) { + u32 mfa = mmsg->mfa; + + mempool_free(mmsg, c->in_msg.mempool); + + if (mfa == I2O_QUEUE_EMPTY) + return ERR_PTR(-EBUSY); + return ERR_PTR(-EFAULT); + } + + return &mmsg->msg; +}; + +/** + * i2o_msg_post - Post I2O message to I2O controller + * @c: I2O controller to which the message should be send + * @msg: message returned by i2o_msg_get() + * + * Post the message to the I2O controller and return immediately. + */ +static inline void i2o_msg_post(struct i2o_controller *c, + struct i2o_message *msg) +{ + struct i2o_msg_mfa *mmsg; + + mmsg = container_of(msg, struct i2o_msg_mfa, msg); + memcpy_toio(i2o_msg_in_to_virt(c, mmsg->mfa), msg, + (le32_to_cpu(msg->u.head[0]) >> 16) << 2); + writel(mmsg->mfa, c->in_port); + mempool_free(mmsg, c->in_msg.mempool); +}; + +/** + * i2o_msg_post_wait - Post and wait a message and wait until return + * @c: controller + * @msg: message to post + * @timeout: time in seconds to wait + * + * This API allows an OSM to post a message and then be told whether or + * not the system received a successful reply. If the message times out + * then the value '-ETIMEDOUT' is returned. + * + * Returns 0 on success or negative error code on failure. + */ +static inline int i2o_msg_post_wait(struct i2o_controller *c, + struct i2o_message *msg, + unsigned long timeout) +{ + return i2o_msg_post_wait_mem(c, msg, timeout, NULL); +}; + +/** + * i2o_msg_nop_mfa - Returns a fetched MFA back to the controller + * @c: I2O controller from which the MFA was fetched + * @mfa: MFA which should be returned + * + * This function must be used for preserved messages, because i2o_msg_nop() + * also returns the allocated memory back to the msg_pool mempool. + */ +static inline void i2o_msg_nop_mfa(struct i2o_controller *c, u32 mfa) +{ + struct i2o_message __iomem *msg; + u32 nop[3] = { + THREE_WORD_MSG_SIZE | SGL_OFFSET_0, + I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, + 0x00000000 + }; + + msg = i2o_msg_in_to_virt(c, mfa); + memcpy_toio(msg, nop, sizeof(nop)); + writel(mfa, c->in_port); +}; + +/** + * i2o_msg_nop - Returns a message which is not used + * @c: I2O controller from which the message was created + * @msg: message which should be returned + * + * If you fetch a message via i2o_msg_get, and can't use it, you must + * return the message with this function. Otherwise the MFA is lost as well + * as the allocated memory from the mempool. + */ +static inline void i2o_msg_nop(struct i2o_controller *c, + struct i2o_message *msg) +{ + struct i2o_msg_mfa *mmsg; + mmsg = container_of(msg, struct i2o_msg_mfa, msg); + + i2o_msg_nop_mfa(c, mmsg->mfa); + mempool_free(mmsg, c->in_msg.mempool); +}; + +/** + * i2o_flush_reply - Flush reply from I2O controller + * @c: I2O controller + * @m: the message identifier + * + * The I2O controller must be informed that the reply message is not needed + * anymore. If you forget to flush the reply, the message frame can't be + * used by the controller anymore and is therefore lost. + */ +static inline void i2o_flush_reply(struct i2o_controller *c, u32 m) +{ + writel(m, c->out_port); +}; + +/* + * Endian handling wrapped into the macro - keeps the core code + * cleaner. + */ + +#define i2o_raw_writel(val, mem) __raw_writel(cpu_to_le32(val), mem) + +extern int i2o_parm_field_get(struct i2o_device *, int, int, void *, int); +extern int i2o_parm_table_get(struct i2o_device *, int, int, int, void *, int, + void *, int); + +/* debugging and troubleshooting/diagnostic helpers. */ +#define osm_printk(level, format, arg...) \ + printk(level "%s: " format, OSM_NAME , ## arg) + +#ifdef DEBUG +#define osm_debug(format, arg...) \ + osm_printk(KERN_DEBUG, format , ## arg) +#else +#define osm_debug(format, arg...) \ + do { } while (0) +#endif + +#define osm_err(format, arg...) \ + osm_printk(KERN_ERR, format , ## arg) +#define osm_info(format, arg...) \ + osm_printk(KERN_INFO, format , ## arg) +#define osm_warn(format, arg...) \ + osm_printk(KERN_WARNING, format , ## arg) + +/* debugging functions */ +extern void i2o_report_status(const char *, const char *, struct i2o_message *); +extern void i2o_dump_message(struct i2o_message *); +extern void i2o_dump_hrt(struct i2o_controller *c); +extern void i2o_debug_state(struct i2o_controller *c); + +#endif /* _I2O_H */ diff --git a/drivers/staging/i2o/i2o_block.c b/drivers/staging/i2o/i2o_block.c new file mode 100644 index 0000000..0a13c64 --- /dev/null +++ b/drivers/staging/i2o/i2o_block.c @@ -0,0 +1,1228 @@ +/* + * Block OSM + * + * Copyright (C) 1999-2002 Red Hat Software + * + * Written by Alan Cox, Building Number Three Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * For the purpose of avoiding doubt the preferred form of the work + * for making modifications shall be a standards compliant form such + * gzipped tar and not one requiring a proprietary or patent encumbered + * tool to unpack. + * + * Fixes/additions: + * Steve Ralston: + * Multiple device handling error fixes, + * Added a queue depth. + * Alan Cox: + * FC920 has an rmw bug. Dont or in the end marker. + * Removed queue walk, fixed for 64bitness. + * Rewrote much of the code over time + * Added indirect block lists + * Handle 64K limits on many controllers + * Don't use indirects on the Promise (breaks) + * Heavily chop down the queue depths + * Deepak Saxena: + * Independent queues per IOP + * Support for dynamic device creation/deletion + * Code cleanup + * Support for larger I/Os through merge* functions + * (taken from DAC960 driver) + * Boji T Kannanthanam: + * Set the I2O Block devices to be detected in increasing + * order of TIDs during boot. + * Search and set the I2O block device that we boot off + * from as the first device to be claimed (as /dev/i2o/hda) + * Properly attach/detach I2O gendisk structure from the + * system gendisk list. The I2O block devices now appear in + * /proc/partitions. + * Markus Lidel : + * Minor bugfixes for 2.6. + */ + +#include +#include +#include "i2o.h" +#include + +#include + +#include +#include +#include + +#include + +#include "i2o_block.h" + +#define OSM_NAME "block-osm" +#define OSM_VERSION "1.325" +#define OSM_DESCRIPTION "I2O Block Device OSM" + +static DEFINE_MUTEX(i2o_block_mutex); +static struct i2o_driver i2o_block_driver; + +/* global Block OSM request mempool */ +static struct i2o_block_mempool i2o_blk_req_pool; + +/* Block OSM class handling definition */ +static struct i2o_class_id i2o_block_class_id[] = { + {I2O_CLASS_RANDOM_BLOCK_STORAGE}, + {I2O_CLASS_END} +}; + +/** + * i2o_block_device_free - free the memory of the I2O Block device + * @dev: I2O Block device, which should be cleaned up + * + * Frees the request queue, gendisk and the i2o_block_device structure. + */ +static void i2o_block_device_free(struct i2o_block_device *dev) +{ + blk_cleanup_queue(dev->gd->queue); + + put_disk(dev->gd); + + kfree(dev); +}; + +/** + * i2o_block_remove - remove the I2O Block device from the system again + * @dev: I2O Block device which should be removed + * + * Remove gendisk from system and free all allocated memory. + * + * Always returns 0. + */ +static int i2o_block_remove(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev); + + osm_info("device removed (TID: %03x): %s\n", i2o_dev->lct_data.tid, + i2o_blk_dev->gd->disk_name); + + i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0); + + del_gendisk(i2o_blk_dev->gd); + + dev_set_drvdata(dev, NULL); + + i2o_device_claim_release(i2o_dev); + + i2o_block_device_free(i2o_blk_dev); + + return 0; +}; + +/** + * i2o_block_device flush - Flush all dirty data of I2O device dev + * @dev: I2O device which should be flushed + * + * Flushes all dirty data on device dev. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_device_flush(struct i2o_device *dev) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(60 << 16); + osm_debug("Flushing...\n"); + + return i2o_msg_post_wait(dev->iop, msg, 60); +}; + +/** + * i2o_block_device_mount - Mount (load) the media of device dev + * @dev: I2O device which should receive the mount request + * @media_id: Media Identifier + * + * Load a media into drive. Identifier should be set to -1, because the + * spec does not support any other value. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(-1); + msg->body[1] = cpu_to_le32(0x00000000); + osm_debug("Mounting...\n"); + + return i2o_msg_post_wait(dev->iop, msg, 2); +}; + +/** + * i2o_block_device_lock - Locks the media of device dev + * @dev: I2O device which should receive the lock request + * @media_id: Media Identifier + * + * Lock media of device dev to prevent removal. The media identifier + * should be set to -1, because the spec does not support any other value. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(-1); + osm_debug("Locking...\n"); + + return i2o_msg_post_wait(dev->iop, msg, 2); +}; + +/** + * i2o_block_device_unlock - Unlocks the media of device dev + * @dev: I2O device which should receive the unlocked request + * @media_id: Media Identifier + * + * Unlocks the media in device dev. The media identifier should be set to + * -1, because the spec does not support any other value. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id) +{ + struct i2o_message *msg; + + msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(media_id); + osm_debug("Unlocking...\n"); + + return i2o_msg_post_wait(dev->iop, msg, 2); +}; + +/** + * i2o_block_device_power - Power management for device dev + * @dev: I2O device which should receive the power management request + * @op: Operation to send + * + * Send a power management request to the device dev. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_device_power(struct i2o_block_device *dev, u8 op) +{ + struct i2o_device *i2o_dev = dev->i2o_dev; + struct i2o_controller *c = i2o_dev->iop; + struct i2o_message *msg; + int rc; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev-> + lct_data.tid); + msg->body[0] = cpu_to_le32(op << 24); + osm_debug("Power...\n"); + + rc = i2o_msg_post_wait(c, msg, 60); + if (!rc) + dev->power = op; + + return rc; +}; + +/** + * i2o_block_request_alloc - Allocate an I2O block request struct + * + * Allocates an I2O block request struct and initialize the list. + * + * Returns a i2o_block_request pointer on success or negative error code + * on failure. + */ +static inline struct i2o_block_request *i2o_block_request_alloc(void) +{ + struct i2o_block_request *ireq; + + ireq = mempool_alloc(i2o_blk_req_pool.pool, GFP_ATOMIC); + if (!ireq) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&ireq->queue); + sg_init_table(ireq->sg_table, I2O_MAX_PHYS_SEGMENTS); + + return ireq; +}; + +/** + * i2o_block_request_free - Frees a I2O block request + * @ireq: I2O block request which should be freed + * + * Frees the allocated memory (give it back to the request mempool). + */ +static inline void i2o_block_request_free(struct i2o_block_request *ireq) +{ + mempool_free(ireq, i2o_blk_req_pool.pool); +}; + +/** + * i2o_block_sglist_alloc - Allocate the SG list and map it + * @c: I2O controller to which the request belongs + * @ireq: I2O block request + * @mptr: message body pointer + * + * Builds the SG list and map it to be accessible by the controller. + * + * Returns 0 on failure or 1 on success. + */ +static inline int i2o_block_sglist_alloc(struct i2o_controller *c, + struct i2o_block_request *ireq, + u32 ** mptr) +{ + int nents; + enum dma_data_direction direction; + + ireq->dev = &c->pdev->dev; + nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table); + + if (rq_data_dir(ireq->req) == READ) + direction = PCI_DMA_FROMDEVICE; + else + direction = PCI_DMA_TODEVICE; + + ireq->sg_nents = nents; + + return i2o_dma_map_sg(c, ireq->sg_table, nents, direction, mptr); +}; + +/** + * i2o_block_sglist_free - Frees the SG list + * @ireq: I2O block request from which the SG should be freed + * + * Frees the SG list from the I2O block request. + */ +static inline void i2o_block_sglist_free(struct i2o_block_request *ireq) +{ + enum dma_data_direction direction; + + if (rq_data_dir(ireq->req) == READ) + direction = PCI_DMA_FROMDEVICE; + else + direction = PCI_DMA_TODEVICE; + + dma_unmap_sg(ireq->dev, ireq->sg_table, ireq->sg_nents, direction); +}; + +/** + * i2o_block_prep_req_fn - Allocates I2O block device specific struct + * @q: request queue for the request + * @req: the request to prepare + * + * Allocate the necessary i2o_block_request struct and connect it to + * the request. This is needed that we not lose the SG list later on. + * + * Returns BLKPREP_OK on success or BLKPREP_DEFER on failure. + */ +static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) +{ + struct i2o_block_device *i2o_blk_dev = q->queuedata; + struct i2o_block_request *ireq; + + if (unlikely(!i2o_blk_dev)) { + osm_err("block device already removed\n"); + return BLKPREP_KILL; + } + + /* connect the i2o_block_request to the request */ + if (!req->special) { + ireq = i2o_block_request_alloc(); + if (IS_ERR(ireq)) { + osm_debug("unable to allocate i2o_block_request!\n"); + return BLKPREP_DEFER; + } + + ireq->i2o_blk_dev = i2o_blk_dev; + req->special = ireq; + ireq->req = req; + } + /* do not come back here */ + req->cmd_flags |= REQ_DONTPREP; + + return BLKPREP_OK; +}; + +/** + * i2o_block_delayed_request_fn - delayed request queue function + * @work: the delayed request with the queue to start + * + * If the request queue is stopped for a disk, and there is no open + * request, a new event is created, which calls this function to start + * the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never + * be started again. + */ +static void i2o_block_delayed_request_fn(struct work_struct *work) +{ + struct i2o_block_delayed_request *dreq = + container_of(work, struct i2o_block_delayed_request, + work.work); + struct request_queue *q = dreq->queue; + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + blk_start_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + kfree(dreq); +}; + +/** + * i2o_block_end_request - Post-processing of completed commands + * @req: request which should be completed + * @error: 0 for success, < 0 for error + * @nr_bytes: number of bytes to complete + * + * Mark the request as complete. The lock must not be held when entering. + * + */ +static void i2o_block_end_request(struct request *req, int error, + int nr_bytes) +{ + struct i2o_block_request *ireq = req->special; + struct i2o_block_device *dev = ireq->i2o_blk_dev; + struct request_queue *q = req->q; + unsigned long flags; + + if (blk_end_request(req, error, nr_bytes)) + if (error) + blk_end_request_all(req, -EIO); + + spin_lock_irqsave(q->queue_lock, flags); + + if (likely(dev)) { + dev->open_queue_depth--; + list_del(&ireq->queue); + } + + blk_start_queue(q); + + spin_unlock_irqrestore(q->queue_lock, flags); + + i2o_block_sglist_free(ireq); + i2o_block_request_free(ireq); +}; + +/** + * i2o_block_reply - Block OSM reply handler. + * @c: I2O controller from which the message arrives + * @m: message id of reply + * @msg: the actual I2O message reply + * + * This function gets all the message replies. + * + */ +static int i2o_block_reply(struct i2o_controller *c, u32 m, + struct i2o_message *msg) +{ + struct request *req; + int error = 0; + + req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); + if (unlikely(!req)) { + osm_err("NULL reply received!\n"); + return -1; + } + + /* + * Lets see what is cooking. We stuffed the + * request in the context. + */ + + if ((le32_to_cpu(msg->body[0]) >> 24) != 0) { + u32 status = le32_to_cpu(msg->body[0]); + /* + * Device not ready means two things. One is that the + * the thing went offline (but not a removal media) + * + * The second is that you have a SuperTrak 100 and the + * firmware got constipated. Unlike standard i2o card + * setups the supertrak returns an error rather than + * blocking for the timeout in these cases. + * + * Don't stick a supertrak100 into cache aggressive modes + */ + + osm_err("TID %03x error status: 0x%02x, detailed status: " + "0x%04x\n", (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff), + status >> 24, status & 0xffff); + + req->errors++; + + error = -EIO; + } + + i2o_block_end_request(req, error, le32_to_cpu(msg->body[1])); + + return 1; +}; + +static void i2o_block_event(struct work_struct *work) +{ + struct i2o_event *evt = container_of(work, struct i2o_event, work); + osm_debug("event received\n"); + kfree(evt); +}; + +/* + * SCSI-CAM for ioctl geometry mapping + * Duplicated with SCSI - this should be moved into somewhere common + * perhaps genhd ? + * + * LBA -> CHS mapping table taken from: + * + * "Incorporating the I2O Architecture into BIOS for Intel Architecture + * Platforms" + * + * This is an I2O document that is only available to I2O members, + * not developers. + * + * From my understanding, this is how all the I2O cards do this + * + * Disk Size | Sectors | Heads | Cylinders + * ---------------+---------+-------+------------------- + * 1 < X <= 528M | 63 | 16 | X/(63 * 16 * 512) + * 528M < X <= 1G | 63 | 32 | X/(63 * 32 * 512) + * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512) + * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512) + * + */ +#define BLOCK_SIZE_528M 1081344 +#define BLOCK_SIZE_1G 2097152 +#define BLOCK_SIZE_21G 4403200 +#define BLOCK_SIZE_42G 8806400 +#define BLOCK_SIZE_84G 17612800 + +static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls, + unsigned char *hds, unsigned char *secs) +{ + unsigned long heads, sectors, cylinders; + + sectors = 63L; /* Maximize sectors per track */ + if (capacity <= BLOCK_SIZE_528M) + heads = 16; + else if (capacity <= BLOCK_SIZE_1G) + heads = 32; + else if (capacity <= BLOCK_SIZE_21G) + heads = 64; + else if (capacity <= BLOCK_SIZE_42G) + heads = 128; + else + heads = 255; + + cylinders = (unsigned long)capacity / (heads * sectors); + + *cyls = (unsigned short)cylinders; /* Stuff return values */ + *secs = (unsigned char)sectors; + *hds = (unsigned char)heads; +} + +/** + * i2o_block_open - Open the block device + * @bdev: block device being opened + * @mode: file open mode + * + * Power up the device, mount and lock the media. This function is called, + * if the block device is opened for access. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_open(struct block_device *bdev, fmode_t mode) +{ + struct i2o_block_device *dev = bdev->bd_disk->private_data; + + if (!dev->i2o_dev) + return -ENODEV; + + mutex_lock(&i2o_block_mutex); + if (dev->power > 0x1f) + i2o_block_device_power(dev, 0x02); + + i2o_block_device_mount(dev->i2o_dev, -1); + + i2o_block_device_lock(dev->i2o_dev, -1); + + osm_debug("Ready.\n"); + mutex_unlock(&i2o_block_mutex); + + return 0; +}; + +/** + * i2o_block_release - Release the I2O block device + * @disk: gendisk device being released + * @mode: file open mode + * + * Unlock and unmount the media, and power down the device. Gets called if + * the block device is closed. + */ +static void i2o_block_release(struct gendisk *disk, fmode_t mode) +{ + struct i2o_block_device *dev = disk->private_data; + u8 operation; + + /* + * This is to deal with the case of an application + * opening a device and then the device disappears while + * it's in use, and then the application tries to release + * it. ex: Unmounting a deleted RAID volume at reboot. + * If we send messages, it will just cause FAILs since + * the TID no longer exists. + */ + if (!dev->i2o_dev) + return; + + mutex_lock(&i2o_block_mutex); + i2o_block_device_flush(dev->i2o_dev); + + i2o_block_device_unlock(dev->i2o_dev, -1); + + if (dev->flags & (1 << 3 | 1 << 4)) /* Removable */ + operation = 0x21; + else + operation = 0x24; + + i2o_block_device_power(dev, operation); + mutex_unlock(&i2o_block_mutex); +} + +static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo) +{ + i2o_block_biosparam(get_capacity(bdev->bd_disk), + &geo->cylinders, &geo->heads, &geo->sectors); + return 0; +} + +/** + * i2o_block_ioctl - Issue device specific ioctl calls. + * @bdev: block device being opened + * @mode: file open mode + * @cmd: ioctl command + * @arg: arg + * + * Handles ioctl request for the block device. + * + * Return 0 on success or negative error on failure. + */ +static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + struct gendisk *disk = bdev->bd_disk; + struct i2o_block_device *dev = disk->private_data; + int ret = -ENOTTY; + + /* Anyone capable of this syscall can do *real bad* things */ + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + mutex_lock(&i2o_block_mutex); + switch (cmd) { + case BLKI2OGRSTRAT: + ret = put_user(dev->rcache, (int __user *)arg); + break; + case BLKI2OGWSTRAT: + ret = put_user(dev->wcache, (int __user *)arg); + break; + case BLKI2OSRSTRAT: + ret = -EINVAL; + if (arg < 0 || arg > CACHE_SMARTFETCH) + break; + dev->rcache = arg; + ret = 0; + break; + case BLKI2OSWSTRAT: + ret = -EINVAL; + if (arg != 0 + && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK)) + break; + dev->wcache = arg; + ret = 0; + break; + } + mutex_unlock(&i2o_block_mutex); + + return ret; +}; + +/** + * i2o_block_check_events - Have we seen a media change? + * @disk: gendisk which should be verified + * @clearing: events being cleared + * + * Verifies if the media has changed. + * + * Returns 1 if the media was changed or 0 otherwise. + */ +static unsigned int i2o_block_check_events(struct gendisk *disk, + unsigned int clearing) +{ + struct i2o_block_device *p = disk->private_data; + + if (p->media_change_flag) { + p->media_change_flag = 0; + return DISK_EVENT_MEDIA_CHANGE; + } + return 0; +} + +/** + * i2o_block_transfer - Transfer a request to/from the I2O controller + * @req: the request which should be transferred + * + * This function converts the request into a I2O message. The necessary + * DMA buffers are allocated and after everything is setup post the message + * to the I2O controller. No cleanup is done by this function. It is done + * on the interrupt side when the reply arrives. + * + * Return 0 on success or negative error code on failure. + */ +static int i2o_block_transfer(struct request *req) +{ + struct i2o_block_device *dev = req->rq_disk->private_data; + struct i2o_controller *c; + u32 tid; + struct i2o_message *msg; + u32 *mptr; + struct i2o_block_request *ireq = req->special; + u32 tcntxt; + u32 sgl_offset = SGL_OFFSET_8; + u32 ctl_flags = 0x00000000; + int rc; + u32 cmd; + + if (unlikely(!dev->i2o_dev)) { + osm_err("transfer to removed drive\n"); + rc = -ENODEV; + goto exit; + } + + tid = dev->i2o_dev->lct_data.tid; + c = dev->i2o_dev->iop; + + msg = i2o_msg_get(c); + if (IS_ERR(msg)) { + rc = PTR_ERR(msg); + goto exit; + } + + tcntxt = i2o_cntxt_list_add(c, req); + if (!tcntxt) { + rc = -ENOMEM; + goto nop_msg; + } + + msg->u.s.icntxt = cpu_to_le32(i2o_block_driver.context); + msg->u.s.tcntxt = cpu_to_le32(tcntxt); + + mptr = &msg->body[0]; + + if (rq_data_dir(req) == READ) { + cmd = I2O_CMD_BLOCK_READ << 24; + + switch (dev->rcache) { + case CACHE_PREFETCH: + ctl_flags = 0x201F0008; + break; + + case CACHE_SMARTFETCH: + if (blk_rq_sectors(req) > 16) + ctl_flags = 0x201F0008; + else + ctl_flags = 0x001F0000; + break; + + default: + break; + } + } else { + cmd = I2O_CMD_BLOCK_WRITE << 24; + + switch (dev->wcache) { + case CACHE_WRITETHROUGH: + ctl_flags = 0x001F0008; + break; + case CACHE_WRITEBACK: + ctl_flags = 0x001F0010; + break; + case CACHE_SMARTBACK: + if (blk_rq_sectors(req) > 16) + ctl_flags = 0x001F0004; + else + ctl_flags = 0x001F0010; + break; + case CACHE_SMARTTHROUGH: + if (blk_rq_sectors(req) > 16) + ctl_flags = 0x001F0004; + else + ctl_flags = 0x001F0010; + default: + break; + } + } + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + u8 cmd[10]; + u32 scsi_flags; + u16 hwsec; + + hwsec = queue_logical_block_size(req->q) >> KERNEL_SECTOR_SHIFT; + memset(cmd, 0, 10); + + sgl_offset = SGL_OFFSET_12; + + msg->u.head[1] = + cpu_to_le32(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid); + + *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); + *mptr++ = cpu_to_le32(tid); + + /* + * ENABLE_DISCONNECT + * SIMPLE_TAG + * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME + */ + if (rq_data_dir(req) == READ) { + cmd[0] = READ_10; + scsi_flags = 0x60a0000a; + } else { + cmd[0] = WRITE_10; + scsi_flags = 0xa0a0000a; + } + + *mptr++ = cpu_to_le32(scsi_flags); + + *((u32 *) & cmd[2]) = cpu_to_be32(blk_rq_pos(req) * hwsec); + *((u16 *) & cmd[7]) = cpu_to_be16(blk_rq_sectors(req) * hwsec); + + memcpy(mptr, cmd, 10); + mptr += 4; + *mptr++ = cpu_to_le32(blk_rq_bytes(req)); + } else +#endif + { + msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); + *mptr++ = cpu_to_le32(ctl_flags); + *mptr++ = cpu_to_le32(blk_rq_bytes(req)); + *mptr++ = + cpu_to_le32((u32) (blk_rq_pos(req) << KERNEL_SECTOR_SHIFT)); + *mptr++ = + cpu_to_le32(blk_rq_pos(req) >> (32 - KERNEL_SECTOR_SHIFT)); + } + + if (!i2o_block_sglist_alloc(c, ireq, &mptr)) { + rc = -ENOMEM; + goto context_remove; + } + + msg->u.head[0] = + cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset); + + list_add_tail(&ireq->queue, &dev->open_queue); + dev->open_queue_depth++; + + i2o_msg_post(c, msg); + + return 0; + + context_remove: + i2o_cntxt_list_remove(c, req); + + nop_msg: + i2o_msg_nop(c, msg); + + exit: + return rc; +}; + +/** + * i2o_block_request_fn - request queue handling function + * @q: request queue from which the request could be fetched + * + * Takes the next request from the queue, transfers it and if no error + * occurs dequeue it from the queue. On arrival of the reply the message + * will be processed further. If an error occurs requeue the request. + */ +static void i2o_block_request_fn(struct request_queue *q) +{ + struct request *req; + + while ((req = blk_peek_request(q)) != NULL) { + if (req->cmd_type == REQ_TYPE_FS) { + struct i2o_block_delayed_request *dreq; + struct i2o_block_request *ireq = req->special; + unsigned int queue_depth; + + queue_depth = ireq->i2o_blk_dev->open_queue_depth; + + if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) { + if (!i2o_block_transfer(req)) { + blk_start_request(req); + continue; + } else + osm_info("transfer error\n"); + } + + if (queue_depth) + break; + + /* stop the queue and retry later */ + dreq = kmalloc(sizeof(*dreq), GFP_ATOMIC); + if (!dreq) + continue; + + dreq->queue = q; + INIT_DELAYED_WORK(&dreq->work, + i2o_block_delayed_request_fn); + + if (!queue_delayed_work(i2o_block_driver.event_queue, + &dreq->work, + I2O_BLOCK_RETRY_TIME)) + kfree(dreq); + else { + blk_stop_queue(q); + break; + } + } else { + blk_start_request(req); + __blk_end_request_all(req, -EIO); + } + } +}; + +/* I2O Block device operations definition */ +static const struct block_device_operations i2o_block_fops = { + .owner = THIS_MODULE, + .open = i2o_block_open, + .release = i2o_block_release, + .ioctl = i2o_block_ioctl, + .compat_ioctl = i2o_block_ioctl, + .getgeo = i2o_block_getgeo, + .check_events = i2o_block_check_events, +}; + +/** + * i2o_block_device_alloc - Allocate memory for a I2O Block device + * + * Allocate memory for the i2o_block_device struct, gendisk and request + * queue and initialize them as far as no additional information is needed. + * + * Returns a pointer to the allocated I2O Block device on success or a + * negative error code on failure. + */ +static struct i2o_block_device *i2o_block_device_alloc(void) +{ + struct i2o_block_device *dev; + struct gendisk *gd; + struct request_queue *queue; + int rc; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + osm_err("Insufficient memory to allocate I2O Block disk.\n"); + rc = -ENOMEM; + goto exit; + } + + INIT_LIST_HEAD(&dev->open_queue); + spin_lock_init(&dev->lock); + dev->rcache = CACHE_PREFETCH; + dev->wcache = CACHE_WRITEBACK; + + /* allocate a gendisk with 16 partitions */ + gd = alloc_disk(16); + if (!gd) { + osm_err("Insufficient memory to allocate gendisk.\n"); + rc = -ENOMEM; + goto cleanup_dev; + } + + /* initialize the request queue */ + queue = blk_init_queue(i2o_block_request_fn, &dev->lock); + if (!queue) { + osm_err("Insufficient memory to allocate request queue.\n"); + rc = -ENOMEM; + goto cleanup_queue; + } + + blk_queue_prep_rq(queue, i2o_block_prep_req_fn); + + gd->major = I2O_MAJOR; + gd->queue = queue; + gd->fops = &i2o_block_fops; + gd->private_data = dev; + + dev->gd = gd; + + return dev; + + cleanup_queue: + put_disk(gd); + + cleanup_dev: + kfree(dev); + + exit: + return ERR_PTR(rc); +}; + +/** + * i2o_block_probe - verify if dev is a I2O Block device and install it + * @dev: device to verify if it is a I2O Block device + * + * We only verify if the user_tid of the device is 0xfff and then install + * the device. Otherwise it is used by some other device (e. g. RAID). + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_block_probe(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_controller *c = i2o_dev->iop; + struct i2o_block_device *i2o_blk_dev; + struct gendisk *gd; + struct request_queue *queue; + static int unit = 0; + int rc; + u64 size; + u32 blocksize; + u16 body_size = 4; + u16 power; + unsigned short max_sectors; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) + body_size = 8; +#endif + + if (c->limit_sectors) + max_sectors = I2O_MAX_SECTORS_LIMITED; + else + max_sectors = I2O_MAX_SECTORS; + + /* skip devices which are used by IOP */ + if (i2o_dev->lct_data.user_tid != 0xfff) { + osm_debug("skipping used device %03x\n", i2o_dev->lct_data.tid); + return -ENODEV; + } + + if (i2o_device_claim(i2o_dev)) { + osm_warn("Unable to claim device. Installation aborted\n"); + rc = -EFAULT; + goto exit; + } + + i2o_blk_dev = i2o_block_device_alloc(); + if (IS_ERR(i2o_blk_dev)) { + osm_err("could not alloc a new I2O block device"); + rc = PTR_ERR(i2o_blk_dev); + goto claim_release; + } + + i2o_blk_dev->i2o_dev = i2o_dev; + dev_set_drvdata(dev, i2o_blk_dev); + + /* setup gendisk */ + gd = i2o_blk_dev->gd; + gd->first_minor = unit << 4; + sprintf(gd->disk_name, "i2o/hd%c", 'a' + unit); + gd->driverfs_dev = &i2o_dev->device; + + /* setup request queue */ + queue = gd->queue; + queue->queuedata = i2o_blk_dev; + + blk_queue_max_hw_sectors(queue, max_sectors); + blk_queue_max_segments(queue, i2o_sg_tablesize(c, body_size)); + + osm_debug("max sectors = %d\n", queue->max_sectors); + osm_debug("phys segments = %d\n", queue->max_phys_segments); + osm_debug("max hw segments = %d\n", queue->max_hw_segments); + + /* + * Ask for the current media data. If that isn't supported + * then we ask for the device capacity data + */ + if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || + !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { + blk_queue_logical_block_size(queue, le32_to_cpu(blocksize)); + } else + osm_warn("unable to get blocksize of %s\n", gd->disk_name); + + if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) || + !i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) { + set_capacity(gd, le64_to_cpu(size) >> KERNEL_SECTOR_SHIFT); + } else + osm_warn("could not get size of %s\n", gd->disk_name); + + if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2)) + i2o_blk_dev->power = power; + + i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff); + + add_disk(gd); + + unit++; + + osm_info("device added (TID: %03x): %s\n", i2o_dev->lct_data.tid, + i2o_blk_dev->gd->disk_name); + + return 0; + + claim_release: + i2o_device_claim_release(i2o_dev); + + exit: + return rc; +}; + +/* Block OSM driver struct */ +static struct i2o_driver i2o_block_driver = { + .name = OSM_NAME, + .event = i2o_block_event, + .reply = i2o_block_reply, + .classes = i2o_block_class_id, + .driver = { + .probe = i2o_block_probe, + .remove = i2o_block_remove, + }, +}; + +/** + * i2o_block_init - Block OSM initialization function + * + * Allocate the slab and mempool for request structs, registers i2o_block + * block device and finally register the Block OSM in the I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_block_init(void) +{ + int rc; + int size; + + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + /* Allocate request mempool and slab */ + size = sizeof(struct i2o_block_request); + i2o_blk_req_pool.slab = kmem_cache_create("i2o_block_req", size, 0, + SLAB_HWCACHE_ALIGN, NULL); + if (!i2o_blk_req_pool.slab) { + osm_err("can't init request slab\n"); + rc = -ENOMEM; + goto exit; + } + + i2o_blk_req_pool.pool = + mempool_create_slab_pool(I2O_BLOCK_REQ_MEMPOOL_SIZE, + i2o_blk_req_pool.slab); + if (!i2o_blk_req_pool.pool) { + osm_err("can't init request mempool\n"); + rc = -ENOMEM; + goto free_slab; + } + + /* Register the block device interfaces */ + rc = register_blkdev(I2O_MAJOR, "i2o_block"); + if (rc) { + osm_err("unable to register block device\n"); + goto free_mempool; + } +#ifdef MODULE + osm_info("registered device at major %d\n", I2O_MAJOR); +#endif + + /* Register Block OSM into I2O core */ + rc = i2o_driver_register(&i2o_block_driver); + if (rc) { + osm_err("Could not register Block driver\n"); + goto unregister_blkdev; + } + + return 0; + + unregister_blkdev: + unregister_blkdev(I2O_MAJOR, "i2o_block"); + + free_mempool: + mempool_destroy(i2o_blk_req_pool.pool); + + free_slab: + kmem_cache_destroy(i2o_blk_req_pool.slab); + + exit: + return rc; +}; + +/** + * i2o_block_exit - Block OSM exit function + * + * Unregisters Block OSM from I2O core, unregisters i2o_block block device + * and frees the mempool and slab. + */ +static void __exit i2o_block_exit(void) +{ + /* Unregister I2O Block OSM from I2O core */ + i2o_driver_unregister(&i2o_block_driver); + + /* Unregister block device */ + unregister_blkdev(I2O_MAJOR, "i2o_block"); + + /* Free request mempool and slab */ + mempool_destroy(i2o_blk_req_pool.pool); + kmem_cache_destroy(i2o_blk_req_pool.slab); +}; + +MODULE_AUTHOR("Red Hat"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_block_init); +module_exit(i2o_block_exit); diff --git a/drivers/staging/i2o/i2o_block.h b/drivers/staging/i2o/i2o_block.h new file mode 100644 index 0000000..cf8873c --- /dev/null +++ b/drivers/staging/i2o/i2o_block.h @@ -0,0 +1,103 @@ +/* + * Block OSM structures/API + * + * Copyright (C) 1999-2002 Red Hat Software + * + * Written by Alan Cox, Building Number Three Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * For the purpose of avoiding doubt the preferred form of the work + * for making modifications shall be a standards compliant form such + * gzipped tar and not one requiring a proprietary or patent encumbered + * tool to unpack. + * + * Fixes/additions: + * Steve Ralston: + * Multiple device handling error fixes, + * Added a queue depth. + * Alan Cox: + * FC920 has an rmw bug. Dont or in the end marker. + * Removed queue walk, fixed for 64bitness. + * Rewrote much of the code over time + * Added indirect block lists + * Handle 64K limits on many controllers + * Don't use indirects on the Promise (breaks) + * Heavily chop down the queue depths + * Deepak Saxena: + * Independent queues per IOP + * Support for dynamic device creation/deletion + * Code cleanup + * Support for larger I/Os through merge* functions + * (taken from DAC960 driver) + * Boji T Kannanthanam: + * Set the I2O Block devices to be detected in increasing + * order of TIDs during boot. + * Search and set the I2O block device that we boot off + * from as the first device to be claimed (as /dev/i2o/hda) + * Properly attach/detach I2O gendisk structure from the + * system gendisk list. The I2O block devices now appear in + * /proc/partitions. + * Markus Lidel : + * Minor bugfixes for 2.6. + */ + +#ifndef I2O_BLOCK_OSM_H +#define I2O_BLOCK_OSM_H + +#define I2O_BLOCK_RETRY_TIME HZ/4 +#define I2O_BLOCK_MAX_OPEN_REQUESTS 50 + +/* request queue sizes */ +#define I2O_BLOCK_REQ_MEMPOOL_SIZE 32 + +#define KERNEL_SECTOR_SHIFT 9 +#define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT) + +/* I2O Block OSM mempool struct */ +struct i2o_block_mempool { + struct kmem_cache *slab; + mempool_t *pool; +}; + +/* I2O Block device descriptor */ +struct i2o_block_device { + struct i2o_device *i2o_dev; /* pointer to I2O device */ + struct gendisk *gd; + spinlock_t lock; /* queue lock */ + struct list_head open_queue; /* list of transferred, but unfinished + requests */ + unsigned int open_queue_depth; /* number of requests in the queue */ + + int rcache; /* read cache flags */ + int wcache; /* write cache flags */ + int flags; + u16 power; /* power state */ + int media_change_flag; /* media changed flag */ +}; + +/* I2O Block device request */ +struct i2o_block_request { + struct list_head queue; + struct request *req; /* corresponding request */ + struct i2o_block_device *i2o_blk_dev; /* I2O block device */ + struct device *dev; /* device used for DMA */ + int sg_nents; /* number of SG elements */ + struct scatterlist sg_table[I2O_MAX_PHYS_SEGMENTS]; /* SG table */ +}; + +/* I2O Block device delayed request */ +struct i2o_block_delayed_request { + struct delayed_work work; + struct request_queue *queue; +}; + +#endif diff --git a/drivers/staging/i2o/i2o_config.c b/drivers/staging/i2o/i2o_config.c new file mode 100644 index 0000000..04bd3b6 --- /dev/null +++ b/drivers/staging/i2o/i2o_config.c @@ -0,0 +1,1163 @@ +/* + * I2O Configuration Interface Driver + * + * (C) Copyright 1999-2002 Red Hat + * + * Written by Alan Cox, Building Number Three Ltd + * + * Fixes/additions: + * Deepak Saxena (04/20/1999): + * Added basic ioctl() support + * Deepak Saxena (06/07/1999): + * Added software download ioctl (still testing) + * Auvo Häkkinen (09/10/1999): + * Changes to i2o_cfg_reply(), ioctl_parms() + * Added ioct_validate() + * Taneli Vähäkangas (09/30/1999): + * Fixed ioctl_swdl() + * Taneli Vähäkangas (10/04/1999): + * Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel() + * Deepak Saxena (11/18/1999): + * Added event managmenet support + * Alan Cox : + * 2.4 rewrite ported to 2.5 + * Markus Lidel : + * Added pass-thru support for Adaptec's raidutils + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include + +#include + +#include "core.h" + +#define SG_TABLESIZE 30 + +static DEFINE_MUTEX(i2o_cfg_mutex); +static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long); + +static spinlock_t i2o_config_lock; + +#define MODINC(x,y) ((x) = ((x) + 1) % (y)) + +struct sg_simple_element { + u32 flag_count; + u32 addr_bus; +}; + +struct i2o_cfg_info { + struct file *fp; + struct fasync_struct *fasync; + struct i2o_evt_info event_q[I2O_EVT_Q_LEN]; + u16 q_in; // Queue head index + u16 q_out; // Queue tail index + u16 q_len; // Queue length + u16 q_lost; // Number of lost events + ulong q_id; // Event queue ID...used as tx_context + struct i2o_cfg_info *next; +}; +static struct i2o_cfg_info *open_files = NULL; +static ulong i2o_cfg_info_id = 0; + +static int i2o_cfg_getiops(unsigned long arg) +{ + struct i2o_controller *c; + u8 __user *user_iop_table = (void __user *)arg; + u8 tmp[MAX_I2O_CONTROLLERS]; + int ret = 0; + + memset(tmp, 0, MAX_I2O_CONTROLLERS); + + list_for_each_entry(c, &i2o_controllers, list) + tmp[c->unit] = 1; + + if (copy_to_user(user_iop_table, tmp, MAX_I2O_CONTROLLERS)) + ret = -EFAULT; + + return ret; +}; + +static int i2o_cfg_gethrt(unsigned long arg) +{ + struct i2o_controller *c; + struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg; + struct i2o_cmd_hrtlct kcmd; + i2o_hrt *hrt; + int len; + u32 reslen; + int ret = 0; + + if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct))) + return -EFAULT; + + if (get_user(reslen, kcmd.reslen) < 0) + return -EFAULT; + + if (kcmd.resbuf == NULL) + return -EFAULT; + + c = i2o_find_iop(kcmd.iop); + if (!c) + return -ENXIO; + + hrt = (i2o_hrt *) c->hrt.virt; + + len = 8 + ((hrt->entry_len * hrt->num_entries) << 2); + + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) + ret = -ENOBUFS; + else if (copy_to_user(kcmd.resbuf, (void *)hrt, len)) + ret = -EFAULT; + + return ret; +}; + +static int i2o_cfg_getlct(unsigned long arg) +{ + struct i2o_controller *c; + struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg; + struct i2o_cmd_hrtlct kcmd; + i2o_lct *lct; + int len; + int ret = 0; + u32 reslen; + + if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct))) + return -EFAULT; + + if (get_user(reslen, kcmd.reslen) < 0) + return -EFAULT; + + if (kcmd.resbuf == NULL) + return -EFAULT; + + c = i2o_find_iop(kcmd.iop); + if (!c) + return -ENXIO; + + lct = (i2o_lct *) c->lct; + + len = (unsigned int)lct->table_size << 2; + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) + ret = -ENOBUFS; + else if (copy_to_user(kcmd.resbuf, lct, len)) + ret = -EFAULT; + + return ret; +}; + +static int i2o_cfg_parms(unsigned long arg, unsigned int type) +{ + int ret = 0; + struct i2o_controller *c; + struct i2o_device *dev; + struct i2o_cmd_psetget __user *cmd = + (struct i2o_cmd_psetget __user *)arg; + struct i2o_cmd_psetget kcmd; + u32 reslen; + u8 *ops; + u8 *res; + int len = 0; + + u32 i2o_cmd = (type == I2OPARMGET ? + I2O_CMD_UTIL_PARAMS_GET : I2O_CMD_UTIL_PARAMS_SET); + + if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget))) + return -EFAULT; + + if (get_user(reslen, kcmd.reslen)) + return -EFAULT; + + c = i2o_find_iop(kcmd.iop); + if (!c) + return -ENXIO; + + dev = i2o_iop_find_device(c, kcmd.tid); + if (!dev) + return -ENXIO; + + /* + * Stop users being able to try and allocate arbitrary amounts + * of DMA space. 64K is way more than sufficient for this. + */ + if (kcmd.oplen > 65536) + return -EMSGSIZE; + + ops = memdup_user(kcmd.opbuf, kcmd.oplen); + if (IS_ERR(ops)) + return PTR_ERR(ops); + + /* + * It's possible to have a _very_ large table + * and that the user asks for all of it at once... + */ + res = kmalloc(65536, GFP_KERNEL); + if (!res) { + kfree(ops); + return -ENOMEM; + } + + len = i2o_parm_issue(dev, i2o_cmd, ops, kcmd.oplen, res, 65536); + kfree(ops); + + if (len < 0) { + kfree(res); + return -EAGAIN; + } + + if (put_user(len, kcmd.reslen)) + ret = -EFAULT; + else if (len > reslen) + ret = -ENOBUFS; + else if (copy_to_user(kcmd.resbuf, res, len)) + ret = -EFAULT; + + kfree(res); + + return ret; +}; + +static int i2o_cfg_swdl(unsigned long arg) +{ + struct i2o_sw_xfer kxfer; + struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; + unsigned char maxfrag = 0, curfrag = 1; + struct i2o_dma buffer; + struct i2o_message *msg; + unsigned int status = 0, swlen = 0, fragsize = 8192; + struct i2o_controller *c; + + if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) + return -EFAULT; + + if (get_user(swlen, kxfer.swlen) < 0) + return -EFAULT; + + if (get_user(maxfrag, kxfer.maxfrag) < 0) + return -EFAULT; + + if (get_user(curfrag, kxfer.curfrag) < 0) + return -EFAULT; + + if (curfrag == maxfrag) + fragsize = swlen - (maxfrag - 1) * 8192; + + if (!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize)) + return -EFAULT; + + c = i2o_find_iop(kxfer.iop); + if (!c) + return -ENXIO; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) { + i2o_msg_nop(c, msg); + return -ENOMEM; + } + + if (__copy_from_user(buffer.virt, kxfer.buf, fragsize)) { + i2o_msg_nop(c, msg); + i2o_dma_free(&c->pdev->dev, &buffer); + return -EFAULT; + } + + msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); + msg->body[0] = + cpu_to_le32((((u32) kxfer.flags) << 24) | (((u32) kxfer. + sw_type) << 16) | + (((u32) maxfrag) << 8) | (((u32) curfrag))); + msg->body[1] = cpu_to_le32(swlen); + msg->body[2] = cpu_to_le32(kxfer.sw_id); + msg->body[3] = cpu_to_le32(0xD0000000 | fragsize); + msg->body[4] = cpu_to_le32(buffer.phys); + + osm_debug("swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); + status = i2o_msg_post_wait_mem(c, msg, 60, &buffer); + + if (status != -ETIMEDOUT) + i2o_dma_free(&c->pdev->dev, &buffer); + + if (status != I2O_POST_WAIT_OK) { + // it fails if you try and send frags out of order + // and for some yet unknown reasons too + osm_info("swdl failed, DetailedStatus = %d\n", status); + return status; + } + + return 0; +}; + +static int i2o_cfg_swul(unsigned long arg) +{ + struct i2o_sw_xfer kxfer; + struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; + unsigned char maxfrag = 0, curfrag = 1; + struct i2o_dma buffer; + struct i2o_message *msg; + unsigned int status = 0, swlen = 0, fragsize = 8192; + struct i2o_controller *c; + int ret = 0; + + if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) + return -EFAULT; + + if (get_user(swlen, kxfer.swlen) < 0) + return -EFAULT; + + if (get_user(maxfrag, kxfer.maxfrag) < 0) + return -EFAULT; + + if (get_user(curfrag, kxfer.curfrag) < 0) + return -EFAULT; + + if (curfrag == maxfrag) + fragsize = swlen - (maxfrag - 1) * 8192; + + if (!kxfer.buf) + return -EFAULT; + + c = i2o_find_iop(kxfer.iop); + if (!c) + return -ENXIO; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) { + i2o_msg_nop(c, msg); + return -ENOMEM; + } + + msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); + msg->body[0] = + cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer. + sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag); + msg->body[1] = cpu_to_le32(swlen); + msg->body[2] = cpu_to_le32(kxfer.sw_id); + msg->body[3] = cpu_to_le32(0xD0000000 | fragsize); + msg->body[4] = cpu_to_le32(buffer.phys); + + osm_debug("swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); + status = i2o_msg_post_wait_mem(c, msg, 60, &buffer); + + if (status != I2O_POST_WAIT_OK) { + if (status != -ETIMEDOUT) + i2o_dma_free(&c->pdev->dev, &buffer); + + osm_info("swul failed, DetailedStatus = %d\n", status); + return status; + } + + if (copy_to_user(kxfer.buf, buffer.virt, fragsize)) + ret = -EFAULT; + + i2o_dma_free(&c->pdev->dev, &buffer); + + return ret; +} + +static int i2o_cfg_swdel(unsigned long arg) +{ + struct i2o_controller *c; + struct i2o_sw_xfer kxfer; + struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; + struct i2o_message *msg; + unsigned int swlen; + int token; + + if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) + return -EFAULT; + + if (get_user(swlen, kxfer.swlen) < 0) + return -EFAULT; + + c = i2o_find_iop(kxfer.iop); + if (!c) + return -ENXIO; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); + msg->body[0] = + cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16); + msg->body[1] = cpu_to_le32(swlen); + msg->body[2] = cpu_to_le32(kxfer.sw_id); + + token = i2o_msg_post_wait(c, msg, 10); + + if (token != I2O_POST_WAIT_OK) { + osm_info("swdel failed, DetailedStatus = %d\n", token); + return -ETIMEDOUT; + } + + return 0; +}; + +static int i2o_cfg_validate(unsigned long arg) +{ + int token; + int iop = (int)arg; + struct i2o_message *msg; + struct i2o_controller *c; + + c = i2o_find_iop(iop); + if (!c) + return -ENXIO; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(0); + + token = i2o_msg_post_wait(c, msg, 10); + + if (token != I2O_POST_WAIT_OK) { + osm_info("Can't validate configuration, ErrorStatus = %d\n", + token); + return -ETIMEDOUT; + } + + return 0; +}; + +static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp) +{ + struct i2o_message *msg; + struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg; + struct i2o_evt_id kdesc; + struct i2o_controller *c; + struct i2o_device *d; + + if (copy_from_user(&kdesc, pdesc, sizeof(struct i2o_evt_id))) + return -EFAULT; + + /* IOP exists? */ + c = i2o_find_iop(kdesc.iop); + if (!c) + return -ENXIO; + + /* Device exists? */ + d = i2o_iop_find_device(c, kdesc.tid); + if (!d) + return -ENODEV; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | + kdesc.tid); + msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); + msg->u.head[3] = cpu_to_le32(i2o_cntxt_list_add(c, fp->private_data)); + msg->body[0] = cpu_to_le32(kdesc.evt_mask); + + i2o_msg_post(c, msg); + + return 0; +} + +static int i2o_cfg_evt_get(unsigned long arg, struct file *fp) +{ + struct i2o_cfg_info *p = NULL; + struct i2o_evt_get __user *uget = (struct i2o_evt_get __user *)arg; + struct i2o_evt_get kget; + unsigned long flags; + + for (p = open_files; p; p = p->next) + if (p->q_id == (ulong) fp->private_data) + break; + + if (!p->q_len) + return -ENOENT; + + memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info)); + MODINC(p->q_out, I2O_EVT_Q_LEN); + spin_lock_irqsave(&i2o_config_lock, flags); + p->q_len--; + kget.pending = p->q_len; + kget.lost = p->q_lost; + spin_unlock_irqrestore(&i2o_config_lock, flags); + + if (copy_to_user(uget, &kget, sizeof(struct i2o_evt_get))) + return -EFAULT; + return 0; +} + +#ifdef CONFIG_COMPAT +static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, + unsigned long arg) +{ + struct i2o_cmd_passthru32 __user *cmd; + struct i2o_controller *c; + u32 __user *user_msg; + u32 *reply = NULL; + u32 __user *user_reply = NULL; + u32 size = 0; + u32 reply_size = 0; + u32 rcode = 0; + struct i2o_dma sg_list[SG_TABLESIZE]; + u32 sg_offset = 0; + u32 sg_count = 0; + u32 i = 0; + u32 sg_index = 0; + i2o_status_block *sb; + struct i2o_message *msg; + unsigned int iop; + + cmd = (struct i2o_cmd_passthru32 __user *)arg; + + if (get_user(iop, &cmd->iop) || get_user(i, &cmd->msg)) + return -EFAULT; + + user_msg = compat_ptr(i); + + c = i2o_find_iop(iop); + if (!c) { + osm_debug("controller %d not found\n", iop); + return -ENXIO; + } + + sb = c->status_block.virt; + + if (get_user(size, &user_msg[0])) { + osm_warn("unable to get size!\n"); + return -EFAULT; + } + size = size >> 16; + + if (size > sb->inbound_frame_size) { + osm_warn("size of message > inbound_frame_size"); + return -EFAULT; + } + + user_reply = &user_msg[size]; + + size <<= 2; // Convert to bytes + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + rcode = -EFAULT; + /* Copy in the user's I2O command */ + if (copy_from_user(msg, user_msg, size)) { + osm_warn("unable to copy user message\n"); + goto out; + } + i2o_dump_message(msg); + + if (get_user(reply_size, &user_reply[0]) < 0) + goto out; + + reply_size >>= 16; + reply_size <<= 2; + + rcode = -ENOMEM; + reply = kzalloc(reply_size, GFP_KERNEL); + if (!reply) { + printk(KERN_WARNING "%s: Could not allocate reply buffer\n", + c->name); + goto out; + } + + sg_offset = (msg->u.head[0] >> 4) & 0x0f; + + memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); + if (sg_offset) { + struct sg_simple_element *sg; + + if (sg_offset * 4 >= size) { + rcode = -EFAULT; + goto cleanup; + } + // TODO 64bit fix + sg = (struct sg_simple_element *)((&msg->u.head[0]) + + sg_offset); + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); + if (sg_count > SG_TABLESIZE) { + printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", + c->name, sg_count); + rcode = -EINVAL; + goto cleanup; + } + + for (i = 0; i < sg_count; i++) { + int sg_size; + struct i2o_dma *p; + + if (!(sg[i].flag_count & 0x10000000 + /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) { + printk(KERN_DEBUG + "%s:Bad SG element %d - not simple (%x)\n", + c->name, i, sg[i].flag_count); + rcode = -EINVAL; + goto cleanup; + } + sg_size = sg[i].flag_count & 0xffffff; + p = &(sg_list[sg_index]); + /* Allocate memory for the transfer */ + if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) { + printk(KERN_DEBUG + "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + c->name, sg_size, i, sg_count); + rcode = -ENOMEM; + goto sg_list_cleanup; + } + sg_index++; + /* Copy in the user's SG buffer if necessary */ + if (sg[i]. + flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { + // TODO 64bit fix + if (copy_from_user + (p->virt, + (void __user *)(unsigned long)sg[i]. + addr_bus, sg_size)) { + printk(KERN_DEBUG + "%s: Could not copy SG buf %d FROM user\n", + c->name, i); + rcode = -EFAULT; + goto sg_list_cleanup; + } + } + //TODO 64bit fix + sg[i].addr_bus = (u32) p->phys; + } + } + + rcode = i2o_msg_post_wait(c, msg, 60); + msg = NULL; + if (rcode) { + reply[4] = ((u32) rcode) << 24; + goto sg_list_cleanup; + } + + if (sg_offset) { + u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE]; + /* Copy back the Scatter Gather buffers back to user space */ + u32 j; + // TODO 64bit fix + struct sg_simple_element *sg; + int sg_size; + + // re-acquire the original message to handle correctly the sg copy operation + memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); + // get user msg size in u32s + if (get_user(size, &user_msg[0])) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + size = size >> 16; + size *= 4; + if (size > sizeof(rmsg)) { + rcode = -EINVAL; + goto sg_list_cleanup; + } + + /* Copy in the user's I2O command */ + if (copy_from_user(rmsg, user_msg, size)) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); + + // TODO 64bit fix + sg = (struct sg_simple_element *)(rmsg + sg_offset); + for (j = 0; j < sg_count; j++) { + /* Copy out the SG list to user's buffer if necessary */ + if (! + (sg[j]. + flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) { + sg_size = sg[j].flag_count & 0xffffff; + // TODO 64bit fix + if (copy_to_user + ((void __user *)(u64) sg[j].addr_bus, + sg_list[j].virt, sg_size)) { + printk(KERN_WARNING + "%s: Could not copy %p TO user %x\n", + c->name, sg_list[j].virt, + sg[j].addr_bus); + rcode = -EFAULT; + goto sg_list_cleanup; + } + } + } + } + +sg_list_cleanup: + /* Copy back the reply to user space */ + if (reply_size) { + // we wrote our own values for context - now restore the user supplied ones + if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) { + printk(KERN_WARNING + "%s: Could not copy message context FROM user\n", + c->name); + rcode = -EFAULT; + } + if (copy_to_user(user_reply, reply, reply_size)) { + printk(KERN_WARNING + "%s: Could not copy reply TO user\n", c->name); + rcode = -EFAULT; + } + } + for (i = 0; i < sg_index; i++) + i2o_dma_free(&c->pdev->dev, &sg_list[i]); + +cleanup: + kfree(reply); +out: + if (msg) + i2o_msg_nop(c, msg); + return rcode; +} + +static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, + unsigned long arg) +{ + int ret; + switch (cmd) { + case I2OGETIOPS: + ret = i2o_cfg_ioctl(file, cmd, arg); + break; + case I2OPASSTHRU32: + mutex_lock(&i2o_cfg_mutex); + ret = i2o_cfg_passthru32(file, cmd, arg); + mutex_unlock(&i2o_cfg_mutex); + break; + default: + ret = -ENOIOCTLCMD; + break; + } + return ret; +} + +#endif + +#ifdef CONFIG_I2O_EXT_ADAPTEC +static int i2o_cfg_passthru(unsigned long arg) +{ + struct i2o_cmd_passthru __user *cmd = + (struct i2o_cmd_passthru __user *)arg; + struct i2o_controller *c; + u32 __user *user_msg; + u32 *reply = NULL; + u32 __user *user_reply = NULL; + u32 size = 0; + u32 reply_size = 0; + u32 rcode = 0; + struct i2o_dma sg_list[SG_TABLESIZE]; + u32 sg_offset = 0; + u32 sg_count = 0; + int sg_index = 0; + u32 i = 0; + i2o_status_block *sb; + struct i2o_message *msg; + unsigned int iop; + + if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg)) + return -EFAULT; + + c = i2o_find_iop(iop); + if (!c) { + osm_warn("controller %d not found\n", iop); + return -ENXIO; + } + + sb = c->status_block.virt; + + if (get_user(size, &user_msg[0])) + return -EFAULT; + size = size >> 16; + + if (size > sb->inbound_frame_size) { + osm_warn("size of message > inbound_frame_size"); + return -EFAULT; + } + + user_reply = &user_msg[size]; + + size <<= 2; // Convert to bytes + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + rcode = -EFAULT; + /* Copy in the user's I2O command */ + if (copy_from_user(msg, user_msg, size)) + goto out; + + if (get_user(reply_size, &user_reply[0]) < 0) + goto out; + + reply_size >>= 16; + reply_size <<= 2; + + reply = kzalloc(reply_size, GFP_KERNEL); + if (!reply) { + printk(KERN_WARNING "%s: Could not allocate reply buffer\n", + c->name); + rcode = -ENOMEM; + goto out; + } + + sg_offset = (msg->u.head[0] >> 4) & 0x0f; + + memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); + if (sg_offset) { + struct sg_simple_element *sg; + struct i2o_dma *p; + + if (sg_offset * 4 >= size) { + rcode = -EFAULT; + goto cleanup; + } + // TODO 64bit fix + sg = (struct sg_simple_element *)((&msg->u.head[0]) + + sg_offset); + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); + if (sg_count > SG_TABLESIZE) { + printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", + c->name, sg_count); + rcode = -EINVAL; + goto cleanup; + } + + for (i = 0; i < sg_count; i++) { + int sg_size; + + if (!(sg[i].flag_count & 0x10000000 + /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) { + printk(KERN_DEBUG + "%s:Bad SG element %d - not simple (%x)\n", + c->name, i, sg[i].flag_count); + rcode = -EINVAL; + goto sg_list_cleanup; + } + sg_size = sg[i].flag_count & 0xffffff; + p = &(sg_list[sg_index]); + if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) { + /* Allocate memory for the transfer */ + printk(KERN_DEBUG + "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + c->name, sg_size, i, sg_count); + rcode = -ENOMEM; + goto sg_list_cleanup; + } + sg_index++; + /* Copy in the user's SG buffer if necessary */ + if (sg[i]. + flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { + // TODO 64bit fix + if (copy_from_user + (p->virt, (void __user *)sg[i].addr_bus, + sg_size)) { + printk(KERN_DEBUG + "%s: Could not copy SG buf %d FROM user\n", + c->name, i); + rcode = -EFAULT; + goto sg_list_cleanup; + } + } + sg[i].addr_bus = p->phys; + } + } + + rcode = i2o_msg_post_wait(c, msg, 60); + msg = NULL; + if (rcode) { + reply[4] = ((u32) rcode) << 24; + goto sg_list_cleanup; + } + + if (sg_offset) { + u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE]; + /* Copy back the Scatter Gather buffers back to user space */ + u32 j; + // TODO 64bit fix + struct sg_simple_element *sg; + int sg_size; + + // re-acquire the original message to handle correctly the sg copy operation + memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4); + // get user msg size in u32s + if (get_user(size, &user_msg[0])) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + size = size >> 16; + size *= 4; + if (size > sizeof(rmsg)) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + + /* Copy in the user's I2O command */ + if (copy_from_user(rmsg, user_msg, size)) { + rcode = -EFAULT; + goto sg_list_cleanup; + } + sg_count = + (size - sg_offset * 4) / sizeof(struct sg_simple_element); + + // TODO 64bit fix + sg = (struct sg_simple_element *)(rmsg + sg_offset); + for (j = 0; j < sg_count; j++) { + /* Copy out the SG list to user's buffer if necessary */ + if (! + (sg[j]. + flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) { + sg_size = sg[j].flag_count & 0xffffff; + // TODO 64bit fix + if (copy_to_user + ((void __user *)sg[j].addr_bus, sg_list[j].virt, + sg_size)) { + printk(KERN_WARNING + "%s: Could not copy %p TO user %x\n", + c->name, sg_list[j].virt, + sg[j].addr_bus); + rcode = -EFAULT; + goto sg_list_cleanup; + } + } + } + } + +sg_list_cleanup: + /* Copy back the reply to user space */ + if (reply_size) { + // we wrote our own values for context - now restore the user supplied ones + if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) { + printk(KERN_WARNING + "%s: Could not copy message context FROM user\n", + c->name); + rcode = -EFAULT; + } + if (copy_to_user(user_reply, reply, reply_size)) { + printk(KERN_WARNING + "%s: Could not copy reply TO user\n", c->name); + rcode = -EFAULT; + } + } + + for (i = 0; i < sg_index; i++) + i2o_dma_free(&c->pdev->dev, &sg_list[i]); + +cleanup: + kfree(reply); +out: + if (msg) + i2o_msg_nop(c, msg); + return rcode; +} +#endif + +/* + * IOCTL Handler + */ +static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) +{ + int ret; + + mutex_lock(&i2o_cfg_mutex); + switch (cmd) { + case I2OGETIOPS: + ret = i2o_cfg_getiops(arg); + break; + + case I2OHRTGET: + ret = i2o_cfg_gethrt(arg); + break; + + case I2OLCTGET: + ret = i2o_cfg_getlct(arg); + break; + + case I2OPARMSET: + ret = i2o_cfg_parms(arg, I2OPARMSET); + break; + + case I2OPARMGET: + ret = i2o_cfg_parms(arg, I2OPARMGET); + break; + + case I2OSWDL: + ret = i2o_cfg_swdl(arg); + break; + + case I2OSWUL: + ret = i2o_cfg_swul(arg); + break; + + case I2OSWDEL: + ret = i2o_cfg_swdel(arg); + break; + + case I2OVALIDATE: + ret = i2o_cfg_validate(arg); + break; + + case I2OEVTREG: + ret = i2o_cfg_evt_reg(arg, fp); + break; + + case I2OEVTGET: + ret = i2o_cfg_evt_get(arg, fp); + break; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + case I2OPASSTHRU: + ret = i2o_cfg_passthru(arg); + break; +#endif + + default: + osm_debug("unknown ioctl called!\n"); + ret = -EINVAL; + } + mutex_unlock(&i2o_cfg_mutex); + return ret; +} + +static int cfg_open(struct inode *inode, struct file *file) +{ + struct i2o_cfg_info *tmp = kmalloc(sizeof(struct i2o_cfg_info), + GFP_KERNEL); + unsigned long flags; + + if (!tmp) + return -ENOMEM; + + mutex_lock(&i2o_cfg_mutex); + file->private_data = (void *)(i2o_cfg_info_id++); + tmp->fp = file; + tmp->fasync = NULL; + tmp->q_id = (ulong) file->private_data; + tmp->q_len = 0; + tmp->q_in = 0; + tmp->q_out = 0; + tmp->q_lost = 0; + tmp->next = open_files; + + spin_lock_irqsave(&i2o_config_lock, flags); + open_files = tmp; + spin_unlock_irqrestore(&i2o_config_lock, flags); + mutex_unlock(&i2o_cfg_mutex); + + return 0; +} + +static int cfg_fasync(int fd, struct file *fp, int on) +{ + ulong id = (ulong) fp->private_data; + struct i2o_cfg_info *p; + int ret = -EBADF; + + mutex_lock(&i2o_cfg_mutex); + for (p = open_files; p; p = p->next) + if (p->q_id == id) + break; + + if (p) + ret = fasync_helper(fd, fp, on, &p->fasync); + mutex_unlock(&i2o_cfg_mutex); + return ret; +} + +static int cfg_release(struct inode *inode, struct file *file) +{ + ulong id = (ulong) file->private_data; + struct i2o_cfg_info *p, **q; + unsigned long flags; + + mutex_lock(&i2o_cfg_mutex); + spin_lock_irqsave(&i2o_config_lock, flags); + for (q = &open_files; (p = *q) != NULL; q = &p->next) { + if (p->q_id == id) { + *q = p->next; + kfree(p); + break; + } + } + spin_unlock_irqrestore(&i2o_config_lock, flags); + mutex_unlock(&i2o_cfg_mutex); + + return 0; +} + +static const struct file_operations config_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .unlocked_ioctl = i2o_cfg_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = i2o_cfg_compat_ioctl, +#endif + .open = cfg_open, + .release = cfg_release, + .fasync = cfg_fasync, +}; + +static struct miscdevice i2o_miscdev = { + I2O_MINOR, + "i2octl", + &config_fops +}; + +static int __init i2o_config_old_init(void) +{ + spin_lock_init(&i2o_config_lock); + + if (misc_register(&i2o_miscdev) < 0) { + osm_err("can't register device.\n"); + return -EBUSY; + } + + return 0; +} + +static void i2o_config_old_exit(void) +{ + misc_deregister(&i2o_miscdev); +} + +MODULE_AUTHOR("Red Hat Software"); diff --git a/drivers/staging/i2o/i2o_proc.c b/drivers/staging/i2o/i2o_proc.c new file mode 100644 index 0000000..ad84f33 --- /dev/null +++ b/drivers/staging/i2o/i2o_proc.c @@ -0,0 +1,2045 @@ +/* + * procfs handler for Linux I2O subsystem + * + * (c) Copyright 1999 Deepak Saxena + * + * Originally written by Deepak Saxena(deepak@plexity.net) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This is an initial test release. The code is based on the design of the + * ide procfs system (drivers/block/ide-proc.c). Some code taken from + * i2o-core module by Alan Cox. + * + * DISCLAIMER: This code is still under development/test and may cause + * your system to behave unpredictably. Use at your own discretion. + * + * + * Fixes/additions: + * Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI), + * Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI) + * University of Helsinki, Department of Computer Science + * LAN entries + * Markus Lidel + * Changes for new I2O API + */ + +#define OSM_NAME "proc-osm" +#define OSM_VERSION "1.316" +#define OSM_DESCRIPTION "I2O ProcFS OSM" + +#define I2O_MAX_MODULES 4 +// FIXME! +#define FMT_U64_HEX "0x%08x%08x" +#define U64_VAL(pu64) *((u32*)(pu64)+1), *((u32*)(pu64)) + +#include +#include +#include +#include "i2o.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Structure used to define /proc entries */ +typedef struct _i2o_proc_entry_t { + char *name; /* entry name */ + umode_t mode; /* mode */ + const struct file_operations *fops; /* open function */ +} i2o_proc_entry; + +/* global I2O /proc/i2o entry */ +static struct proc_dir_entry *i2o_proc_dir_root; + +/* proc OSM driver struct */ +static struct i2o_driver i2o_proc_driver = { + .name = OSM_NAME, +}; + +static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len) +{ + int i; + + /* 19990419 -sralston + * The I2O v1.5 (and v2.0 so far) "official specification" + * got serial numbers WRONG! + * Apparently, and despite what Section 3.4.4 says and + * Figure 3-35 shows (pg 3-39 in the pdf doc), + * the convention / consensus seems to be: + * + First byte is SNFormat + * + Second byte is SNLen (but only if SNFormat==7 (?)) + * + (v2.0) SCSI+BS may use IEEE Registered (64 or 128 bit) format + */ + switch (serialno[0]) { + case I2O_SNFORMAT_BINARY: /* Binary */ + seq_printf(seq, "0x"); + for (i = 0; i < serialno[1]; i++) { + seq_printf(seq, "%02X", serialno[2 + i]); + } + break; + + case I2O_SNFORMAT_ASCII: /* ASCII */ + if (serialno[1] < ' ') { /* printable or SNLen? */ + /* sanity */ + max_len = + (max_len < serialno[1]) ? max_len : serialno[1]; + serialno[1 + max_len] = '\0'; + + /* just print it */ + seq_printf(seq, "%s", &serialno[2]); + } else { + /* print chars for specified length */ + for (i = 0; i < serialno[1]; i++) { + seq_printf(seq, "%c", serialno[2 + i]); + } + } + break; + + case I2O_SNFORMAT_UNICODE: /* UNICODE */ + seq_printf(seq, "UNICODE Format. Can't Display\n"); + break; + + case I2O_SNFORMAT_LAN48_MAC: /* LAN-48 MAC Address */ + seq_printf(seq, "LAN-48 MAC address @ %pM", &serialno[2]); + break; + + case I2O_SNFORMAT_WAN: /* WAN MAC Address */ + /* FIXME: Figure out what a WAN access address looks like?? */ + seq_printf(seq, "WAN Access Address"); + break; + +/* plus new in v2.0 */ + case I2O_SNFORMAT_LAN64_MAC: /* LAN-64 MAC Address */ + /* FIXME: Figure out what a LAN-64 address really looks like?? */ + seq_printf(seq, + "LAN-64 MAC address @ [?:%02X:%02X:?] %pM", + serialno[8], serialno[9], &serialno[2]); + break; + + case I2O_SNFORMAT_DDM: /* I2O DDM */ + seq_printf(seq, + "DDM: Tid=%03Xh, Rsvd=%04Xh, OrgId=%04Xh", + *(u16 *) & serialno[2], + *(u16 *) & serialno[4], *(u16 *) & serialno[6]); + break; + + case I2O_SNFORMAT_IEEE_REG64: /* IEEE Registered (64-bit) */ + case I2O_SNFORMAT_IEEE_REG128: /* IEEE Registered (128-bit) */ + /* FIXME: Figure if this is even close?? */ + seq_printf(seq, + "IEEE NodeName(hi,lo)=(%08Xh:%08Xh), PortName(hi,lo)=(%08Xh:%08Xh)\n", + *(u32 *) & serialno[2], + *(u32 *) & serialno[6], + *(u32 *) & serialno[10], *(u32 *) & serialno[14]); + break; + + case I2O_SNFORMAT_UNKNOWN: /* Unknown 0 */ + case I2O_SNFORMAT_UNKNOWN2: /* Unknown 0xff */ + default: + seq_printf(seq, "Unknown data format (0x%02x)", serialno[0]); + break; + } + + return 0; +} + +/** + * i2o_get_class_name - do i2o class name lookup + * @class: class number + * + * Return a descriptive string for an i2o class. + */ +static const char *i2o_get_class_name(int class) +{ + int idx = 16; + static char *i2o_class_name[] = { + "Executive", + "Device Driver Module", + "Block Device", + "Tape Device", + "LAN Interface", + "WAN Interface", + "Fibre Channel Port", + "Fibre Channel Device", + "SCSI Device", + "ATE Port", + "ATE Device", + "Floppy Controller", + "Floppy Device", + "Secondary Bus Port", + "Peer Transport Agent", + "Peer Transport", + "Unknown" + }; + + switch (class & 0xfff) { + case I2O_CLASS_EXECUTIVE: + idx = 0; + break; + case I2O_CLASS_DDM: + idx = 1; + break; + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + idx = 2; + break; + case I2O_CLASS_SEQUENTIAL_STORAGE: + idx = 3; + break; + case I2O_CLASS_LAN: + idx = 4; + break; + case I2O_CLASS_WAN: + idx = 5; + break; + case I2O_CLASS_FIBRE_CHANNEL_PORT: + idx = 6; + break; + case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: + idx = 7; + break; + case I2O_CLASS_SCSI_PERIPHERAL: + idx = 8; + break; + case I2O_CLASS_ATE_PORT: + idx = 9; + break; + case I2O_CLASS_ATE_PERIPHERAL: + idx = 10; + break; + case I2O_CLASS_FLOPPY_CONTROLLER: + idx = 11; + break; + case I2O_CLASS_FLOPPY_DEVICE: + idx = 12; + break; + case I2O_CLASS_BUS_ADAPTER: + idx = 13; + break; + case I2O_CLASS_PEER_TRANSPORT_AGENT: + idx = 14; + break; + case I2O_CLASS_PEER_TRANSPORT: + idx = 15; + break; + } + + return i2o_class_name[idx]; +} + +#define SCSI_TABLE_SIZE 13 +static char *scsi_devices[] = { + "Direct-Access Read/Write", + "Sequential-Access Storage", + "Printer", + "Processor", + "WORM Device", + "CD-ROM Device", + "Scanner Device", + "Optical Memory Device", + "Medium Changer Device", + "Communications Device", + "Graphics Art Pre-Press Device", + "Graphics Art Pre-Press Device", + "Array Controller Device" +}; + +static char *chtostr(char *tmp, u8 *chars, int n) +{ + tmp[0] = 0; + return strncat(tmp, (char *)chars, n); +} + +static int i2o_report_query_status(struct seq_file *seq, int block_status, + char *group) +{ + switch (block_status) { + case -ETIMEDOUT: + return seq_printf(seq, "Timeout reading group %s.\n", group); + case -ENOMEM: + return seq_printf(seq, "No free memory to read the table.\n"); + case -I2O_PARAMS_STATUS_INVALID_GROUP_ID: + return seq_printf(seq, "Group %s not supported.\n", group); + default: + return seq_printf(seq, + "Error reading group %s. BlockStatus 0x%02X\n", + group, -block_status); + } +} + +static char *bus_strings[] = { + "Local Bus", + "ISA", + "EISA", + "PCI", + "PCMCIA", + "NUBUS", + "CARDBUS" +}; + +static int i2o_seq_show_hrt(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + i2o_hrt *hrt = (i2o_hrt *) c->hrt.virt; + u32 bus; + int i; + + if (hrt->hrt_version) { + seq_printf(seq, + "HRT table for controller is too new a version.\n"); + return 0; + } + + seq_printf(seq, "HRT has %d entries of %d bytes each.\n", + hrt->num_entries, hrt->entry_len << 2); + + for (i = 0; i < hrt->num_entries; i++) { + seq_printf(seq, "Entry %d:\n", i); + seq_printf(seq, " Adapter ID: %0#10x\n", + hrt->hrt_entry[i].adapter_id); + seq_printf(seq, " Controlling tid: %0#6x\n", + hrt->hrt_entry[i].parent_tid); + + if (hrt->hrt_entry[i].bus_type != 0x80) { + bus = hrt->hrt_entry[i].bus_type; + seq_printf(seq, " %s Information\n", + bus_strings[bus]); + + switch (bus) { + case I2O_BUS_LOCAL: + seq_printf(seq, " IOBase: %0#6x,", + hrt->hrt_entry[i].bus.local_bus. + LbBaseIOPort); + seq_printf(seq, " MemoryBase: %0#10x\n", + hrt->hrt_entry[i].bus.local_bus. + LbBaseMemoryAddress); + break; + + case I2O_BUS_ISA: + seq_printf(seq, " IOBase: %0#6x,", + hrt->hrt_entry[i].bus.isa_bus. + IsaBaseIOPort); + seq_printf(seq, " MemoryBase: %0#10x,", + hrt->hrt_entry[i].bus.isa_bus. + IsaBaseMemoryAddress); + seq_printf(seq, " CSN: %0#4x,", + hrt->hrt_entry[i].bus.isa_bus.CSN); + break; + + case I2O_BUS_EISA: + seq_printf(seq, " IOBase: %0#6x,", + hrt->hrt_entry[i].bus.eisa_bus. + EisaBaseIOPort); + seq_printf(seq, " MemoryBase: %0#10x,", + hrt->hrt_entry[i].bus.eisa_bus. + EisaBaseMemoryAddress); + seq_printf(seq, " Slot: %0#4x,", + hrt->hrt_entry[i].bus.eisa_bus. + EisaSlotNumber); + break; + + case I2O_BUS_PCI: + seq_printf(seq, " Bus: %0#4x", + hrt->hrt_entry[i].bus.pci_bus. + PciBusNumber); + seq_printf(seq, " Dev: %0#4x", + hrt->hrt_entry[i].bus.pci_bus. + PciDeviceNumber); + seq_printf(seq, " Func: %0#4x", + hrt->hrt_entry[i].bus.pci_bus. + PciFunctionNumber); + seq_printf(seq, " Vendor: %0#6x", + hrt->hrt_entry[i].bus.pci_bus. + PciVendorID); + seq_printf(seq, " Device: %0#6x\n", + hrt->hrt_entry[i].bus.pci_bus. + PciDeviceID); + break; + + default: + seq_printf(seq, " Unsupported Bus Type\n"); + } + } else + seq_printf(seq, " Unknown Bus Type\n"); + } + + return 0; +} + +static int i2o_seq_show_lct(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + i2o_lct *lct = (i2o_lct *) c->lct; + int entries; + int i; + +#define BUS_TABLE_SIZE 3 + static char *bus_ports[] = { + "Generic Bus", + "SCSI Bus", + "Fibre Channel Bus" + }; + + entries = (lct->table_size - 3) / 9; + + seq_printf(seq, "LCT contains %d %s\n", entries, + entries == 1 ? "entry" : "entries"); + if (lct->boot_tid) + seq_printf(seq, "Boot Device @ ID %d\n", lct->boot_tid); + + seq_printf(seq, "Current Change Indicator: %#10x\n", lct->change_ind); + + for (i = 0; i < entries; i++) { + seq_printf(seq, "Entry %d\n", i); + seq_printf(seq, " Class, SubClass : %s", + i2o_get_class_name(lct->lct_entry[i].class_id)); + + /* + * Classes which we'll print subclass info for + */ + switch (lct->lct_entry[i].class_id & 0xFFF) { + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + switch (lct->lct_entry[i].sub_class) { + case 0x00: + seq_printf(seq, ", Direct-Access Read/Write"); + break; + + case 0x04: + seq_printf(seq, ", WORM Drive"); + break; + + case 0x05: + seq_printf(seq, ", CD-ROM Drive"); + break; + + case 0x07: + seq_printf(seq, ", Optical Memory Device"); + break; + + default: + seq_printf(seq, ", Unknown (0x%02x)", + lct->lct_entry[i].sub_class); + break; + } + break; + + case I2O_CLASS_LAN: + switch (lct->lct_entry[i].sub_class & 0xFF) { + case 0x30: + seq_printf(seq, ", Ethernet"); + break; + + case 0x40: + seq_printf(seq, ", 100base VG"); + break; + + case 0x50: + seq_printf(seq, ", IEEE 802.5/Token-Ring"); + break; + + case 0x60: + seq_printf(seq, ", ANSI X3T9.5 FDDI"); + break; + + case 0x70: + seq_printf(seq, ", Fibre Channel"); + break; + + default: + seq_printf(seq, ", Unknown Sub-Class (0x%02x)", + lct->lct_entry[i].sub_class & 0xFF); + break; + } + break; + + case I2O_CLASS_SCSI_PERIPHERAL: + if (lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE) + seq_printf(seq, ", %s", + scsi_devices[lct->lct_entry[i]. + sub_class]); + else + seq_printf(seq, ", Unknown Device Type"); + break; + + case I2O_CLASS_BUS_ADAPTER: + if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) + seq_printf(seq, ", %s", + bus_ports[lct->lct_entry[i]. + sub_class]); + else + seq_printf(seq, ", Unknown Bus Type"); + break; + } + seq_printf(seq, "\n"); + + seq_printf(seq, " Local TID : 0x%03x\n", + lct->lct_entry[i].tid); + seq_printf(seq, " User TID : 0x%03x\n", + lct->lct_entry[i].user_tid); + seq_printf(seq, " Parent TID : 0x%03x\n", + lct->lct_entry[i].parent_tid); + seq_printf(seq, " Identity Tag : 0x%x%x%x%x%x%x%x%x\n", + lct->lct_entry[i].identity_tag[0], + lct->lct_entry[i].identity_tag[1], + lct->lct_entry[i].identity_tag[2], + lct->lct_entry[i].identity_tag[3], + lct->lct_entry[i].identity_tag[4], + lct->lct_entry[i].identity_tag[5], + lct->lct_entry[i].identity_tag[6], + lct->lct_entry[i].identity_tag[7]); + seq_printf(seq, " Change Indicator : %0#10x\n", + lct->lct_entry[i].change_ind); + seq_printf(seq, " Event Capab Mask : %0#10x\n", + lct->lct_entry[i].device_flags); + } + + return 0; +} + +static int i2o_seq_show_status(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + char prodstr[25]; + int version; + i2o_status_block *sb = c->status_block.virt; + + i2o_status_get(c); // reread the status block + + seq_printf(seq, "Organization ID : %0#6x\n", sb->org_id); + + version = sb->i2o_version; + +/* FIXME for Spec 2.0 + if (version == 0x02) { + seq_printf(seq, "Lowest I2O version supported: "); + switch(workspace[2]) { + case 0x00: + seq_printf(seq, "1.0\n"); + break; + case 0x01: + seq_printf(seq, "1.5\n"); + break; + case 0x02: + seq_printf(seq, "2.0\n"); + break; + } + + seq_printf(seq, "Highest I2O version supported: "); + switch(workspace[3]) { + case 0x00: + seq_printf(seq, "1.0\n"); + break; + case 0x01: + seq_printf(seq, "1.5\n"); + break; + case 0x02: + seq_printf(seq, "2.0\n"); + break; + } + } +*/ + seq_printf(seq, "IOP ID : %0#5x\n", sb->iop_id); + seq_printf(seq, "Host Unit ID : %0#6x\n", sb->host_unit_id); + seq_printf(seq, "Segment Number : %0#5x\n", sb->segment_number); + + seq_printf(seq, "I2O version : "); + switch (version) { + case 0x00: + seq_printf(seq, "1.0\n"); + break; + case 0x01: + seq_printf(seq, "1.5\n"); + break; + case 0x02: + seq_printf(seq, "2.0\n"); + break; + default: + seq_printf(seq, "Unknown version\n"); + } + + seq_printf(seq, "IOP State : "); + switch (sb->iop_state) { + case 0x01: + seq_printf(seq, "INIT\n"); + break; + + case 0x02: + seq_printf(seq, "RESET\n"); + break; + + case 0x04: + seq_printf(seq, "HOLD\n"); + break; + + case 0x05: + seq_printf(seq, "READY\n"); + break; + + case 0x08: + seq_printf(seq, "OPERATIONAL\n"); + break; + + case 0x10: + seq_printf(seq, "FAILED\n"); + break; + + case 0x11: + seq_printf(seq, "FAULTED\n"); + break; + + default: + seq_printf(seq, "Unknown\n"); + break; + } + + seq_printf(seq, "Messenger Type : "); + switch (sb->msg_type) { + case 0x00: + seq_printf(seq, "Memory mapped\n"); + break; + case 0x01: + seq_printf(seq, "Memory mapped only\n"); + break; + case 0x02: + seq_printf(seq, "Remote only\n"); + break; + case 0x03: + seq_printf(seq, "Memory mapped and remote\n"); + break; + default: + seq_printf(seq, "Unknown\n"); + } + + seq_printf(seq, "Inbound Frame Size : %d bytes\n", + sb->inbound_frame_size << 2); + seq_printf(seq, "Max Inbound Frames : %d\n", + sb->max_inbound_frames); + seq_printf(seq, "Current Inbound Frames : %d\n", + sb->cur_inbound_frames); + seq_printf(seq, "Max Outbound Frames : %d\n", + sb->max_outbound_frames); + + /* Spec doesn't say if NULL terminated or not... */ + memcpy(prodstr, sb->product_id, 24); + prodstr[24] = '\0'; + seq_printf(seq, "Product ID : %s\n", prodstr); + seq_printf(seq, "Expected LCT Size : %d bytes\n", + sb->expected_lct_size); + + seq_printf(seq, "IOP Capabilities\n"); + seq_printf(seq, " Context Field Size Support : "); + switch (sb->iop_capabilities & 0x0000003) { + case 0: + seq_printf(seq, "Supports only 32-bit context fields\n"); + break; + case 1: + seq_printf(seq, "Supports only 64-bit context fields\n"); + break; + case 2: + seq_printf(seq, "Supports 32-bit and 64-bit context fields, " + "but not concurrently\n"); + break; + case 3: + seq_printf(seq, "Supports 32-bit and 64-bit context fields " + "concurrently\n"); + break; + default: + seq_printf(seq, "0x%08x\n", sb->iop_capabilities); + } + seq_printf(seq, " Current Context Field Size : "); + switch (sb->iop_capabilities & 0x0000000C) { + case 0: + seq_printf(seq, "not configured\n"); + break; + case 4: + seq_printf(seq, "Supports only 32-bit context fields\n"); + break; + case 8: + seq_printf(seq, "Supports only 64-bit context fields\n"); + break; + case 12: + seq_printf(seq, "Supports both 32-bit or 64-bit context fields " + "concurrently\n"); + break; + default: + seq_printf(seq, "\n"); + } + seq_printf(seq, " Inbound Peer Support : %s\n", + (sb-> + iop_capabilities & 0x00000010) ? "Supported" : + "Not supported"); + seq_printf(seq, " Outbound Peer Support : %s\n", + (sb-> + iop_capabilities & 0x00000020) ? "Supported" : + "Not supported"); + seq_printf(seq, " Peer to Peer Support : %s\n", + (sb-> + iop_capabilities & 0x00000040) ? "Supported" : + "Not supported"); + + seq_printf(seq, "Desired private memory size : %d kB\n", + sb->desired_mem_size >> 10); + seq_printf(seq, "Allocated private memory size : %d kB\n", + sb->current_mem_size >> 10); + seq_printf(seq, "Private memory base address : %0#10x\n", + sb->current_mem_base); + seq_printf(seq, "Desired private I/O size : %d kB\n", + sb->desired_io_size >> 10); + seq_printf(seq, "Allocated private I/O size : %d kB\n", + sb->current_io_size >> 10); + seq_printf(seq, "Private I/O base address : %0#10x\n", + sb->current_io_base); + + return 0; +} + +static int i2o_seq_show_hw(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + static u32 work32[5]; + static u8 *work8 = (u8 *) work32; + static u16 *work16 = (u16 *) work32; + int token; + u32 hwcap; + + static char *cpu_table[] = { + "Intel 80960 series", + "AMD2900 series", + "Motorola 68000 series", + "ARM series", + "MIPS series", + "Sparc series", + "PowerPC series", + "Intel x86 series" + }; + + token = + i2o_parm_field_get(c->exec, 0x0000, -1, &work32, sizeof(work32)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0x0000 IOP Hardware"); + return 0; + } + + seq_printf(seq, "I2O Vendor ID : %0#6x\n", work16[0]); + seq_printf(seq, "Product ID : %0#6x\n", work16[1]); + seq_printf(seq, "CPU : "); + if (work8[16] > 8) + seq_printf(seq, "Unknown\n"); + else + seq_printf(seq, "%s\n", cpu_table[work8[16]]); + /* Anyone using ProcessorVersion? */ + + seq_printf(seq, "RAM : %dkB\n", work32[1] >> 10); + seq_printf(seq, "Non-Volatile Mem : %dkB\n", work32[2] >> 10); + + hwcap = work32[3]; + seq_printf(seq, "Capabilities : 0x%08x\n", hwcap); + seq_printf(seq, " [%s] Self booting\n", + (hwcap & 0x00000001) ? "+" : "-"); + seq_printf(seq, " [%s] Upgradable IRTOS\n", + (hwcap & 0x00000002) ? "+" : "-"); + seq_printf(seq, " [%s] Supports downloading DDMs\n", + (hwcap & 0x00000004) ? "+" : "-"); + seq_printf(seq, " [%s] Supports installing DDMs\n", + (hwcap & 0x00000008) ? "+" : "-"); + seq_printf(seq, " [%s] Battery-backed RAM\n", + (hwcap & 0x00000010) ? "+" : "-"); + + return 0; +} + +/* Executive group 0003h - Executing DDM List (table) */ +static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + int token; + int i; + + typedef struct _i2o_exec_execute_ddm_table { + u16 ddm_tid; + u8 module_type; + u8 reserved; + u16 i2o_vendor_id; + u16 module_id; + u8 module_name_version[28]; + u32 data_size; + u32 code_size; + } i2o_exec_execute_ddm_table; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_exec_execute_ddm_table ddm_table[I2O_MAX_MODULES]; + } *result; + + i2o_exec_execute_ddm_table ddm_table; + char tmp[28 + 1]; + + result = kmalloc(sizeof(*result), GFP_KERNEL); + if (!result) + return -ENOMEM; + + token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0003, -1, + NULL, 0, result, sizeof(*result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0x0003 Executing DDM List"); + goto out; + } + + seq_printf(seq, + "Tid Module_type Vendor Mod_id Module_name Vrs Data_size Code_size\n"); + ddm_table = result->ddm_table[0]; + + for (i = 0; i < result->row_count; ddm_table = result->ddm_table[++i]) { + seq_printf(seq, "0x%03x ", ddm_table.ddm_tid & 0xFFF); + + switch (ddm_table.module_type) { + case 0x01: + seq_printf(seq, "Downloaded DDM "); + break; + case 0x22: + seq_printf(seq, "Embedded DDM "); + break; + default: + seq_printf(seq, " "); + } + + seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id); + seq_printf(seq, "%-#8x", ddm_table.module_id); + seq_printf(seq, "%-29s", + chtostr(tmp, ddm_table.module_name_version, 28)); + seq_printf(seq, "%9d ", ddm_table.data_size); + seq_printf(seq, "%8d", ddm_table.code_size); + + seq_printf(seq, "\n"); + } + out: + kfree(result); + return 0; +} + +/* Executive group 0004h - Driver Store (scalar) */ +static int i2o_seq_show_driver_store(struct seq_file *seq, void *v) +{ + struct i2o_controller *c = (struct i2o_controller *)seq->private; + u32 work32[8]; + int token; + + token = + i2o_parm_field_get(c->exec, 0x0004, -1, &work32, sizeof(work32)); + if (token < 0) { + i2o_report_query_status(seq, token, "0x0004 Driver Store"); + return 0; + } + + seq_printf(seq, "Module limit : %d\n" + "Module count : %d\n" + "Current space : %d kB\n" + "Free space : %d kB\n", + work32[0], work32[1], work32[2] >> 10, work32[3] >> 10); + + return 0; +} + +/* Executive group 0005h - Driver Store Table (table) */ +static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) +{ + typedef struct _i2o_driver_store { + u16 stored_ddm_index; + u8 module_type; + u8 reserved; + u16 i2o_vendor_id; + u16 module_id; + u8 module_name_version[28]; + u8 date[8]; + u32 module_size; + u32 mpb_size; + u32 module_flags; + } i2o_driver_store_table; + + struct i2o_controller *c = (struct i2o_controller *)seq->private; + int token; + int i; + + typedef struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_driver_store_table dst[I2O_MAX_MODULES]; + } i2o_driver_result_table; + + i2o_driver_result_table *result; + i2o_driver_store_table *dst; + char tmp[28 + 1]; + + result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL); + if (result == NULL) + return -ENOMEM; + + token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0005, -1, + NULL, 0, result, sizeof(*result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0x0005 DRIVER STORE TABLE"); + kfree(result); + return 0; + } + + seq_printf(seq, + "# Module_type Vendor Mod_id Module_name Vrs" + "Date Mod_size Par_size Flags\n"); + for (i = 0, dst = &result->dst[0]; i < result->row_count; + dst = &result->dst[++i]) { + seq_printf(seq, "%-3d", dst->stored_ddm_index); + switch (dst->module_type) { + case 0x01: + seq_printf(seq, "Downloaded DDM "); + break; + case 0x22: + seq_printf(seq, "Embedded DDM "); + break; + default: + seq_printf(seq, " "); + } + + seq_printf(seq, "%-#7x", dst->i2o_vendor_id); + seq_printf(seq, "%-#8x", dst->module_id); + seq_printf(seq, "%-29s", + chtostr(tmp, dst->module_name_version, 28)); + seq_printf(seq, "%-9s", chtostr(tmp, dst->date, 8)); + seq_printf(seq, "%8d ", dst->module_size); + seq_printf(seq, "%8d ", dst->mpb_size); + seq_printf(seq, "0x%04x", dst->module_flags); + seq_printf(seq, "\n"); + } + + kfree(result); + return 0; +} + +/* Generic group F000h - Params Descriptor (table) */ +static int i2o_seq_show_groups(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + u8 properties; + + typedef struct _i2o_group_info { + u16 group_number; + u16 field_count; + u16 row_count; + u8 properties; + u8 reserved; + } i2o_group_info; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_group_info group[256]; + } *result; + + result = kmalloc(sizeof(*result), GFP_KERNEL); + if (!result) + return -ENOMEM; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0, + result, sizeof(*result)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF000 Params Descriptor"); + goto out; + } + + seq_printf(seq, + "# Group FieldCount RowCount Type Add Del Clear\n"); + + for (i = 0; i < result->row_count; i++) { + seq_printf(seq, "%-3d", i); + seq_printf(seq, "0x%04X ", result->group[i].group_number); + seq_printf(seq, "%10d ", result->group[i].field_count); + seq_printf(seq, "%8d ", result->group[i].row_count); + + properties = result->group[i].properties; + if (properties & 0x1) + seq_printf(seq, "Table "); + else + seq_printf(seq, "Scalar "); + if (properties & 0x2) + seq_printf(seq, " + "); + else + seq_printf(seq, " - "); + if (properties & 0x4) + seq_printf(seq, " + "); + else + seq_printf(seq, " - "); + if (properties & 0x8) + seq_printf(seq, " + "); + else + seq_printf(seq, " - "); + + seq_printf(seq, "\n"); + } + + if (result->more_flag) + seq_printf(seq, "There is more...\n"); + out: + kfree(result); + return 0; +} + +/* Generic group F001h - Physical Device Table (table) */ +static int i2o_seq_show_phys_device(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + u32 adapter_id[64]; + } result; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF001, -1, NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0xF001 Physical Device Table"); + return 0; + } + + if (result.row_count) + seq_printf(seq, "# AdapterId\n"); + + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%-2d", i); + seq_printf(seq, "%#7x\n", result.adapter_id[i]); + } + + if (result.more_flag) + seq_printf(seq, "There is more...\n"); + + return 0; +} + +/* Generic group F002h - Claimed Table (table) */ +static int i2o_seq_show_claimed(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + u16 claimed_tid[64]; + } result; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF002, -1, NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF002 Claimed Table"); + return 0; + } + + if (result.row_count) + seq_printf(seq, "# ClaimedTid\n"); + + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%-2d", i); + seq_printf(seq, "%#7x\n", result.claimed_tid[i]); + } + + if (result.more_flag) + seq_printf(seq, "There is more...\n"); + + return 0; +} + +/* Generic group F003h - User Table (table) */ +static int i2o_seq_show_users(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + + typedef struct _i2o_user_table { + u16 instance; + u16 user_tid; + u8 claim_type; + u8 reserved1; + u16 reserved2; + } i2o_user_table; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_user_table user[64]; + } *result; + + result = kmalloc(sizeof(*result), GFP_KERNEL); + if (!result) + return -ENOMEM; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF003, -1, NULL, 0, + result, sizeof(*result)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF003 User Table"); + goto out; + } + + seq_printf(seq, "# Instance UserTid ClaimType\n"); + + for (i = 0; i < result->row_count; i++) { + seq_printf(seq, "%-3d", i); + seq_printf(seq, "%#8x ", result->user[i].instance); + seq_printf(seq, "%#7x ", result->user[i].user_tid); + seq_printf(seq, "%#9x\n", result->user[i].claim_type); + } + + if (result->more_flag) + seq_printf(seq, "There is more...\n"); + out: + kfree(result); + return 0; +} + +/* Generic group F005h - Private message extensions (table) (optional) */ +static int i2o_seq_show_priv_msgs(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + + typedef struct _i2o_private { + u16 ext_instance; + u16 organization_id; + u16 x_function_code; + } i2o_private; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_private extension[64]; + } result; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0xF005 Private Message Extensions (optional)"); + return 0; + } + + seq_printf(seq, "Instance# OrgId FunctionCode\n"); + + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%0#9x ", result.extension[i].ext_instance); + seq_printf(seq, "%0#6x ", result.extension[i].organization_id); + seq_printf(seq, "%0#6x", result.extension[i].x_function_code); + + seq_printf(seq, "\n"); + } + + if (result.more_flag) + seq_printf(seq, "There is more...\n"); + + return 0; +} + +/* Generic group F006h - Authorized User Table (table) */ +static int i2o_seq_show_authorized_users(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + int i; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + u32 alternate_tid[64]; + } result; + + token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF006, -1, NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0xF006 Autohorized User Table"); + return 0; + } + + if (result.row_count) + seq_printf(seq, "# AlternateTid\n"); + + for (i = 0; i < result.row_count; i++) { + seq_printf(seq, "%-2d", i); + seq_printf(seq, "%#7x ", result.alternate_tid[i]); + } + + if (result.more_flag) + seq_printf(seq, "There is more...\n"); + + return 0; +} + +/* Generic group F100h - Device Identity (scalar) */ +static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + static u32 work32[128]; // allow for "stuff" + up to 256 byte (max) serial number + // == (allow) 512d bytes (max) + static u16 *work16 = (u16 *) work32; + int token; + char tmp[16 + 1]; + + token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF100 Device Identity"); + return 0; + } + + seq_printf(seq, "Device Class : %s\n", i2o_get_class_name(work16[0])); + seq_printf(seq, "Owner TID : %0#5x\n", work16[2]); + seq_printf(seq, "Parent TID : %0#5x\n", work16[3]); + seq_printf(seq, "Vendor info : %s\n", + chtostr(tmp, (u8 *) (work32 + 2), 16)); + seq_printf(seq, "Product info : %s\n", + chtostr(tmp, (u8 *) (work32 + 6), 16)); + seq_printf(seq, "Description : %s\n", + chtostr(tmp, (u8 *) (work32 + 10), 16)); + seq_printf(seq, "Product rev. : %s\n", + chtostr(tmp, (u8 *) (work32 + 14), 8)); + + seq_printf(seq, "Serial number : "); + print_serial_number(seq, (u8 *) (work32 + 16), + /* allow for SNLen plus + * possible trailing '\0' + */ + sizeof(work32) - (16 * sizeof(u32)) - 2); + seq_printf(seq, "\n"); + + return 0; +} + +static int i2o_seq_show_dev_name(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + + seq_printf(seq, "%s\n", dev_name(&d->device)); + + return 0; +} + +/* Generic group F101h - DDM Identity (scalar) */ +static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + + struct { + u16 ddm_tid; + u8 module_name[24]; + u8 module_rev[8]; + u8 sn_format; + u8 serial_number[12]; + u8 pad[256]; // allow up to 256 byte (max) serial number + } result; + + char tmp[24 + 1]; + + token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF101 DDM Identity"); + return 0; + } + + seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid); + seq_printf(seq, "Module name : %s\n", + chtostr(tmp, result.module_name, 24)); + seq_printf(seq, "Module revision : %s\n", + chtostr(tmp, result.module_rev, 8)); + + seq_printf(seq, "Serial number : "); + print_serial_number(seq, result.serial_number, sizeof(result) - 36); + /* allow for SNLen plus possible trailing '\0' */ + + seq_printf(seq, "\n"); + + return 0; +} + +/* Generic group F102h - User Information (scalar) */ +static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + + struct { + u8 device_name[64]; + u8 service_name[64]; + u8 physical_location[64]; + u8 instance_number[4]; + } result; + + char tmp[64 + 1]; + + token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, "0xF102 User Information"); + return 0; + } + + seq_printf(seq, "Device name : %s\n", + chtostr(tmp, result.device_name, 64)); + seq_printf(seq, "Service name : %s\n", + chtostr(tmp, result.service_name, 64)); + seq_printf(seq, "Physical name : %s\n", + chtostr(tmp, result.physical_location, 64)); + seq_printf(seq, "Instance number : %s\n", + chtostr(tmp, result.instance_number, 4)); + + return 0; +} + +/* Generic group F103h - SGL Operating Limits (scalar) */ +static int i2o_seq_show_sgl_limits(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + static u32 work32[12]; + static u16 *work16 = (u16 *) work32; + static u8 *work8 = (u8 *) work32; + int token; + + token = i2o_parm_field_get(d, 0xF103, -1, &work32, sizeof(work32)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0xF103 SGL Operating Limits"); + return 0; + } + + seq_printf(seq, "SGL chain size : %d\n", work32[0]); + seq_printf(seq, "Max SGL chain size : %d\n", work32[1]); + seq_printf(seq, "SGL chain size target : %d\n", work32[2]); + seq_printf(seq, "SGL frag count : %d\n", work16[6]); + seq_printf(seq, "Max SGL frag count : %d\n", work16[7]); + seq_printf(seq, "SGL frag count target : %d\n", work16[8]); + +/* FIXME + if (d->i2oversion == 0x02) + { +*/ + seq_printf(seq, "SGL data alignment : %d\n", work16[8]); + seq_printf(seq, "SGL addr limit : %d\n", work8[20]); + seq_printf(seq, "SGL addr sizes supported : "); + if (work8[21] & 0x01) + seq_printf(seq, "32 bit "); + if (work8[21] & 0x02) + seq_printf(seq, "64 bit "); + if (work8[21] & 0x04) + seq_printf(seq, "96 bit "); + if (work8[21] & 0x08) + seq_printf(seq, "128 bit "); + seq_printf(seq, "\n"); +/* + } +*/ + + return 0; +} + +/* Generic group F200h - Sensors (scalar) */ +static int i2o_seq_show_sensors(struct seq_file *seq, void *v) +{ + struct i2o_device *d = (struct i2o_device *)seq->private; + int token; + + struct { + u16 sensor_instance; + u8 component; + u16 component_instance; + u8 sensor_class; + u8 sensor_type; + u8 scaling_exponent; + u32 actual_reading; + u32 minimum_reading; + u32 low2lowcat_treshold; + u32 lowcat2low_treshold; + u32 lowwarn2low_treshold; + u32 low2lowwarn_treshold; + u32 norm2lowwarn_treshold; + u32 lowwarn2norm_treshold; + u32 nominal_reading; + u32 hiwarn2norm_treshold; + u32 norm2hiwarn_treshold; + u32 high2hiwarn_treshold; + u32 hiwarn2high_treshold; + u32 hicat2high_treshold; + u32 hi2hicat_treshold; + u32 maximum_reading; + u8 sensor_state; + u16 event_enable; + } result; + + token = i2o_parm_field_get(d, 0xF200, -1, &result, sizeof(result)); + + if (token < 0) { + i2o_report_query_status(seq, token, + "0xF200 Sensors (optional)"); + return 0; + } + + seq_printf(seq, "Sensor instance : %d\n", result.sensor_instance); + + seq_printf(seq, "Component : %d = ", result.component); + switch (result.component) { + case 0: + seq_printf(seq, "Other"); + break; + case 1: + seq_printf(seq, "Planar logic Board"); + break; + case 2: + seq_printf(seq, "CPU"); + break; + case 3: + seq_printf(seq, "Chassis"); + break; + case 4: + seq_printf(seq, "Power Supply"); + break; + case 5: + seq_printf(seq, "Storage"); + break; + case 6: + seq_printf(seq, "External"); + break; + } + seq_printf(seq, "\n"); + + seq_printf(seq, "Component instance : %d\n", + result.component_instance); + seq_printf(seq, "Sensor class : %s\n", + result.sensor_class ? "Analog" : "Digital"); + + seq_printf(seq, "Sensor type : %d = ", result.sensor_type); + switch (result.sensor_type) { + case 0: + seq_printf(seq, "Other\n"); + break; + case 1: + seq_printf(seq, "Thermal\n"); + break; + case 2: + seq_printf(seq, "DC voltage (DC volts)\n"); + break; + case 3: + seq_printf(seq, "AC voltage (AC volts)\n"); + break; + case 4: + seq_printf(seq, "DC current (DC amps)\n"); + break; + case 5: + seq_printf(seq, "AC current (AC volts)\n"); + break; + case 6: + seq_printf(seq, "Door open\n"); + break; + case 7: + seq_printf(seq, "Fan operational\n"); + break; + } + + seq_printf(seq, "Scaling exponent : %d\n", + result.scaling_exponent); + seq_printf(seq, "Actual reading : %d\n", result.actual_reading); + seq_printf(seq, "Minimum reading : %d\n", result.minimum_reading); + seq_printf(seq, "Low2LowCat treshold : %d\n", + result.low2lowcat_treshold); + seq_printf(seq, "LowCat2Low treshold : %d\n", + result.lowcat2low_treshold); + seq_printf(seq, "LowWarn2Low treshold : %d\n", + result.lowwarn2low_treshold); + seq_printf(seq, "Low2LowWarn treshold : %d\n", + result.low2lowwarn_treshold); + seq_printf(seq, "Norm2LowWarn treshold : %d\n", + result.norm2lowwarn_treshold); + seq_printf(seq, "LowWarn2Norm treshold : %d\n", + result.lowwarn2norm_treshold); + seq_printf(seq, "Nominal reading : %d\n", result.nominal_reading); + seq_printf(seq, "HiWarn2Norm treshold : %d\n", + result.hiwarn2norm_treshold); + seq_printf(seq, "Norm2HiWarn treshold : %d\n", + result.norm2hiwarn_treshold); + seq_printf(seq, "High2HiWarn treshold : %d\n", + result.high2hiwarn_treshold); + seq_printf(seq, "HiWarn2High treshold : %d\n", + result.hiwarn2high_treshold); + seq_printf(seq, "HiCat2High treshold : %d\n", + result.hicat2high_treshold); + seq_printf(seq, "High2HiCat treshold : %d\n", + result.hi2hicat_treshold); + seq_printf(seq, "Maximum reading : %d\n", result.maximum_reading); + + seq_printf(seq, "Sensor state : %d = ", result.sensor_state); + switch (result.sensor_state) { + case 0: + seq_printf(seq, "Normal\n"); + break; + case 1: + seq_printf(seq, "Abnormal\n"); + break; + case 2: + seq_printf(seq, "Unknown\n"); + break; + case 3: + seq_printf(seq, "Low Catastrophic (LoCat)\n"); + break; + case 4: + seq_printf(seq, "Low (Low)\n"); + break; + case 5: + seq_printf(seq, "Low Warning (LoWarn)\n"); + break; + case 6: + seq_printf(seq, "High Warning (HiWarn)\n"); + break; + case 7: + seq_printf(seq, "High (High)\n"); + break; + case 8: + seq_printf(seq, "High Catastrophic (HiCat)\n"); + break; + } + + seq_printf(seq, "Event_enable : 0x%02X\n", result.event_enable); + seq_printf(seq, " [%s] Operational state change. \n", + (result.event_enable & 0x01) ? "+" : "-"); + seq_printf(seq, " [%s] Low catastrophic. \n", + (result.event_enable & 0x02) ? "+" : "-"); + seq_printf(seq, " [%s] Low reading. \n", + (result.event_enable & 0x04) ? "+" : "-"); + seq_printf(seq, " [%s] Low warning. \n", + (result.event_enable & 0x08) ? "+" : "-"); + seq_printf(seq, + " [%s] Change back to normal from out of range state. \n", + (result.event_enable & 0x10) ? "+" : "-"); + seq_printf(seq, " [%s] High warning. \n", + (result.event_enable & 0x20) ? "+" : "-"); + seq_printf(seq, " [%s] High reading. \n", + (result.event_enable & 0x40) ? "+" : "-"); + seq_printf(seq, " [%s] High catastrophic. \n", + (result.event_enable & 0x80) ? "+" : "-"); + + return 0; +} + +static int i2o_seq_open_hrt(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_hrt, PDE_DATA(inode)); +}; + +static int i2o_seq_open_lct(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_lct, PDE_DATA(inode)); +}; + +static int i2o_seq_open_status(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_status, PDE_DATA(inode)); +}; + +static int i2o_seq_open_hw(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_hw, PDE_DATA(inode)); +}; + +static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_ddm_table, PDE_DATA(inode)); +}; + +static int i2o_seq_open_driver_store(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_driver_store, PDE_DATA(inode)); +}; + +static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_drivers_stored, PDE_DATA(inode)); +}; + +static int i2o_seq_open_groups(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_groups, PDE_DATA(inode)); +}; + +static int i2o_seq_open_phys_device(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_phys_device, PDE_DATA(inode)); +}; + +static int i2o_seq_open_claimed(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_claimed, PDE_DATA(inode)); +}; + +static int i2o_seq_open_users(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_users, PDE_DATA(inode)); +}; + +static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_priv_msgs, PDE_DATA(inode)); +}; + +static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_authorized_users, + PDE_DATA(inode)); +}; + +static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_dev_identity, PDE_DATA(inode)); +}; + +static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_ddm_identity, PDE_DATA(inode)); +}; + +static int i2o_seq_open_uinfo(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_uinfo, PDE_DATA(inode)); +}; + +static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_sgl_limits, PDE_DATA(inode)); +}; + +static int i2o_seq_open_sensors(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_sensors, PDE_DATA(inode)); +}; + +static int i2o_seq_open_dev_name(struct inode *inode, struct file *file) +{ + return single_open(file, i2o_seq_show_dev_name, PDE_DATA(inode)); +}; + +static const struct file_operations i2o_seq_fops_lct = { + .open = i2o_seq_open_lct, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_hrt = { + .open = i2o_seq_open_hrt, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_status = { + .open = i2o_seq_open_status, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_hw = { + .open = i2o_seq_open_hw, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_ddm_table = { + .open = i2o_seq_open_ddm_table, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_driver_store = { + .open = i2o_seq_open_driver_store, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_drivers_stored = { + .open = i2o_seq_open_drivers_stored, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_groups = { + .open = i2o_seq_open_groups, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_phys_device = { + .open = i2o_seq_open_phys_device, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_claimed = { + .open = i2o_seq_open_claimed, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_users = { + .open = i2o_seq_open_users, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_priv_msgs = { + .open = i2o_seq_open_priv_msgs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_authorized_users = { + .open = i2o_seq_open_authorized_users, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_dev_name = { + .open = i2o_seq_open_dev_name, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_dev_identity = { + .open = i2o_seq_open_dev_identity, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_ddm_identity = { + .open = i2o_seq_open_ddm_identity, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_uinfo = { + .open = i2o_seq_open_uinfo, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_sgl_limits = { + .open = i2o_seq_open_sgl_limits, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations i2o_seq_fops_sensors = { + .open = i2o_seq_open_sensors, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* + * IOP specific entries...write field just in case someone + * ever wants one. + */ +static i2o_proc_entry i2o_proc_generic_iop_entries[] = { + {"hrt", S_IFREG | S_IRUGO, &i2o_seq_fops_hrt}, + {"lct", S_IFREG | S_IRUGO, &i2o_seq_fops_lct}, + {"status", S_IFREG | S_IRUGO, &i2o_seq_fops_status}, + {"hw", S_IFREG | S_IRUGO, &i2o_seq_fops_hw}, + {"ddm_table", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_table}, + {"driver_store", S_IFREG | S_IRUGO, &i2o_seq_fops_driver_store}, + {"drivers_stored", S_IFREG | S_IRUGO, &i2o_seq_fops_drivers_stored}, + {NULL, 0, NULL} +}; + +/* + * Device specific entries + */ +static i2o_proc_entry generic_dev_entries[] = { + {"groups", S_IFREG | S_IRUGO, &i2o_seq_fops_groups}, + {"phys_dev", S_IFREG | S_IRUGO, &i2o_seq_fops_phys_device}, + {"claimed", S_IFREG | S_IRUGO, &i2o_seq_fops_claimed}, + {"users", S_IFREG | S_IRUGO, &i2o_seq_fops_users}, + {"priv_msgs", S_IFREG | S_IRUGO, &i2o_seq_fops_priv_msgs}, + {"authorized_users", S_IFREG | S_IRUGO, &i2o_seq_fops_authorized_users}, + {"dev_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_identity}, + {"ddm_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_identity}, + {"user_info", S_IFREG | S_IRUGO, &i2o_seq_fops_uinfo}, + {"sgl_limits", S_IFREG | S_IRUGO, &i2o_seq_fops_sgl_limits}, + {"sensors", S_IFREG | S_IRUGO, &i2o_seq_fops_sensors}, + {NULL, 0, NULL} +}; + +/* + * Storage unit specific entries (SCSI Periph, BS) with device names + */ +static i2o_proc_entry rbs_dev_entries[] = { + {"dev_name", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_name}, + {NULL, 0, NULL} +}; + +/** + * i2o_proc_create_entries - Creates proc dir entries + * @dir: proc dir entry under which the entries should be placed + * @i2o_pe: pointer to the entries which should be added + * @data: pointer to I2O controller or device + * + * Create proc dir entries for a I2O controller or I2O device. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_proc_create_entries(struct proc_dir_entry *dir, + i2o_proc_entry * i2o_pe, void *data) +{ + struct proc_dir_entry *tmp; + + while (i2o_pe->name) { + tmp = proc_create_data(i2o_pe->name, i2o_pe->mode, dir, + i2o_pe->fops, data); + if (!tmp) + return -1; + + i2o_pe++; + } + + return 0; +} + +/** + * i2o_proc_device_add - Add an I2O device to the proc dir + * @dir: proc dir entry to which the device should be added + * @dev: I2O device which should be added + * + * Add an I2O device to the proc dir entry dir and create the entries for + * the device depending on the class of the I2O device. + */ +static void i2o_proc_device_add(struct proc_dir_entry *dir, + struct i2o_device *dev) +{ + char buff[10]; + struct proc_dir_entry *devdir; + i2o_proc_entry *i2o_pe = NULL; + + sprintf(buff, "%03x", dev->lct_data.tid); + + osm_debug("adding device /proc/i2o/%s/%s\n", dev->iop->name, buff); + + devdir = proc_mkdir_data(buff, 0, dir, dev); + if (!devdir) { + osm_warn("Could not allocate procdir!\n"); + return; + } + + i2o_proc_create_entries(devdir, generic_dev_entries, dev); + + /* Inform core that we want updates about this device's status */ + switch (dev->lct_data.class_id) { + case I2O_CLASS_SCSI_PERIPHERAL: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + i2o_pe = rbs_dev_entries; + break; + default: + break; + } + if (i2o_pe) + i2o_proc_create_entries(devdir, i2o_pe, dev); +} + +/** + * i2o_proc_iop_add - Add an I2O controller to the i2o proc tree + * @dir: parent proc dir entry + * @c: I2O controller which should be added + * + * Add the entries to the parent proc dir entry. Also each device is added + * to the controllers proc dir entry. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_proc_iop_add(struct proc_dir_entry *dir, + struct i2o_controller *c) +{ + struct proc_dir_entry *iopdir; + struct i2o_device *dev; + + osm_debug("adding IOP /proc/i2o/%s\n", c->name); + + iopdir = proc_mkdir_data(c->name, 0, dir, c); + if (!iopdir) + return -1; + + i2o_proc_create_entries(iopdir, i2o_proc_generic_iop_entries, c); + + list_for_each_entry(dev, &c->devices, list) + i2o_proc_device_add(iopdir, dev); + + return 0; +} + +/** + * i2o_proc_fs_create - Create the i2o proc fs. + * + * Iterate over each I2O controller and create the entries for it. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_proc_fs_create(void) +{ + struct i2o_controller *c; + + i2o_proc_dir_root = proc_mkdir("i2o", NULL); + if (!i2o_proc_dir_root) + return -1; + + list_for_each_entry(c, &i2o_controllers, list) + i2o_proc_iop_add(i2o_proc_dir_root, c); + + return 0; +}; + +/** + * i2o_proc_fs_destroy - Cleanup the all i2o proc entries + * + * Iterate over each I2O controller and remove the entries for it. + * + * Returns 0 on success or negative error code on failure. + */ +static int __exit i2o_proc_fs_destroy(void) +{ + remove_proc_subtree("i2o", NULL); + + return 0; +}; + +/** + * i2o_proc_init - Init function for procfs + * + * Registers Proc OSM and creates procfs entries. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_proc_init(void) +{ + int rc; + + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + rc = i2o_driver_register(&i2o_proc_driver); + if (rc) + return rc; + + rc = i2o_proc_fs_create(); + if (rc) { + i2o_driver_unregister(&i2o_proc_driver); + return rc; + } + + return 0; +}; + +/** + * i2o_proc_exit - Exit function for procfs + * + * Unregisters Proc OSM and removes procfs entries. + */ +static void __exit i2o_proc_exit(void) +{ + i2o_driver_unregister(&i2o_proc_driver); + i2o_proc_fs_destroy(); +}; + +MODULE_AUTHOR("Deepak Saxena"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_proc_init); +module_exit(i2o_proc_exit); diff --git a/drivers/staging/i2o/i2o_scsi.c b/drivers/staging/i2o/i2o_scsi.c new file mode 100644 index 0000000..1b11dcb --- /dev/null +++ b/drivers/staging/i2o/i2o_scsi.c @@ -0,0 +1,814 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open non patent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. + * + * Complications for I2O scsi + * + * o Each (bus,lun) is a logical device in I2O. We keep a map + * table. We spoof failed selection for unmapped units + * o Request sense buffers can come back for free. + * o Scatter gather is a bit dynamic. We have to investigate at + * setup time. + * o Some of our resources are dynamically shared. The i2o core + * needs a message reservation protocol to avoid swap v net + * deadlocking. We need to back off queue requests. + * + * In general the firmware wants to help. Where its help isn't performance + * useful we just ignore the aid. Its not worth the code in truth. + * + * Fixes/additions: + * Steve Ralston: + * Scatter gather now works + * Markus Lidel : + * Minor fixes for 2.6. + * + * To Do: + * 64bit cleanups + * Fix the resource management problems. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i2o.h" +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define OSM_NAME "scsi-osm" +#define OSM_VERSION "1.316" +#define OSM_DESCRIPTION "I2O SCSI Peripheral OSM" + +static struct i2o_driver i2o_scsi_driver; + +static unsigned int i2o_scsi_max_id = 16; +static unsigned int i2o_scsi_max_lun = 255; + +struct i2o_scsi_host { + struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ + struct i2o_controller *iop; /* pointer to the I2O controller */ + u64 lun; /* lun's used for block devices */ + struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ +}; + +static struct scsi_host_template i2o_scsi_host_template; + +#define I2O_SCSI_CAN_QUEUE 4 + +/* SCSI OSM class handling definition */ +static struct i2o_class_id i2o_scsi_class_id[] = { + {I2O_CLASS_SCSI_PERIPHERAL}, + {I2O_CLASS_END} +}; + +static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) +{ + struct i2o_scsi_host *i2o_shost; + struct i2o_device *i2o_dev; + struct Scsi_Host *scsi_host; + int max_channel = 0; + u8 type; + int i; + size_t size; + u16 body_size = 6; + +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) + body_size = 8; +#endif + + list_for_each_entry(i2o_dev, &c->devices, list) + if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { + if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) + && (type == 0x01)) /* SCSI bus */ + max_channel++; + } + + if (!max_channel) { + osm_warn("no channels found on %s\n", c->name); + return ERR_PTR(-EFAULT); + } + + size = max_channel * sizeof(struct i2o_device *) + + sizeof(struct i2o_scsi_host); + + scsi_host = scsi_host_alloc(&i2o_scsi_host_template, size); + if (!scsi_host) { + osm_warn("Could not allocate SCSI host\n"); + return ERR_PTR(-ENOMEM); + } + + scsi_host->max_channel = max_channel - 1; + scsi_host->max_id = i2o_scsi_max_id; + scsi_host->max_lun = i2o_scsi_max_lun; + scsi_host->this_id = c->unit; + scsi_host->sg_tablesize = i2o_sg_tablesize(c, body_size); + + i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata; + i2o_shost->scsi_host = scsi_host; + i2o_shost->iop = c; + i2o_shost->lun = 1; + + i = 0; + list_for_each_entry(i2o_dev, &c->devices, list) + if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { + if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) + && (type == 0x01)) /* only SCSI bus */ + i2o_shost->channel[i++] = i2o_dev; + + if (i >= max_channel) + break; + } + + return i2o_shost; +}; + +/** + * i2o_scsi_get_host - Get an I2O SCSI host + * @c: I2O controller to for which to get the SCSI host + * + * If the I2O controller already exists as SCSI host, the SCSI host + * is returned, otherwise the I2O controller is added to the SCSI + * core. + * + * Returns pointer to the I2O SCSI host on success or NULL on failure. + */ +static struct i2o_scsi_host *i2o_scsi_get_host(struct i2o_controller *c) +{ + return c->driver_data[i2o_scsi_driver.context]; +}; + +/** + * i2o_scsi_remove - Remove I2O device from SCSI core + * @dev: device which should be removed + * + * Removes the I2O device from the SCSI core again. + * + * Returns 0 on success. + */ +static int i2o_scsi_remove(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_controller *c = i2o_dev->iop; + struct i2o_scsi_host *i2o_shost; + struct scsi_device *scsi_dev; + + osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid); + + i2o_shost = i2o_scsi_get_host(c); + + shost_for_each_device(scsi_dev, i2o_shost->scsi_host) + if (scsi_dev->hostdata == i2o_dev) { + sysfs_remove_link(&i2o_dev->device.kobj, "scsi"); + scsi_remove_device(scsi_dev); + scsi_device_put(scsi_dev); + break; + } + + return 0; +}; + +/** + * i2o_scsi_probe - verify if dev is a I2O SCSI device and install it + * @dev: device to verify if it is a I2O SCSI device + * + * Retrieve channel, id and lun for I2O device. If everything goes well + * register the I2O device as SCSI device on the I2O SCSI controller. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_scsi_probe(struct device *dev) +{ + struct i2o_device *i2o_dev = to_i2o_device(dev); + struct i2o_controller *c = i2o_dev->iop; + struct i2o_scsi_host *i2o_shost; + struct Scsi_Host *scsi_host; + struct i2o_device *parent; + struct scsi_device *scsi_dev; + u32 id = -1; + u64 lun = -1; + int channel = -1; + int i, rc; + + i2o_shost = i2o_scsi_get_host(c); + if (!i2o_shost) + return -EFAULT; + + scsi_host = i2o_shost->scsi_host; + + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + case I2O_CLASS_EXECUTIVE: +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + u8 type; + struct i2o_device *d = i2o_shost->channel[0]; + + if (!i2o_parm_field_get(d, 0x0000, 0, &type, 1) + && (type == 0x01)) /* SCSI bus */ + if (!i2o_parm_field_get(d, 0x0200, 4, &id, 4)) { + channel = 0; + if (i2o_dev->lct_data.class_id == + I2O_CLASS_RANDOM_BLOCK_STORAGE) + lun = + cpu_to_le64(i2o_shost-> + lun++); + else + lun = 0; + } + } +#endif + break; + + case I2O_CLASS_SCSI_PERIPHERAL: + if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4)) + return -EFAULT; + + if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8)) + return -EFAULT; + + parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); + if (!parent) { + osm_warn("can not find parent of device %03x\n", + i2o_dev->lct_data.tid); + return -EFAULT; + } + + for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++) + if (i2o_shost->channel[i] == parent) + channel = i; + break; + + default: + return -EFAULT; + } + + if (channel == -1) { + osm_warn("can not find channel of device %03x\n", + i2o_dev->lct_data.tid); + return -EFAULT; + } + + if (le32_to_cpu(id) >= scsi_host->max_id) { + osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", + le32_to_cpu(id), scsi_host->max_id); + return -EFAULT; + } + + if (le64_to_cpu(lun) >= scsi_host->max_lun) { + osm_warn("SCSI device lun (%llu) >= max_lun of I2O host (%llu)", + le64_to_cpu(lun), scsi_host->max_lun); + return -EFAULT; + } + + scsi_dev = + __scsi_add_device(i2o_shost->scsi_host, channel, le32_to_cpu(id), + le64_to_cpu(lun), i2o_dev); + + if (IS_ERR(scsi_dev)) { + osm_warn("can not add SCSI device %03x\n", + i2o_dev->lct_data.tid); + return PTR_ERR(scsi_dev); + } + + rc = sysfs_create_link(&i2o_dev->device.kobj, + &scsi_dev->sdev_gendev.kobj, "scsi"); + if (rc) + goto err; + + osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %llu\n", + i2o_dev->lct_data.tid, channel, le32_to_cpu(id), + le64_to_cpu(lun)); + + return 0; + +err: + scsi_remove_device(scsi_dev); + return rc; +}; + +static const char *i2o_scsi_info(struct Scsi_Host *SChost) +{ + struct i2o_scsi_host *hostdata; + hostdata = (struct i2o_scsi_host *)SChost->hostdata; + return hostdata->iop->name; +} + +/** + * i2o_scsi_reply - SCSI OSM message reply handler + * @c: controller issuing the reply + * @m: message id for flushing + * @msg: the message from the controller + * + * Process reply messages (interrupts in normal scsi controller think). + * We can get a variety of messages to process. The normal path is + * scsi command completions. We must also deal with IOP failures, + * the reply to a bus reset and the reply to a LUN query. + * + * Returns 0 on success and if the reply should not be flushed or > 0 + * on success and if the reply should be flushed. Returns negative error + * code on failure and if the reply should be flushed. + */ +static int i2o_scsi_reply(struct i2o_controller *c, u32 m, + struct i2o_message *msg) +{ + struct scsi_cmnd *cmd; + u32 error; + struct device *dev; + + cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt)); + if (unlikely(!cmd)) { + osm_err("NULL reply received!\n"); + return -1; + } + + /* + * Low byte is device status, next is adapter status, + * (then one byte reserved), then request status. + */ + error = le32_to_cpu(msg->body[0]); + + osm_debug("Completed %0x%p\n", cmd); + + cmd->result = error & 0xff; + /* + * if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let + * the SCSI layer handle the error + */ + if (cmd->result) + memcpy(cmd->sense_buffer, &msg->body[3], + min(SCSI_SENSE_BUFFERSIZE, 40)); + + /* only output error code if AdapterStatus is not HBA_SUCCESS */ + if ((error >> 8) & 0xff) + osm_err("SCSI error %08x\n", error); + + dev = &c->pdev->dev; + + scsi_dma_unmap(cmd); + + cmd->scsi_done(cmd); + + return 1; +}; + +/** + * i2o_scsi_notify_device_add - Retrieve notifications of added devices + * @i2o_dev: the I2O device which was added + * + * If a I2O device is added we catch the notification, because I2O classes + * other than SCSI peripheral will not be received through + * i2o_scsi_probe(). + */ +static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev) +{ + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + i2o_scsi_probe(&i2o_dev->device); + break; + + default: + break; + } +}; + +/** + * i2o_scsi_notify_device_remove - Retrieve notifications of removed devices + * @i2o_dev: the I2O device which was removed + * + * If a I2O device is removed, we catch the notification to remove the + * corresponding SCSI device. + */ +static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev) +{ + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + i2o_scsi_remove(&i2o_dev->device); + break; + + default: + break; + } +}; + +/** + * i2o_scsi_notify_controller_add - Retrieve notifications of added controllers + * @c: the controller which was added + * + * If a I2O controller is added, we catch the notification to add a + * corresponding Scsi_Host. + */ +static void i2o_scsi_notify_controller_add(struct i2o_controller *c) +{ + struct i2o_scsi_host *i2o_shost; + int rc; + + i2o_shost = i2o_scsi_host_alloc(c); + if (IS_ERR(i2o_shost)) { + osm_err("Could not initialize SCSI host\n"); + return; + } + + rc = scsi_add_host(i2o_shost->scsi_host, &c->device); + if (rc) { + osm_err("Could not add SCSI host\n"); + scsi_host_put(i2o_shost->scsi_host); + return; + } + + c->driver_data[i2o_scsi_driver.context] = i2o_shost; + + osm_debug("new I2O SCSI host added\n"); +}; + +/** + * i2o_scsi_notify_controller_remove - Retrieve notifications of removed controllers + * @c: the controller which was removed + * + * If a I2O controller is removed, we catch the notification to remove the + * corresponding Scsi_Host. + */ +static void i2o_scsi_notify_controller_remove(struct i2o_controller *c) +{ + struct i2o_scsi_host *i2o_shost; + i2o_shost = i2o_scsi_get_host(c); + if (!i2o_shost) + return; + + c->driver_data[i2o_scsi_driver.context] = NULL; + + scsi_remove_host(i2o_shost->scsi_host); + scsi_host_put(i2o_shost->scsi_host); + osm_debug("I2O SCSI host removed\n"); +}; + +/* SCSI OSM driver struct */ +static struct i2o_driver i2o_scsi_driver = { + .name = OSM_NAME, + .reply = i2o_scsi_reply, + .classes = i2o_scsi_class_id, + .notify_device_add = i2o_scsi_notify_device_add, + .notify_device_remove = i2o_scsi_notify_device_remove, + .notify_controller_add = i2o_scsi_notify_controller_add, + .notify_controller_remove = i2o_scsi_notify_controller_remove, + .driver = { + .probe = i2o_scsi_probe, + .remove = i2o_scsi_remove, + }, +}; + +/** + * i2o_scsi_queuecommand - queue a SCSI command + * @SCpnt: scsi command pointer + * @done: callback for completion + * + * Issue a scsi command asynchronously. Return 0 on success or 1 if + * we hit an error (normally message queue congestion). The only + * minor complication here is that I2O deals with the device addressing + * so we have to map the bus/dev/lun back to an I2O handle as well + * as faking absent devices ourself. + * + * Locks: takes the controller lock on error path only + */ + +static int i2o_scsi_queuecommand_lck(struct scsi_cmnd *SCpnt, + void (*done) (struct scsi_cmnd *)) +{ + struct i2o_controller *c; + struct i2o_device *i2o_dev; + int tid; + struct i2o_message *msg; + /* + * ENABLE_DISCONNECT + * SIMPLE_TAG + * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME + */ + u32 scsi_flags = 0x20a00000; + u32 sgl_offset; + u32 *mptr; + u32 cmd = I2O_CMD_SCSI_EXEC << 24; + int rc = 0; + + /* + * Do the incoming paperwork + */ + i2o_dev = SCpnt->device->hostdata; + + SCpnt->scsi_done = done; + + if (unlikely(!i2o_dev)) { + osm_warn("no I2O device in request\n"); + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + goto exit; + } + c = i2o_dev->iop; + tid = i2o_dev->lct_data.tid; + + osm_debug("qcmd: Tid = %03x\n", tid); + osm_debug("Real scsi messages.\n"); + + /* + * Put together a scsi execscb message + */ + switch (SCpnt->sc_data_direction) { + case PCI_DMA_NONE: + /* DATA NO XFER */ + sgl_offset = SGL_OFFSET_0; + break; + + case PCI_DMA_TODEVICE: + /* DATA OUT (iop-->dev) */ + scsi_flags |= 0x80000000; + sgl_offset = SGL_OFFSET_10; + break; + + case PCI_DMA_FROMDEVICE: + /* DATA IN (iop<--dev) */ + scsi_flags |= 0x40000000; + sgl_offset = SGL_OFFSET_10; + break; + + default: + /* Unknown - kill the command */ + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + goto exit; + } + + /* + * Obtain an I2O message. If there are none free then + * throw it back to the scsi layer + */ + + msg = i2o_msg_get(c); + if (IS_ERR(msg)) { + rc = SCSI_MLQUEUE_HOST_BUSY; + goto exit; + } + + mptr = &msg->body[0]; + +#if 0 /* this code can't work */ +#ifdef CONFIG_I2O_EXT_ADAPTEC + if (c->adaptec) { + u32 adpt_flags = 0; + + if (SCpnt->sc_request && SCpnt->sc_request->upper_private_data) { + i2o_sg_io_hdr_t __user *usr_ptr = + ((Sg_request *) (SCpnt->sc_request-> + upper_private_data))->header. + usr_ptr; + + if (usr_ptr) + get_user(adpt_flags, &usr_ptr->flags); + } + + switch (i2o_dev->lct_data.class_id) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + /* interpret flag has to be set for executive */ + adpt_flags ^= I2O_DPT_SG_FLAG_INTERPRET; + break; + + default: + break; + } + + /* + * for Adaptec controllers we use the PRIVATE command, because + * the normal SCSI EXEC doesn't support all SCSI commands on + * all controllers (for example READ CAPACITY). + */ + if (sgl_offset == SGL_OFFSET_10) + sgl_offset = SGL_OFFSET_12; + cmd = I2O_CMD_PRIVATE << 24; + *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); + *mptr++ = cpu_to_le32(adpt_flags | tid); + } +#endif +#endif + + msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); + msg->u.s.icntxt = cpu_to_le32(i2o_scsi_driver.context); + + /* We want the SCSI control block back */ + msg->u.s.tcntxt = cpu_to_le32(i2o_cntxt_list_add(c, SCpnt)); + + /* LSI_920_PCI_QUIRK + * + * Intermittant observations of msg frame word data corruption + * observed on msg[4] after: + * WRITE, READ-MODIFY-WRITE + * operations. 19990606 -sralston + * + * (Hence we build this word via tag. Its good practice anyway + * we don't want fetches over PCI needlessly) + */ + + /* Attach tags to the devices */ + /* FIXME: implement + if(SCpnt->device->tagged_supported) { + if(SCpnt->tag == HEAD_OF_QUEUE_TAG) + scsi_flags |= 0x01000000; + else if(SCpnt->tag == ORDERED_QUEUE_TAG) + scsi_flags |= 0x01800000; + } + */ + + *mptr++ = cpu_to_le32(scsi_flags | SCpnt->cmd_len); + + /* Write SCSI command into the message - always 16 byte block */ + memcpy(mptr, SCpnt->cmnd, 16); + mptr += 4; + + if (sgl_offset != SGL_OFFSET_0) { + /* write size of data addressed by SGL */ + *mptr++ = cpu_to_le32(scsi_bufflen(SCpnt)); + + /* Now fill in the SGList and command */ + + if (scsi_sg_count(SCpnt)) { + if (!i2o_dma_map_sg(c, scsi_sglist(SCpnt), + scsi_sg_count(SCpnt), + SCpnt->sc_data_direction, &mptr)) + goto nomem; + } + } + + /* Stick the headers on */ + msg->u.head[0] = + cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset); + + /* Queue the message */ + i2o_msg_post(c, msg); + + osm_debug("Issued %0x%p\n", SCpnt); + + return 0; + + nomem: + rc = -ENOMEM; + i2o_msg_nop(c, msg); + + exit: + return rc; +} + +static DEF_SCSI_QCMD(i2o_scsi_queuecommand) + +/** + * i2o_scsi_abort - abort a running command + * @SCpnt: command to abort + * + * Ask the I2O controller to abort a command. This is an asynchrnous + * process and our callback handler will see the command complete with an + * aborted message if it succeeds. + * + * Returns 0 if the command is successfully aborted or negative error code + * on failure. + */ +static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) +{ + struct i2o_device *i2o_dev; + struct i2o_controller *c; + struct i2o_message *msg; + int tid; + int status = FAILED; + + osm_warn("Aborting command block.\n"); + + i2o_dev = SCpnt->device->hostdata; + c = i2o_dev->iop; + tid = i2o_dev->lct_data.tid; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return SCSI_MLQUEUE_HOST_BUSY; + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid); + msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt)); + + if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT)) + status = SUCCESS; + + return status; +} + +/** + * i2o_scsi_bios_param - Invent disk geometry + * @sdev: scsi device + * @dev: block layer device + * @capacity: size in sectors + * @ip: geometry array + * + * This is anyone's guess quite frankly. We use the same rules everyone + * else appears to and hope. It seems to work. + */ + +static int i2o_scsi_bios_param(struct scsi_device *sdev, + struct block_device *dev, sector_t capacity, + int *ip) +{ + int size; + + size = capacity; + ip[0] = 64; /* heads */ + ip[1] = 32; /* sectors */ + if ((ip[2] = size >> 11) > 1024) { /* cylinders, test for big disk */ + ip[0] = 255; /* heads */ + ip[1] = 63; /* sectors */ + ip[2] = size / (255 * 63); /* cylinders */ + } + return 0; +} + +static struct scsi_host_template i2o_scsi_host_template = { + .proc_name = OSM_NAME, + .name = OSM_DESCRIPTION, + .info = i2o_scsi_info, + .queuecommand = i2o_scsi_queuecommand, + .eh_abort_handler = i2o_scsi_abort, + .bios_param = i2o_scsi_bios_param, + .can_queue = I2O_SCSI_CAN_QUEUE, + .sg_tablesize = 8, + .cmd_per_lun = 6, + .use_clustering = ENABLE_CLUSTERING, +}; + +/** + * i2o_scsi_init - SCSI OSM initialization function + * + * Register SCSI OSM into I2O core. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_scsi_init(void) +{ + int rc; + + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + /* Register SCSI OSM into I2O core */ + rc = i2o_driver_register(&i2o_scsi_driver); + if (rc) { + osm_err("Could not register SCSI driver\n"); + return rc; + } + + return 0; +}; + +/** + * i2o_scsi_exit - SCSI OSM exit function + * + * Unregisters SCSI OSM from I2O core. + */ +static void __exit i2o_scsi_exit(void) +{ + /* Unregister I2O SCSI OSM from I2O core */ + i2o_driver_unregister(&i2o_scsi_driver); +}; + +MODULE_AUTHOR("Red Hat Software"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +module_init(i2o_scsi_init); +module_exit(i2o_scsi_exit); diff --git a/drivers/staging/i2o/iop.c b/drivers/staging/i2o/iop.c new file mode 100644 index 0000000..52334fc --- /dev/null +++ b/drivers/staging/i2o/iop.c @@ -0,0 +1,1247 @@ +/* + * Functions to handle I2O controllers and I2O message handling + * + * Copyright (C) 1999-2002 Red Hat Software + * + * Written by Alan Cox, Building Number Three Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * A lot of the I2O message side code from this is taken from the + * Red Creek RCPCI45 adapter driver by Red Creek Communications + * + * Fixes/additions: + * Philipp Rumpf + * Juha Sievänen + * Auvo Häkkinen + * Deepak Saxena + * Boji T Kannanthanam + * Alan Cox : + * Ported to Linux 2.5. + * Markus Lidel : + * Minor fixes for 2.6. + */ + +#include +#include "i2o.h" +#include +#include +#include +#include "core.h" + +#define OSM_NAME "i2o" +#define OSM_VERSION "1.325" +#define OSM_DESCRIPTION "I2O subsystem" + +/* global I2O controller list */ +LIST_HEAD(i2o_controllers); + +/* + * global I2O System Table. Contains information about all the IOPs in the + * system. Used to inform IOPs about each others existence. + */ +static struct i2o_dma i2o_systab; + +static int i2o_hrt_get(struct i2o_controller *c); + +/** + * i2o_msg_get_wait - obtain an I2O message from the IOP + * @c: I2O controller + * @wait: how long to wait until timeout + * + * This function waits up to wait seconds for a message slot to be + * available. + * + * On a success the message is returned and the pointer to the message is + * set in msg. The returned message is the physical page frame offset + * address from the read port (see the i2o spec). If no message is + * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. + */ +struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait) +{ + unsigned long timeout = jiffies + wait * HZ; + struct i2o_message *msg; + + while (IS_ERR(msg = i2o_msg_get(c))) { + if (time_after(jiffies, timeout)) { + osm_debug("%s: Timeout waiting for message frame.\n", + c->name); + return ERR_PTR(-ETIMEDOUT); + } + schedule_timeout_uninterruptible(1); + } + + return msg; +}; + +#if BITS_PER_LONG == 64 +/** + * i2o_cntxt_list_add - Append a pointer to context list and return a id + * @c: controller to which the context list belong + * @ptr: pointer to add to the context list + * + * Because the context field in I2O is only 32-bit large, on 64-bit the + * pointer is to large to fit in the context field. The i2o_cntxt_list + * functions therefore map pointers to context fields. + * + * Returns context id > 0 on success or 0 on failure. + */ +u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr) +{ + struct i2o_context_list_element *entry; + unsigned long flags; + + if (!ptr) + osm_err("%s: couldn't add NULL pointer to context list!\n", + c->name); + + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); + if (!entry) { + osm_err("%s: Could not allocate memory for context list element" + "\n", c->name); + return 0; + } + + entry->ptr = ptr; + entry->timestamp = jiffies; + INIT_LIST_HEAD(&entry->list); + + spin_lock_irqsave(&c->context_list_lock, flags); + + if (unlikely(atomic_inc_and_test(&c->context_list_counter))) + atomic_inc(&c->context_list_counter); + + entry->context = atomic_read(&c->context_list_counter); + + list_add(&entry->list, &c->context_list); + + spin_unlock_irqrestore(&c->context_list_lock, flags); + + osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context); + + return entry->context; +}; + +/** + * i2o_cntxt_list_remove - Remove a pointer from the context list + * @c: controller to which the context list belong + * @ptr: pointer which should be removed from the context list + * + * Removes a previously added pointer from the context list and returns + * the matching context id. + * + * Returns context id on success or 0 on failure. + */ +u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr) +{ + struct i2o_context_list_element *entry; + u32 context = 0; + unsigned long flags; + + spin_lock_irqsave(&c->context_list_lock, flags); + list_for_each_entry(entry, &c->context_list, list) + if (entry->ptr == ptr) { + list_del(&entry->list); + context = entry->context; + kfree(entry); + break; + } + spin_unlock_irqrestore(&c->context_list_lock, flags); + + if (!context) + osm_warn("%s: Could not remove nonexistent ptr %p\n", c->name, + ptr); + + osm_debug("%s: remove ptr from context list %d -> %p\n", c->name, + context, ptr); + + return context; +}; + +/** + * i2o_cntxt_list_get - Get a pointer from the context list and remove it + * @c: controller to which the context list belong + * @context: context id to which the pointer belong + * + * Returns pointer to the matching context id on success or NULL on + * failure. + */ +void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) +{ + struct i2o_context_list_element *entry; + unsigned long flags; + void *ptr = NULL; + + spin_lock_irqsave(&c->context_list_lock, flags); + list_for_each_entry(entry, &c->context_list, list) + if (entry->context == context) { + list_del(&entry->list); + ptr = entry->ptr; + kfree(entry); + break; + } + spin_unlock_irqrestore(&c->context_list_lock, flags); + + if (!ptr) + osm_warn("%s: context id %d not found\n", c->name, context); + + osm_debug("%s: get ptr from context list %d -> %p\n", c->name, context, + ptr); + + return ptr; +}; + +/** + * i2o_cntxt_list_get_ptr - Get a context id from the context list + * @c: controller to which the context list belong + * @ptr: pointer to which the context id should be fetched + * + * Returns context id which matches to the pointer on success or 0 on + * failure. + */ +u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr) +{ + struct i2o_context_list_element *entry; + u32 context = 0; + unsigned long flags; + + spin_lock_irqsave(&c->context_list_lock, flags); + list_for_each_entry(entry, &c->context_list, list) + if (entry->ptr == ptr) { + context = entry->context; + break; + } + spin_unlock_irqrestore(&c->context_list_lock, flags); + + if (!context) + osm_warn("%s: Could not find nonexistent ptr %p\n", c->name, + ptr); + + osm_debug("%s: get context id from context list %p -> %d\n", c->name, + ptr, context); + + return context; +}; +#endif + +/** + * i2o_iop_find - Find an I2O controller by id + * @unit: unit number of the I2O controller to search for + * + * Lookup the I2O controller on the controller list. + * + * Returns pointer to the I2O controller on success or NULL if not found. + */ +struct i2o_controller *i2o_find_iop(int unit) +{ + struct i2o_controller *c; + + list_for_each_entry(c, &i2o_controllers, list) { + if (c->unit == unit) + return c; + } + + return NULL; +}; + +/** + * i2o_iop_find_device - Find a I2O device on an I2O controller + * @c: I2O controller where the I2O device hangs on + * @tid: TID of the I2O device to search for + * + * Searches the devices of the I2O controller for a device with TID tid and + * returns it. + * + * Returns a pointer to the I2O device if found, otherwise NULL. + */ +struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid) +{ + struct i2o_device *dev; + + list_for_each_entry(dev, &c->devices, list) + if (dev->lct_data.tid == tid) + return dev; + + return NULL; +}; + +/** + * i2o_quiesce_controller - quiesce controller + * @c: controller + * + * Quiesce an IOP. Causes IOP to make external operation quiescent + * (i2o 'READY' state). Internal operation of the IOP continues normally. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_quiesce(struct i2o_controller *c) +{ + struct i2o_message *msg; + i2o_status_block *sb = c->status_block.virt; + int rc; + + i2o_status_get(c); + + /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */ + if ((sb->iop_state != ADAPTER_STATE_READY) && + (sb->iop_state != ADAPTER_STATE_OPERATIONAL)) + return 0; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | + ADAPTER_TID); + + /* Long timeout needed for quiesce if lots of devices */ + if ((rc = i2o_msg_post_wait(c, msg, 240))) + osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc); + else + osm_debug("%s: Quiesced.\n", c->name); + + i2o_status_get(c); // Entered READY state + + return rc; +}; + +/** + * i2o_iop_enable - move controller from ready to OPERATIONAL + * @c: I2O controller + * + * Enable IOP. This allows the IOP to resume external operations and + * reverses the effect of a quiesce. Returns zero or an error code if + * an error occurs. + */ +static int i2o_iop_enable(struct i2o_controller *c) +{ + struct i2o_message *msg; + i2o_status_block *sb = c->status_block.virt; + int rc; + + i2o_status_get(c); + + /* Enable only allowed on READY state */ + if (sb->iop_state != ADAPTER_STATE_READY) + return -EINVAL; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | + ADAPTER_TID); + + /* How long of a timeout do we need? */ + if ((rc = i2o_msg_post_wait(c, msg, 240))) + osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc); + else + osm_debug("%s: Enabled.\n", c->name); + + i2o_status_get(c); // entered OPERATIONAL state + + return rc; +}; + +/** + * i2o_iop_quiesce_all - Quiesce all I2O controllers on the system + * + * Quiesce all I2O controllers which are connected to the system. + */ +static inline void i2o_iop_quiesce_all(void) +{ + struct i2o_controller *c, *tmp; + + list_for_each_entry_safe(c, tmp, &i2o_controllers, list) { + if (!c->no_quiesce) + i2o_iop_quiesce(c); + } +}; + +/** + * i2o_iop_enable_all - Enables all controllers on the system + * + * Enables all I2O controllers which are connected to the system. + */ +static inline void i2o_iop_enable_all(void) +{ + struct i2o_controller *c, *tmp; + + list_for_each_entry_safe(c, tmp, &i2o_controllers, list) + i2o_iop_enable(c); +}; + +/** + * i2o_clear_controller - Bring I2O controller into HOLD state + * @c: controller + * + * Clear an IOP to HOLD state, ie. terminate external operations, clear all + * input queues and prepare for a system restart. IOP's internal operation + * continues normally and the outbound queue is alive. The IOP is not + * expected to rebuild its LCT. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_clear(struct i2o_controller *c) +{ + struct i2o_message *msg; + int rc; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + /* Quiesce all IOPs first */ + i2o_iop_quiesce_all(); + + msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | + ADAPTER_TID); + + if ((rc = i2o_msg_post_wait(c, msg, 30))) + osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc); + else + osm_debug("%s: Cleared.\n", c->name); + + /* Enable all IOPs */ + i2o_iop_enable_all(); + + return rc; +} + +/** + * i2o_iop_init_outbound_queue - setup the outbound message queue + * @c: I2O controller + * + * Clear and (re)initialize IOP's outbound queue and post the message + * frames to the IOP. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_init_outbound_queue(struct i2o_controller *c) +{ + u32 m; + volatile u8 *status = c->status.virt; + struct i2o_message *msg; + ulong timeout; + int i; + + osm_debug("%s: Initializing Outbound Queue...\n", c->name); + + memset(c->status.virt, 0, 4); + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(PAGE_SIZE); + /* Outbound msg frame size in words and Initcode */ + msg->body[1] = cpu_to_le32(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80); + msg->body[2] = cpu_to_le32(0xd0000004); + msg->body[3] = cpu_to_le32(i2o_dma_low(c->status.phys)); + msg->body[4] = cpu_to_le32(i2o_dma_high(c->status.phys)); + + i2o_msg_post(c, msg); + + timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ; + while (*status <= I2O_CMD_IN_PROGRESS) { + if (time_after(jiffies, timeout)) { + osm_warn("%s: Timeout Initializing\n", c->name); + return -ETIMEDOUT; + } + schedule_timeout_uninterruptible(1); + } + + m = c->out_queue.phys; + + /* Post frames */ + for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) { + i2o_flush_reply(c, m); + udelay(1); /* Promise */ + m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32); + } + + return 0; +} + +/** + * i2o_iop_reset - reset an I2O controller + * @c: controller to reset + * + * Reset the IOP into INIT state and wait until IOP gets into RESET state. + * Terminate all external operations, clear IOP's inbound and outbound + * queues, terminate all DDMs, and reload the IOP's operating environment + * and all local DDMs. The IOP rebuilds its LCT. + */ +static int i2o_iop_reset(struct i2o_controller *c) +{ + volatile u8 *status = c->status.virt; + struct i2o_message *msg; + unsigned long timeout; + i2o_status_block *sb = c->status_block.virt; + int rc = 0; + + osm_debug("%s: Resetting controller\n", c->name); + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + memset(c->status_block.virt, 0, 8); + + /* Quiesce all IOPs first */ + i2o_iop_quiesce_all(); + + msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(0x00000000); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(i2o_dma_low(c->status.phys)); + msg->body[3] = cpu_to_le32(i2o_dma_high(c->status.phys)); + + i2o_msg_post(c, msg); + + /* Wait for a reply */ + timeout = jiffies + I2O_TIMEOUT_RESET * HZ; + while (!*status) { + if (time_after(jiffies, timeout)) + break; + + schedule_timeout_uninterruptible(1); + } + + switch (*status) { + case I2O_CMD_REJECTED: + osm_warn("%s: IOP reset rejected\n", c->name); + rc = -EPERM; + break; + + case I2O_CMD_IN_PROGRESS: + /* + * Once the reset is sent, the IOP goes into the INIT state + * which is indeterminate. We need to wait until the IOP has + * rebooted before we can let the system talk to it. We read + * the inbound Free_List until a message is available. If we + * can't read one in the given amount of time, we assume the + * IOP could not reboot properly. + */ + osm_debug("%s: Reset in progress, waiting for reboot...\n", + c->name); + + while (IS_ERR(msg = i2o_msg_get_wait(c, I2O_TIMEOUT_RESET))) { + if (time_after(jiffies, timeout)) { + osm_err("%s: IOP reset timeout.\n", c->name); + rc = PTR_ERR(msg); + goto exit; + } + schedule_timeout_uninterruptible(1); + } + i2o_msg_nop(c, msg); + + /* from here all quiesce commands are safe */ + c->no_quiesce = 0; + + /* verify if controller is in state RESET */ + i2o_status_get(c); + + if (!c->promise && (sb->iop_state != ADAPTER_STATE_RESET)) + osm_warn("%s: reset completed, but adapter not in RESET" + " state.\n", c->name); + else + osm_debug("%s: reset completed.\n", c->name); + + break; + + default: + osm_err("%s: IOP reset timeout.\n", c->name); + rc = -ETIMEDOUT; + break; + } + + exit: + /* Enable all IOPs */ + i2o_iop_enable_all(); + + return rc; +}; + +/** + * i2o_iop_activate - Bring controller up to HOLD + * @c: controller + * + * This function brings an I2O controller into HOLD state. The adapter + * is reset if necessary and then the queues and resource table are read. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_activate(struct i2o_controller *c) +{ + i2o_status_block *sb = c->status_block.virt; + int rc; + int state; + + /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */ + /* In READY state, Get status */ + + rc = i2o_status_get(c); + if (rc) { + osm_info("%s: Unable to obtain status, attempting a reset.\n", + c->name); + rc = i2o_iop_reset(c); + if (rc) + return rc; + } + + if (sb->i2o_version > I2OVER15) { + osm_err("%s: Not running version 1.5 of the I2O Specification." + "\n", c->name); + return -ENODEV; + } + + switch (sb->iop_state) { + case ADAPTER_STATE_FAULTED: + osm_err("%s: hardware fault\n", c->name); + return -EFAULT; + + case ADAPTER_STATE_READY: + case ADAPTER_STATE_OPERATIONAL: + case ADAPTER_STATE_HOLD: + case ADAPTER_STATE_FAILED: + osm_debug("%s: already running, trying to reset...\n", c->name); + rc = i2o_iop_reset(c); + if (rc) + return rc; + } + + /* preserve state */ + state = sb->iop_state; + + rc = i2o_iop_init_outbound_queue(c); + if (rc) + return rc; + + /* if adapter was not in RESET state clear now */ + if (state != ADAPTER_STATE_RESET) + i2o_iop_clear(c); + + i2o_status_get(c); + + if (sb->iop_state != ADAPTER_STATE_HOLD) { + osm_err("%s: failed to bring IOP into HOLD state\n", c->name); + return -EIO; + } + + return i2o_hrt_get(c); +}; + +static void i2o_res_alloc(struct i2o_controller *c, unsigned long flags) +{ + i2o_status_block *sb = c->status_block.virt; + struct resource *res = &c->mem_resource; + resource_size_t size, align; + int err; + + res->name = c->pdev->bus->name; + res->flags = flags; + res->start = 0; + res->end = 0; + osm_info("%s: requires private memory resources.\n", c->name); + + if (flags & IORESOURCE_MEM) { + size = sb->desired_mem_size; + align = 1 << 20; /* unspecified, use 1Mb and play safe */ + } else { + size = sb->desired_io_size; + align = 1 << 12; /* unspecified, use 4Kb and play safe */ + } + + err = pci_bus_alloc_resource(c->pdev->bus, res, size, align, 0, 0, + NULL, NULL); + if (err < 0) + return; + + if (flags & IORESOURCE_MEM) { + c->mem_alloc = 1; + sb->current_mem_size = resource_size(res); + sb->current_mem_base = res->start; + } else if (flags & IORESOURCE_IO) { + c->io_alloc = 1; + sb->current_io_size = resource_size(res); + sb->current_io_base = res->start; + } + osm_info("%s: allocated PCI space %pR\n", c->name, res); +} + +/** + * i2o_iop_systab_set - Set the I2O System Table of the specified IOP + * @c: I2O controller to which the system table should be send + * + * Before the systab could be set i2o_systab_build() must be called. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_systab_set(struct i2o_controller *c) +{ + struct i2o_message *msg; + i2o_status_block *sb = c->status_block.virt; + struct device *dev = &c->pdev->dev; + int rc; + + if (sb->current_mem_size < sb->desired_mem_size) + i2o_res_alloc(c, IORESOURCE_MEM); + + if (sb->current_io_size < sb->desired_io_size) + i2o_res_alloc(c, IORESOURCE_IO); + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len, + PCI_DMA_TODEVICE); + if (!i2o_systab.phys) { + i2o_msg_nop(c, msg); + return -ENOMEM; + } + + msg->u.head[0] = cpu_to_le32(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | + ADAPTER_TID); + + /* + * Provide three SGL-elements: + * System table (SysTab), Private memory space declaration and + * Private i/o space declaration + */ + + msg->body[0] = cpu_to_le32(c->unit + 2); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(0x54000000 | i2o_systab.len); + msg->body[3] = cpu_to_le32(i2o_systab.phys); + msg->body[4] = cpu_to_le32(0x54000000 | sb->current_mem_size); + msg->body[5] = cpu_to_le32(sb->current_mem_base); + msg->body[6] = cpu_to_le32(0xd4000000 | sb->current_io_size); + msg->body[6] = cpu_to_le32(sb->current_io_base); + + rc = i2o_msg_post_wait(c, msg, 120); + + dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len, + PCI_DMA_TODEVICE); + + if (rc < 0) + osm_err("%s: Unable to set SysTab (status=%#x).\n", c->name, + -rc); + else + osm_debug("%s: SysTab set.\n", c->name); + + return rc; +} + +/** + * i2o_iop_online - Bring a controller online into OPERATIONAL state. + * @c: I2O controller + * + * Send the system table and enable the I2O controller. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_iop_online(struct i2o_controller *c) +{ + int rc; + + rc = i2o_iop_systab_set(c); + if (rc) + return rc; + + /* In READY state */ + osm_debug("%s: Attempting to enable...\n", c->name); + rc = i2o_iop_enable(c); + if (rc) + return rc; + + return 0; +}; + +/** + * i2o_iop_remove - Remove the I2O controller from the I2O core + * @c: I2O controller + * + * Remove the I2O controller from the I2O core. If devices are attached to + * the controller remove these also and finally reset the controller. + */ +void i2o_iop_remove(struct i2o_controller *c) +{ + struct i2o_device *dev, *tmp; + + osm_debug("%s: deleting controller\n", c->name); + + i2o_driver_notify_controller_remove_all(c); + + list_del(&c->list); + + list_for_each_entry_safe(dev, tmp, &c->devices, list) + i2o_device_remove(dev); + + device_del(&c->device); + + /* Ask the IOP to switch to RESET state */ + i2o_iop_reset(c); +} + +/** + * i2o_systab_build - Build system table + * + * The system table contains information about all the IOPs in the system + * (duh) and is used by the Executives on the IOPs to establish peer2peer + * connections. We're not supporting peer2peer at the moment, but this + * will be needed down the road for things like lan2lan forwarding. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_systab_build(void) +{ + struct i2o_controller *c, *tmp; + int num_controllers = 0; + u32 change_ind = 0; + int count = 0; + struct i2o_sys_tbl *systab = i2o_systab.virt; + + list_for_each_entry_safe(c, tmp, &i2o_controllers, list) + num_controllers++; + + if (systab) { + change_ind = systab->change_ind; + kfree(i2o_systab.virt); + } + + /* Header + IOPs */ + i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers * + sizeof(struct i2o_sys_tbl_entry); + + systab = i2o_systab.virt = kzalloc(i2o_systab.len, GFP_KERNEL); + if (!systab) { + osm_err("unable to allocate memory for System Table\n"); + return -ENOMEM; + } + + systab->version = I2OVERSION; + systab->change_ind = change_ind + 1; + + list_for_each_entry_safe(c, tmp, &i2o_controllers, list) { + i2o_status_block *sb; + + if (count >= num_controllers) { + osm_err("controller added while building system table" + "\n"); + break; + } + + sb = c->status_block.virt; + + /* + * Get updated IOP state so we have the latest information + * + * We should delete the controller at this point if it + * doesn't respond since if it's not on the system table + * it is techninically not part of the I2O subsystem... + */ + if (unlikely(i2o_status_get(c))) { + osm_err("%s: Deleting b/c could not get status while " + "attempting to build system table\n", c->name); + i2o_iop_remove(c); + continue; // try the next one + } + + systab->iops[count].org_id = sb->org_id; + systab->iops[count].iop_id = c->unit + 2; + systab->iops[count].seg_num = 0; + systab->iops[count].i2o_version = sb->i2o_version; + systab->iops[count].iop_state = sb->iop_state; + systab->iops[count].msg_type = sb->msg_type; + systab->iops[count].frame_size = sb->inbound_frame_size; + systab->iops[count].last_changed = change_ind; + systab->iops[count].iop_capabilities = sb->iop_capabilities; + systab->iops[count].inbound_low = + i2o_dma_low(c->base.phys + I2O_IN_PORT); + systab->iops[count].inbound_high = + i2o_dma_high(c->base.phys + I2O_IN_PORT); + + count++; + } + + systab->num_entries = count; + + return 0; +}; + +/** + * i2o_parse_hrt - Parse the hardware resource table. + * @c: I2O controller + * + * We don't do anything with it except dumping it (in debug mode). + * + * Returns 0. + */ +static int i2o_parse_hrt(struct i2o_controller *c) +{ + i2o_dump_hrt(c); + return 0; +}; + +/** + * i2o_status_get - Get the status block from the I2O controller + * @c: I2O controller + * + * Issue a status query on the controller. This updates the attached + * status block. The status block could then be accessed through + * c->status_block. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_status_get(struct i2o_controller *c) +{ + struct i2o_message *msg; + volatile u8 *status_block; + unsigned long timeout; + + status_block = (u8 *) c->status_block.virt; + memset(c->status_block.virt, 0, sizeof(i2o_status_block)); + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + msg->u.s.tcntxt = cpu_to_le32(0x00000000); + msg->body[0] = cpu_to_le32(0x00000000); + msg->body[1] = cpu_to_le32(0x00000000); + msg->body[2] = cpu_to_le32(i2o_dma_low(c->status_block.phys)); + msg->body[3] = cpu_to_le32(i2o_dma_high(c->status_block.phys)); + msg->body[4] = cpu_to_le32(sizeof(i2o_status_block)); /* always 88 bytes */ + + i2o_msg_post(c, msg); + + /* Wait for a reply */ + timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ; + while (status_block[87] != 0xFF) { + if (time_after(jiffies, timeout)) { + osm_err("%s: Get status timeout.\n", c->name); + return -ETIMEDOUT; + } + + schedule_timeout_uninterruptible(1); + } + +#ifdef DEBUG + i2o_debug_state(c); +#endif + + return 0; +} + +/* + * i2o_hrt_get - Get the Hardware Resource Table from the I2O controller + * @c: I2O controller from which the HRT should be fetched + * + * The HRT contains information about possible hidden devices but is + * mostly useless to us. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_hrt_get(struct i2o_controller *c) +{ + int rc; + int i; + i2o_hrt *hrt = c->hrt.virt; + u32 size = sizeof(i2o_hrt); + struct device *dev = &c->pdev->dev; + + for (i = 0; i < I2O_HRT_GET_TRIES; i++) { + struct i2o_message *msg; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(SIX_WORD_MSG_SIZE | SGL_OFFSET_4); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | + ADAPTER_TID); + msg->body[0] = cpu_to_le32(0xd0000000 | c->hrt.len); + msg->body[1] = cpu_to_le32(c->hrt.phys); + + rc = i2o_msg_post_wait_mem(c, msg, 20, &c->hrt); + + if (rc < 0) { + osm_err("%s: Unable to get HRT (status=%#x)\n", c->name, + -rc); + return rc; + } + + size = hrt->num_entries * hrt->entry_len << 2; + if (size > c->hrt.len) { + if (i2o_dma_realloc(dev, &c->hrt, size)) + return -ENOMEM; + else + hrt = c->hrt.virt; + } else + return i2o_parse_hrt(c); + } + + osm_err("%s: Unable to get HRT after %d tries, giving up\n", c->name, + I2O_HRT_GET_TRIES); + + return -EBUSY; +} + +/** + * i2o_iop_release - release the memory for a I2O controller + * @dev: I2O controller which should be released + * + * Release the allocated memory. This function is called if refcount of + * device reaches 0 automatically. + */ +static void i2o_iop_release(struct device *dev) +{ + struct i2o_controller *c = to_i2o_controller(dev); + + i2o_iop_free(c); +}; + +/** + * i2o_iop_alloc - Allocate and initialize a i2o_controller struct + * + * Allocate the necessary memory for a i2o_controller struct and + * initialize the lists and message mempool. + * + * Returns a pointer to the I2O controller or a negative error code on + * failure. + */ +struct i2o_controller *i2o_iop_alloc(void) +{ + static int unit = 0; /* 0 and 1 are NULL IOP and Local Host */ + struct i2o_controller *c; + char poolname[32]; + + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) { + osm_err("i2o: Insufficient memory to allocate a I2O controller." + "\n"); + return ERR_PTR(-ENOMEM); + } + + c->unit = unit++; + sprintf(c->name, "iop%d", c->unit); + + snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name); + if (i2o_pool_alloc + (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32), + I2O_MSG_INPOOL_MIN)) { + kfree(c); + return ERR_PTR(-ENOMEM); + }; + + INIT_LIST_HEAD(&c->devices); + spin_lock_init(&c->lock); + mutex_init(&c->lct_lock); + + device_initialize(&c->device); + + c->device.release = &i2o_iop_release; + + dev_set_name(&c->device, "iop%d", c->unit); + +#if BITS_PER_LONG == 64 + spin_lock_init(&c->context_list_lock); + atomic_set(&c->context_list_counter, 0); + INIT_LIST_HEAD(&c->context_list); +#endif + + return c; +}; + +/** + * i2o_iop_add - Initialize the I2O controller and add him to the I2O core + * @c: controller + * + * Initialize the I2O controller and if no error occurs add him to the I2O + * core. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_iop_add(struct i2o_controller *c) +{ + int rc; + + if ((rc = device_add(&c->device))) { + osm_err("%s: could not add controller\n", c->name); + goto iop_reset; + } + + osm_info("%s: Activating I2O controller...\n", c->name); + osm_info("%s: This may take a few minutes if there are many devices\n", + c->name); + + if ((rc = i2o_iop_activate(c))) { + osm_err("%s: could not activate controller\n", c->name); + goto device_del; + } + + osm_debug("%s: building sys table...\n", c->name); + + if ((rc = i2o_systab_build())) + goto device_del; + + osm_debug("%s: online controller...\n", c->name); + + if ((rc = i2o_iop_online(c))) + goto device_del; + + osm_debug("%s: getting LCT...\n", c->name); + + if ((rc = i2o_exec_lct_get(c))) + goto device_del; + + list_add(&c->list, &i2o_controllers); + + i2o_driver_notify_controller_add_all(c); + + osm_info("%s: Controller added\n", c->name); + + return 0; + + device_del: + device_del(&c->device); + + iop_reset: + i2o_iop_reset(c); + + return rc; +}; + +/** + * i2o_event_register - Turn on/off event notification for a I2O device + * @dev: I2O device which should receive the event registration request + * @drv: driver which want to get notified + * @tcntxt: transaction context to use with this notifier + * @evt_mask: mask of events + * + * Create and posts an event registration message to the task. No reply + * is waited for, or expected. If you do not want further notifications, + * call the i2o_event_register again with a evt_mask of 0. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv, + int tcntxt, u32 evt_mask) +{ + struct i2o_controller *c = dev->iop; + struct i2o_message *msg; + + msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + if (IS_ERR(msg)) + return PTR_ERR(msg); + + msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); + msg->u.head[1] = + cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev-> + lct_data.tid); + msg->u.s.icntxt = cpu_to_le32(drv->context); + msg->u.s.tcntxt = cpu_to_le32(tcntxt); + msg->body[0] = cpu_to_le32(evt_mask); + + i2o_msg_post(c, msg); + + return 0; +}; + +/** + * i2o_iop_init - I2O main initialization function + * + * Initialize the I2O drivers (OSM) functions, register the Executive OSM, + * initialize the I2O PCI part and finally initialize I2O device stuff. + * + * Returns 0 on success or negative error code on failure. + */ +static int __init i2o_iop_init(void) +{ + int rc = 0; + + printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); + + if ((rc = i2o_driver_init())) + goto exit; + + if ((rc = i2o_exec_init())) + goto driver_exit; + + if ((rc = i2o_pci_init())) + goto exec_exit; + + return 0; + + exec_exit: + i2o_exec_exit(); + + driver_exit: + i2o_driver_exit(); + + exit: + return rc; +} + +/** + * i2o_iop_exit - I2O main exit function + * + * Removes I2O controllers from PCI subsystem and shut down OSMs. + */ +static void __exit i2o_iop_exit(void) +{ + i2o_pci_exit(); + i2o_exec_exit(); + i2o_driver_exit(); +}; + +module_init(i2o_iop_init); +module_exit(i2o_iop_exit); + +MODULE_AUTHOR("Red Hat Software"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION(OSM_DESCRIPTION); +MODULE_VERSION(OSM_VERSION); + +#if BITS_PER_LONG == 64 +EXPORT_SYMBOL(i2o_cntxt_list_add); +EXPORT_SYMBOL(i2o_cntxt_list_get); +EXPORT_SYMBOL(i2o_cntxt_list_remove); +EXPORT_SYMBOL(i2o_cntxt_list_get_ptr); +#endif +EXPORT_SYMBOL(i2o_msg_get_wait); +EXPORT_SYMBOL(i2o_find_iop); +EXPORT_SYMBOL(i2o_iop_find_device); +EXPORT_SYMBOL(i2o_event_register); +EXPORT_SYMBOL(i2o_status_get); +EXPORT_SYMBOL(i2o_controllers); diff --git a/drivers/staging/i2o/memory.c b/drivers/staging/i2o/memory.c new file mode 100644 index 0000000..8f9509d --- /dev/null +++ b/drivers/staging/i2o/memory.c @@ -0,0 +1,313 @@ +/* + * Functions to handle I2O memory + * + * Pulled from the inlines in i2o headers and uninlined + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include "i2o.h" +#include +#include +#include +#include "core.h" + +/* Protects our 32/64bit mask switching */ +static DEFINE_MUTEX(mem_lock); + +/** + * i2o_sg_tablesize - Calculate the maximum number of elements in a SGL + * @c: I2O controller for which the calculation should be done + * @body_size: maximum body size used for message in 32-bit words. + * + * Return the maximum number of SG elements in a SG list. + */ +u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size) +{ + i2o_status_block *sb = c->status_block.virt; + u16 sg_count = + (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) - + body_size; + + if (c->pae_support) { + /* + * for 64-bit a SG attribute element must be added and each + * SG element needs 12 bytes instead of 8. + */ + sg_count -= 2; + sg_count /= 3; + } else + sg_count /= 2; + + if (c->short_req && (sg_count > 8)) + sg_count = 8; + + return sg_count; +} +EXPORT_SYMBOL_GPL(i2o_sg_tablesize); + + +/** + * i2o_dma_map_single - Map pointer to controller and fill in I2O message. + * @c: I2O controller + * @ptr: pointer to the data which should be mapped + * @size: size of data in bytes + * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE + * @sg_ptr: pointer to the SG list inside the I2O message + * + * This function does all necessary DMA handling and also writes the I2O + * SGL elements into the I2O message. For details on DMA handling see also + * dma_map_single(). The pointer sg_ptr will only be set to the end of the + * SG list if the allocation was successful. + * + * Returns DMA address which must be checked for failures using + * dma_mapping_error(). + */ +dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr, + size_t size, + enum dma_data_direction direction, + u32 ** sg_ptr) +{ + u32 sg_flags; + u32 *mptr = *sg_ptr; + dma_addr_t dma_addr; + + switch (direction) { + case DMA_TO_DEVICE: + sg_flags = 0xd4000000; + break; + case DMA_FROM_DEVICE: + sg_flags = 0xd0000000; + break; + default: + return 0; + } + + dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction); + if (!dma_mapping_error(&c->pdev->dev, dma_addr)) { +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) { + *mptr++ = cpu_to_le32(0x7C020002); + *mptr++ = cpu_to_le32(PAGE_SIZE); + } +#endif + + *mptr++ = cpu_to_le32(sg_flags | size); + *mptr++ = cpu_to_le32(i2o_dma_low(dma_addr)); +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) + *mptr++ = cpu_to_le32(i2o_dma_high(dma_addr)); +#endif + *sg_ptr = mptr; + } + return dma_addr; +} +EXPORT_SYMBOL_GPL(i2o_dma_map_single); + +/** + * i2o_dma_map_sg - Map a SG List to controller and fill in I2O message. + * @c: I2O controller + * @sg: SG list to be mapped + * @sg_count: number of elements in the SG list + * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE + * @sg_ptr: pointer to the SG list inside the I2O message + * + * This function does all necessary DMA handling and also writes the I2O + * SGL elements into the I2O message. For details on DMA handling see also + * dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG + * list if the allocation was successful. + * + * Returns 0 on failure or 1 on success. + */ +int i2o_dma_map_sg(struct i2o_controller *c, struct scatterlist *sg, + int sg_count, enum dma_data_direction direction, u32 ** sg_ptr) +{ + u32 sg_flags; + u32 *mptr = *sg_ptr; + + switch (direction) { + case DMA_TO_DEVICE: + sg_flags = 0x14000000; + break; + case DMA_FROM_DEVICE: + sg_flags = 0x10000000; + break; + default: + return 0; + } + + sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction); + if (!sg_count) + return 0; + +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) { + *mptr++ = cpu_to_le32(0x7C020002); + *mptr++ = cpu_to_le32(PAGE_SIZE); + } +#endif + + while (sg_count-- > 0) { + if (!sg_count) + sg_flags |= 0xC0000000; + *mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg)); + *mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg))); +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) + *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg))); +#endif + sg = sg_next(sg); + } + *sg_ptr = mptr; + + return 1; +} +EXPORT_SYMBOL_GPL(i2o_dma_map_sg); + +/** + * i2o_dma_alloc - Allocate DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: i2o_dma struct which should get the DMA buffer + * @len: length of the new DMA memory + * + * Allocate a coherent DMA memory and write the pointers into addr. + * + * Returns 0 on success or -ENOMEM on failure. + */ +int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len) +{ + struct pci_dev *pdev = to_pci_dev(dev); + int dma_64 = 0; + + mutex_lock(&mem_lock); + if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_BIT_MASK(64))) { + dma_64 = 1; + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + mutex_unlock(&mem_lock); + return -ENOMEM; + } + } + + addr->virt = dma_alloc_coherent(dev, len, &addr->phys, GFP_KERNEL); + + if ((sizeof(dma_addr_t) > 4) && dma_64) + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) + printk(KERN_WARNING "i2o: unable to set 64-bit DMA"); + mutex_unlock(&mem_lock); + + if (!addr->virt) + return -ENOMEM; + + memset(addr->virt, 0, len); + addr->len = len; + + return 0; +} +EXPORT_SYMBOL_GPL(i2o_dma_alloc); + + +/** + * i2o_dma_free - Free DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: i2o_dma struct which contains the DMA buffer + * + * Free a coherent DMA memory and set virtual address of addr to NULL. + */ +void i2o_dma_free(struct device *dev, struct i2o_dma *addr) +{ + if (addr->virt) { + if (addr->phys) + dma_free_coherent(dev, addr->len, addr->virt, + addr->phys); + else + kfree(addr->virt); + addr->virt = NULL; + } +} +EXPORT_SYMBOL_GPL(i2o_dma_free); + + +/** + * i2o_dma_realloc - Realloc DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: pointer to a i2o_dma struct DMA buffer + * @len: new length of memory + * + * If there was something allocated in the addr, free it first. If len > 0 + * than try to allocate it and write the addresses back to the addr + * structure. If len == 0 set the virtual address to NULL. + * + * Returns the 0 on success or negative error code on failure. + */ +int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len) +{ + i2o_dma_free(dev, addr); + + if (len) + return i2o_dma_alloc(dev, addr, len); + + return 0; +} +EXPORT_SYMBOL_GPL(i2o_dma_realloc); + +/* + * i2o_pool_alloc - Allocate an slab cache and mempool + * @mempool: pointer to struct i2o_pool to write data into. + * @name: name which is used to identify cache + * @size: size of each object + * @min_nr: minimum number of objects + * + * First allocates a slab cache with name and size. Then allocates a + * mempool which uses the slab cache for allocation and freeing. + * + * Returns 0 on success or negative error code on failure. + */ +int i2o_pool_alloc(struct i2o_pool *pool, const char *name, + size_t size, int min_nr) +{ + pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL); + if (!pool->name) + goto exit; + strcpy(pool->name, name); + + pool->slab = + kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL); + if (!pool->slab) + goto free_name; + + pool->mempool = mempool_create_slab_pool(min_nr, pool->slab); + if (!pool->mempool) + goto free_slab; + + return 0; + +free_slab: + kmem_cache_destroy(pool->slab); + +free_name: + kfree(pool->name); + +exit: + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(i2o_pool_alloc); + +/* + * i2o_pool_free - Free slab cache and mempool again + * @mempool: pointer to struct i2o_pool which should be freed + * + * Note that you have to return all objects to the mempool again before + * calling i2o_pool_free(). + */ +void i2o_pool_free(struct i2o_pool *pool) +{ + mempool_destroy(pool->mempool); + kmem_cache_destroy(pool->slab); + kfree(pool->name); +}; +EXPORT_SYMBOL_GPL(i2o_pool_free); diff --git a/drivers/staging/i2o/pci.c b/drivers/staging/i2o/pci.c new file mode 100644 index 0000000..b3b8a61 --- /dev/null +++ b/drivers/staging/i2o/pci.c @@ -0,0 +1,497 @@ +/* + * PCI handling of I2O controller + * + * Copyright (C) 1999-2002 Red Hat Software + * + * Written by Alan Cox, Building Number Three Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * A lot of the I2O message side code from this is taken from the Red + * Creek RCPCI45 adapter driver by Red Creek Communications + * + * Fixes/additions: + * Philipp Rumpf + * Juha Sievänen + * Auvo Häkkinen + * Deepak Saxena + * Boji T Kannanthanam + * Alan Cox : + * Ported to Linux 2.5. + * Markus Lidel : + * Minor fixes for 2.6. + * Markus Lidel : + * Support for sysfs included. + */ + +#include +#include +#include +#include "i2o.h" +#include +#include "core.h" + +#define OSM_DESCRIPTION "I2O-subsystem" + +/* PCI device id table for all I2O controllers */ +static struct pci_device_id i2o_pci_ids[] = { + {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, + {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)}, + {.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962, + .subvendor = PCI_VENDOR_ID_PROMISE,.subdevice = PCI_ANY_ID}, + {0} +}; + +/** + * i2o_pci_free - Frees the DMA memory for the I2O controller + * @c: I2O controller to free + * + * Remove all allocated DMA memory and unmap memory IO regions. If MTRR + * is enabled, also remove it again. + */ +static void i2o_pci_free(struct i2o_controller *c) +{ + struct device *dev; + + dev = &c->pdev->dev; + + i2o_dma_free(dev, &c->out_queue); + i2o_dma_free(dev, &c->status_block); + kfree(c->lct); + i2o_dma_free(dev, &c->dlct); + i2o_dma_free(dev, &c->hrt); + i2o_dma_free(dev, &c->status); + + if (c->raptor && c->in_queue.virt) + iounmap(c->in_queue.virt); + + if (c->base.virt) + iounmap(c->base.virt); + + pci_release_regions(c->pdev); +} + +/** + * i2o_pci_alloc - Allocate DMA memory, map IO memory for I2O controller + * @c: I2O controller + * + * Allocate DMA memory for a PCI (or in theory AGP) I2O controller. All + * IO mappings are also done here. If MTRR is enabled, also do add memory + * regions here. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_pci_alloc(struct i2o_controller *c) +{ + struct pci_dev *pdev = c->pdev; + struct device *dev = &pdev->dev; + int i; + + if (pci_request_regions(pdev, OSM_DESCRIPTION)) { + printk(KERN_ERR "%s: device already claimed\n", c->name); + return -ENODEV; + } + + for (i = 0; i < 6; i++) { + /* Skip I/O spaces */ + if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) { + if (!c->base.phys) { + c->base.phys = pci_resource_start(pdev, i); + c->base.len = pci_resource_len(pdev, i); + + /* + * If we know what card it is, set the size + * correctly. Code is taken from dpt_i2o.c + */ + if (pdev->device == 0xa501) { + if (pdev->subsystem_device >= 0xc032 && + pdev->subsystem_device <= 0xc03b) { + if (c->base.len > 0x400000) + c->base.len = 0x400000; + } else { + if (c->base.len > 0x100000) + c->base.len = 0x100000; + } + } + if (!c->raptor) + break; + } else { + c->in_queue.phys = pci_resource_start(pdev, i); + c->in_queue.len = pci_resource_len(pdev, i); + break; + } + } + } + + if (i == 6) { + printk(KERN_ERR "%s: I2O controller has no memory regions" + " defined.\n", c->name); + i2o_pci_free(c); + return -EINVAL; + } + + /* Map the I2O controller */ + if (c->raptor) { + printk(KERN_INFO "%s: PCI I2O controller\n", c->name); + printk(KERN_INFO " BAR0 at 0x%08lX size=%ld\n", + (unsigned long)c->base.phys, (unsigned long)c->base.len); + printk(KERN_INFO " BAR1 at 0x%08lX size=%ld\n", + (unsigned long)c->in_queue.phys, + (unsigned long)c->in_queue.len); + } else + printk(KERN_INFO "%s: PCI I2O controller at %08lX size=%ld\n", + c->name, (unsigned long)c->base.phys, + (unsigned long)c->base.len); + + c->base.virt = ioremap_nocache(c->base.phys, c->base.len); + if (!c->base.virt) { + printk(KERN_ERR "%s: Unable to map controller.\n", c->name); + i2o_pci_free(c); + return -ENOMEM; + } + + if (c->raptor) { + c->in_queue.virt = + ioremap_nocache(c->in_queue.phys, c->in_queue.len); + if (!c->in_queue.virt) { + printk(KERN_ERR "%s: Unable to map controller.\n", + c->name); + i2o_pci_free(c); + return -ENOMEM; + } + } else + c->in_queue = c->base; + + c->irq_status = c->base.virt + I2O_IRQ_STATUS; + c->irq_mask = c->base.virt + I2O_IRQ_MASK; + c->in_port = c->base.virt + I2O_IN_PORT; + c->out_port = c->base.virt + I2O_OUT_PORT; + + /* Motorola/Freescale chip does not follow spec */ + if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) { + /* Check if CPU is enabled */ + if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) { + printk(KERN_INFO "%s: MPC82XX needs CPU running to " + "service I2O.\n", c->name); + i2o_pci_free(c); + return -ENODEV; + } else { + c->irq_status += I2O_MOTOROLA_PORT_OFFSET; + c->irq_mask += I2O_MOTOROLA_PORT_OFFSET; + c->in_port += I2O_MOTOROLA_PORT_OFFSET; + c->out_port += I2O_MOTOROLA_PORT_OFFSET; + printk(KERN_INFO "%s: MPC82XX workarounds activated.\n", + c->name); + } + } + + if (i2o_dma_alloc(dev, &c->status, 8)) { + i2o_pci_free(c); + return -ENOMEM; + } + + if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt))) { + i2o_pci_free(c); + return -ENOMEM; + } + + if (i2o_dma_alloc(dev, &c->dlct, 8192)) { + i2o_pci_free(c); + return -ENOMEM; + } + + if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block))) { + i2o_pci_free(c); + return -ENOMEM; + } + + if (i2o_dma_alloc(dev, &c->out_queue, + I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE * + sizeof(u32))) { + i2o_pci_free(c); + return -ENOMEM; + } + + pci_set_drvdata(pdev, c); + + return 0; +} + +/** + * i2o_pci_interrupt - Interrupt handler for I2O controller + * @irq: interrupt line + * @dev_id: pointer to the I2O controller + * + * Handle an interrupt from a PCI based I2O controller. This turns out + * to be rather simple. We keep the controller pointer in the cookie. + */ +static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id) +{ + struct i2o_controller *c = dev_id; + u32 m; + irqreturn_t rc = IRQ_NONE; + + while (readl(c->irq_status) & I2O_IRQ_OUTBOUND_POST) { + m = readl(c->out_port); + if (m == I2O_QUEUE_EMPTY) { + /* + * Old 960 steppings had a bug in the I2O unit that + * caused the queue to appear empty when it wasn't. + */ + m = readl(c->out_port); + if (unlikely(m == I2O_QUEUE_EMPTY)) + break; + } + + /* dispatch it */ + if (i2o_driver_dispatch(c, m)) + /* flush it if result != 0 */ + i2o_flush_reply(c, m); + + rc = IRQ_HANDLED; + } + + return rc; +} + +/** + * i2o_pci_irq_enable - Allocate interrupt for I2O controller + * @c: i2o_controller that the request is for + * + * Allocate an interrupt for the I2O controller, and activate interrupts + * on the I2O controller. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_pci_irq_enable(struct i2o_controller *c) +{ + struct pci_dev *pdev = c->pdev; + int rc; + + writel(0xffffffff, c->irq_mask); + + if (pdev->irq) { + rc = request_irq(pdev->irq, i2o_pci_interrupt, IRQF_SHARED, + c->name, c); + if (rc < 0) { + printk(KERN_ERR "%s: unable to allocate interrupt %d." + "\n", c->name, pdev->irq); + return rc; + } + } + + writel(0x00000000, c->irq_mask); + + printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq); + + return 0; +} + +/** + * i2o_pci_irq_disable - Free interrupt for I2O controller + * @c: I2O controller + * + * Disable interrupts in I2O controller and then free interrupt. + */ +static void i2o_pci_irq_disable(struct i2o_controller *c) +{ + writel(0xffffffff, c->irq_mask); + + if (c->pdev->irq > 0) + free_irq(c->pdev->irq, c); +} + +/** + * i2o_pci_probe - Probe the PCI device for an I2O controller + * @pdev: PCI device to test + * @id: id which matched with the PCI device id table + * + * Probe the PCI device for any device which is a memory of the + * Intelligent, I2O class or an Adaptec Zero Channel Controller. We + * attempt to set up each such device and register it with the core. + * + * Returns 0 on success or negative error code on failure. + */ +static int i2o_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct i2o_controller *c; + int rc; + struct pci_dev *i960 = NULL; + + printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); + + if ((pdev->class & 0xff) > 1) { + printk(KERN_WARNING "i2o: %s does not support I2O 1.5 " + "(skipping).\n", pci_name(pdev)); + return -ENODEV; + } + + if ((rc = pci_enable_device(pdev))) { + printk(KERN_WARNING "i2o: couldn't enable device %s\n", + pci_name(pdev)); + return rc; + } + + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", + pci_name(pdev)); + rc = -ENODEV; + goto disable; + } + + pci_set_master(pdev); + + c = i2o_iop_alloc(); + if (IS_ERR(c)) { + printk(KERN_ERR "i2o: couldn't allocate memory for %s\n", + pci_name(pdev)); + rc = PTR_ERR(c); + goto disable; + } else + printk(KERN_INFO "%s: controller found (%s)\n", c->name, + pci_name(pdev)); + + c->pdev = pdev; + c->device.parent = &pdev->dev; + + /* Cards that fall apart if you hit them with large I/O loads... */ + if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) { + c->short_req = 1; + printk(KERN_INFO "%s: Symbios FC920 workarounds activated.\n", + c->name); + } + + if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) { + /* + * Expose the ship behind i960 for initialization, or it will + * failed + */ + i960 = pci_get_slot(c->pdev->bus, + PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0)); + + if (i960) { + pci_write_config_word(i960, 0x42, 0); + pci_dev_put(i960); + } + + c->promise = 1; + c->limit_sectors = 1; + } + + if (pdev->subsystem_vendor == PCI_VENDOR_ID_DPT) + c->adaptec = 1; + + /* Cards that go bananas if you quiesce them before you reset them. */ + if (pdev->vendor == PCI_VENDOR_ID_DPT) { + c->no_quiesce = 1; + if (pdev->device == 0xa511) + c->raptor = 1; + + if (pdev->subsystem_device == 0xc05a) { + c->limit_sectors = 1; + printk(KERN_INFO + "%s: limit sectors per request to %d\n", c->name, + I2O_MAX_SECTORS_LIMITED); + } +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if (sizeof(dma_addr_t) > 4) { + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) + printk(KERN_INFO "%s: 64-bit DMA unavailable\n", + c->name); + else { + c->pae_support = 1; + printk(KERN_INFO "%s: using 64-bit DMA\n", + c->name); + } + } +#endif + } + + if ((rc = i2o_pci_alloc(c))) { + printk(KERN_ERR "%s: DMA / IO allocation for I2O controller " + "failed\n", c->name); + goto free_controller; + } + + if (i2o_pci_irq_enable(c)) { + printk(KERN_ERR "%s: unable to enable interrupts for I2O " + "controller\n", c->name); + goto free_pci; + } + + if ((rc = i2o_iop_add(c))) + goto uninstall; + + if (i960) + pci_write_config_word(i960, 0x42, 0x03ff); + + return 0; + + uninstall: + i2o_pci_irq_disable(c); + + free_pci: + i2o_pci_free(c); + + free_controller: + i2o_iop_free(c); + + disable: + pci_disable_device(pdev); + + return rc; +} + +/** + * i2o_pci_remove - Removes a I2O controller from the system + * @pdev: I2O controller which should be removed + * + * Reset the I2O controller, disable interrupts and remove all allocated + * resources. + */ +static void i2o_pci_remove(struct pci_dev *pdev) +{ + struct i2o_controller *c; + c = pci_get_drvdata(pdev); + + i2o_iop_remove(c); + i2o_pci_irq_disable(c); + i2o_pci_free(c); + + pci_disable_device(pdev); + + printk(KERN_INFO "%s: Controller removed.\n", c->name); + + put_device(&c->device); +}; + +/* PCI driver for I2O controller */ +static struct pci_driver i2o_pci_driver = { + .name = "PCI_I2O", + .id_table = i2o_pci_ids, + .probe = i2o_pci_probe, + .remove = i2o_pci_remove, +}; + +/** + * i2o_pci_init - registers I2O PCI driver in PCI subsystem + * + * Returns > 0 on success or negative error code on failure. + */ +int __init i2o_pci_init(void) +{ + return pci_register_driver(&i2o_pci_driver); +}; + +/** + * i2o_pci_exit - unregisters I2O PCI driver from PCI subsystem + */ +void __exit i2o_pci_exit(void) +{ + pci_unregister_driver(&i2o_pci_driver); +}; + +MODULE_DEVICE_TABLE(pci, i2o_pci_ids); diff --git a/include/linux/i2o.h b/include/linux/i2o.h deleted file mode 100644 index d23c3c2..0000000 --- a/include/linux/i2o.h +++ /dev/null @@ -1,988 +0,0 @@ -/* - * I2O kernel space accessible structures/APIs - * - * (c) Copyright 1999, 2000 Red Hat Software - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - ************************************************************************* - * - * This header file defined the I2O APIs/structures for use by - * the I2O kernel modules. - * - */ - -#ifndef _I2O_H -#define _I2O_H - -#include - -/* How many different OSM's are we allowing */ -#define I2O_MAX_DRIVERS 8 - -#include -#include -#include -#include -#include -#include /* work_struct */ -#include -#include -#include -#include /* Needed for MUTEX init macros */ - -#include - -/* message queue empty */ -#define I2O_QUEUE_EMPTY 0xffffffff - -/* - * Cache strategies - */ - -/* The NULL strategy leaves everything up to the controller. This tends to be a - * pessimal but functional choice. - */ -#define CACHE_NULL 0 -/* Prefetch data when reading. We continually attempt to load the next 32 sectors - * into the controller cache. - */ -#define CACHE_PREFETCH 1 -/* Prefetch data when reading. We sometimes attempt to load the next 32 sectors - * into the controller cache. When an I/O is less <= 8K we assume its probably - * not sequential and don't prefetch (default) - */ -#define CACHE_SMARTFETCH 2 -/* Data is written to the cache and then out on to the disk. The I/O must be - * physically on the medium before the write is acknowledged (default without - * NVRAM) - */ -#define CACHE_WRITETHROUGH 17 -/* Data is written to the cache and then out on to the disk. The controller - * is permitted to write back the cache any way it wants. (default if battery - * backed NVRAM is present). It can be useful to set this for swap regardless of - * battery state. - */ -#define CACHE_WRITEBACK 18 -/* Optimise for under powered controllers, especially on RAID1 and RAID0. We - * write large I/O's directly to disk bypassing the cache to avoid the extra - * memory copy hits. Small writes are writeback cached - */ -#define CACHE_SMARTBACK 19 -/* Optimise for under powered controllers, especially on RAID1 and RAID0. We - * write large I/O's directly to disk bypassing the cache to avoid the extra - * memory copy hits. Small writes are writethrough cached. Suitable for devices - * lacking battery backup - */ -#define CACHE_SMARTTHROUGH 20 - -/* - * Ioctl structures - */ - -#define BLKI2OGRSTRAT _IOR('2', 1, int) -#define BLKI2OGWSTRAT _IOR('2', 2, int) -#define BLKI2OSRSTRAT _IOW('2', 3, int) -#define BLKI2OSWSTRAT _IOW('2', 4, int) - -/* - * I2O Function codes - */ - -/* - * Executive Class - */ -#define I2O_CMD_ADAPTER_ASSIGN 0xB3 -#define I2O_CMD_ADAPTER_READ 0xB2 -#define I2O_CMD_ADAPTER_RELEASE 0xB5 -#define I2O_CMD_BIOS_INFO_SET 0xA5 -#define I2O_CMD_BOOT_DEVICE_SET 0xA7 -#define I2O_CMD_CONFIG_VALIDATE 0xBB -#define I2O_CMD_CONN_SETUP 0xCA -#define I2O_CMD_DDM_DESTROY 0xB1 -#define I2O_CMD_DDM_ENABLE 0xD5 -#define I2O_CMD_DDM_QUIESCE 0xC7 -#define I2O_CMD_DDM_RESET 0xD9 -#define I2O_CMD_DDM_SUSPEND 0xAF -#define I2O_CMD_DEVICE_ASSIGN 0xB7 -#define I2O_CMD_DEVICE_RELEASE 0xB9 -#define I2O_CMD_HRT_GET 0xA8 -#define I2O_CMD_ADAPTER_CLEAR 0xBE -#define I2O_CMD_ADAPTER_CONNECT 0xC9 -#define I2O_CMD_ADAPTER_RESET 0xBD -#define I2O_CMD_LCT_NOTIFY 0xA2 -#define I2O_CMD_OUTBOUND_INIT 0xA1 -#define I2O_CMD_PATH_ENABLE 0xD3 -#define I2O_CMD_PATH_QUIESCE 0xC5 -#define I2O_CMD_PATH_RESET 0xD7 -#define I2O_CMD_STATIC_MF_CREATE 0xDD -#define I2O_CMD_STATIC_MF_RELEASE 0xDF -#define I2O_CMD_STATUS_GET 0xA0 -#define I2O_CMD_SW_DOWNLOAD 0xA9 -#define I2O_CMD_SW_UPLOAD 0xAB -#define I2O_CMD_SW_REMOVE 0xAD -#define I2O_CMD_SYS_ENABLE 0xD1 -#define I2O_CMD_SYS_MODIFY 0xC1 -#define I2O_CMD_SYS_QUIESCE 0xC3 -#define I2O_CMD_SYS_TAB_SET 0xA3 - -/* - * Utility Class - */ -#define I2O_CMD_UTIL_NOP 0x00 -#define I2O_CMD_UTIL_ABORT 0x01 -#define I2O_CMD_UTIL_CLAIM 0x09 -#define I2O_CMD_UTIL_RELEASE 0x0B -#define I2O_CMD_UTIL_PARAMS_GET 0x06 -#define I2O_CMD_UTIL_PARAMS_SET 0x05 -#define I2O_CMD_UTIL_EVT_REGISTER 0x13 -#define I2O_CMD_UTIL_EVT_ACK 0x14 -#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10 -#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D -#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F -#define I2O_CMD_UTIL_LOCK 0x17 -#define I2O_CMD_UTIL_LOCK_RELEASE 0x19 -#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15 - -/* - * SCSI Host Bus Adapter Class - */ -#define I2O_CMD_SCSI_EXEC 0x81 -#define I2O_CMD_SCSI_ABORT 0x83 -#define I2O_CMD_SCSI_BUSRESET 0x27 - -/* - * Bus Adapter Class - */ -#define I2O_CMD_BUS_ADAPTER_RESET 0x85 -#define I2O_CMD_BUS_RESET 0x87 -#define I2O_CMD_BUS_SCAN 0x89 -#define I2O_CMD_BUS_QUIESCE 0x8b - -/* - * Random Block Storage Class - */ -#define I2O_CMD_BLOCK_READ 0x30 -#define I2O_CMD_BLOCK_WRITE 0x31 -#define I2O_CMD_BLOCK_CFLUSH 0x37 -#define I2O_CMD_BLOCK_MLOCK 0x49 -#define I2O_CMD_BLOCK_MUNLOCK 0x4B -#define I2O_CMD_BLOCK_MMOUNT 0x41 -#define I2O_CMD_BLOCK_MEJECT 0x43 -#define I2O_CMD_BLOCK_POWER 0x70 - -#define I2O_CMD_PRIVATE 0xFF - -/* Command status values */ - -#define I2O_CMD_IN_PROGRESS 0x01 -#define I2O_CMD_REJECTED 0x02 -#define I2O_CMD_FAILED 0x03 -#define I2O_CMD_COMPLETED 0x04 - -/* I2O API function return values */ - -#define I2O_RTN_NO_ERROR 0 -#define I2O_RTN_NOT_INIT 1 -#define I2O_RTN_FREE_Q_EMPTY 2 -#define I2O_RTN_TCB_ERROR 3 -#define I2O_RTN_TRANSACTION_ERROR 4 -#define I2O_RTN_ADAPTER_ALREADY_INIT 5 -#define I2O_RTN_MALLOC_ERROR 6 -#define I2O_RTN_ADPTR_NOT_REGISTERED 7 -#define I2O_RTN_MSG_REPLY_TIMEOUT 8 -#define I2O_RTN_NO_STATUS 9 -#define I2O_RTN_NO_FIRM_VER 10 -#define I2O_RTN_NO_LINK_SPEED 11 - -/* Reply message status defines for all messages */ - -#define I2O_REPLY_STATUS_SUCCESS 0x00 -#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 -#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 -#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 -#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 -#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 -#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 -#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 -#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 -#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A -#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B -#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 - -/* Status codes and Error Information for Parameter functions */ - -#define I2O_PARAMS_STATUS_SUCCESS 0x00 -#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01 -#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02 -#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03 -#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04 -#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05 -#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06 -#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07 -#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08 -#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09 -#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A -#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B -#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C -#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D -#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E -#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F -#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10 - -/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error - * messages: Table 3-2 Detailed Status Codes.*/ - -#define I2O_DSC_SUCCESS 0x0000 -#define I2O_DSC_BAD_KEY 0x0002 -#define I2O_DSC_TCL_ERROR 0x0003 -#define I2O_DSC_REPLY_BUFFER_FULL 0x0004 -#define I2O_DSC_NO_SUCH_PAGE 0x0005 -#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006 -#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007 -#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009 -#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A -#define I2O_DSC_DEVICE_LOCKED 0x000B -#define I2O_DSC_DEVICE_RESET 0x000C -#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D -#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E -#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F -#define I2O_DSC_INVALID_OFFSET 0x0010 -#define I2O_DSC_INVALID_PARAMETER 0x0011 -#define I2O_DSC_INVALID_REQUEST 0x0012 -#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013 -#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014 -#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015 -#define I2O_DSC_MISSING_PARAMETER 0x0016 -#define I2O_DSC_TIMEOUT 0x0017 -#define I2O_DSC_UNKNOWN_ERROR 0x0018 -#define I2O_DSC_UNKNOWN_FUNCTION 0x0019 -#define I2O_DSC_UNSUPPORTED_VERSION 0x001A -#define I2O_DSC_DEVICE_BUSY 0x001B -#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C - -/* DetailedStatusCode defines for Block Storage Operation: Table 6-7 Detailed - Status Codes.*/ - -#define I2O_BSA_DSC_SUCCESS 0x0000 -#define I2O_BSA_DSC_MEDIA_ERROR 0x0001 -#define I2O_BSA_DSC_ACCESS_ERROR 0x0002 -#define I2O_BSA_DSC_DEVICE_FAILURE 0x0003 -#define I2O_BSA_DSC_DEVICE_NOT_READY 0x0004 -#define I2O_BSA_DSC_MEDIA_NOT_PRESENT 0x0005 -#define I2O_BSA_DSC_MEDIA_LOCKED 0x0006 -#define I2O_BSA_DSC_MEDIA_FAILURE 0x0007 -#define I2O_BSA_DSC_PROTOCOL_FAILURE 0x0008 -#define I2O_BSA_DSC_BUS_FAILURE 0x0009 -#define I2O_BSA_DSC_ACCESS_VIOLATION 0x000A -#define I2O_BSA_DSC_WRITE_PROTECTED 0x000B -#define I2O_BSA_DSC_DEVICE_RESET 0x000C -#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D -#define I2O_BSA_DSC_TIMEOUT 0x000E - -/* FailureStatusCodes, Table 3-3 Message Failure Codes */ - -#define I2O_FSC_TRANSPORT_SERVICE_SUSPENDED 0x81 -#define I2O_FSC_TRANSPORT_SERVICE_TERMINATED 0x82 -#define I2O_FSC_TRANSPORT_CONGESTION 0x83 -#define I2O_FSC_TRANSPORT_FAILURE 0x84 -#define I2O_FSC_TRANSPORT_STATE_ERROR 0x85 -#define I2O_FSC_TRANSPORT_TIME_OUT 0x86 -#define I2O_FSC_TRANSPORT_ROUTING_FAILURE 0x87 -#define I2O_FSC_TRANSPORT_INVALID_VERSION 0x88 -#define I2O_FSC_TRANSPORT_INVALID_OFFSET 0x89 -#define I2O_FSC_TRANSPORT_INVALID_MSG_FLAGS 0x8A -#define I2O_FSC_TRANSPORT_FRAME_TOO_SMALL 0x8B -#define I2O_FSC_TRANSPORT_FRAME_TOO_LARGE 0x8C -#define I2O_FSC_TRANSPORT_INVALID_TARGET_ID 0x8D -#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_ID 0x8E -#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_CONTEXT 0x8F -#define I2O_FSC_TRANSPORT_UNKNOWN_FAILURE 0xFF - -/* Device Claim Types */ -#define I2O_CLAIM_PRIMARY 0x01000000 -#define I2O_CLAIM_MANAGEMENT 0x02000000 -#define I2O_CLAIM_AUTHORIZED 0x03000000 -#define I2O_CLAIM_SECONDARY 0x04000000 - -/* Message header defines for VersionOffset */ -#define I2OVER15 0x0001 -#define I2OVER20 0x0002 - -/* Default is 1.5 */ -#define I2OVERSION I2OVER15 - -#define SGL_OFFSET_0 I2OVERSION -#define SGL_OFFSET_4 (0x0040 | I2OVERSION) -#define SGL_OFFSET_5 (0x0050 | I2OVERSION) -#define SGL_OFFSET_6 (0x0060 | I2OVERSION) -#define SGL_OFFSET_7 (0x0070 | I2OVERSION) -#define SGL_OFFSET_8 (0x0080 | I2OVERSION) -#define SGL_OFFSET_9 (0x0090 | I2OVERSION) -#define SGL_OFFSET_10 (0x00A0 | I2OVERSION) -#define SGL_OFFSET_11 (0x00B0 | I2OVERSION) -#define SGL_OFFSET_12 (0x00C0 | I2OVERSION) -#define SGL_OFFSET(x) (((x)<<4) | I2OVERSION) - -/* Transaction Reply Lists (TRL) Control Word structure */ -#define TRL_SINGLE_FIXED_LENGTH 0x00 -#define TRL_SINGLE_VARIABLE_LENGTH 0x40 -#define TRL_MULTIPLE_FIXED_LENGTH 0x80 - - /* msg header defines for MsgFlags */ -#define MSG_STATIC 0x0100 -#define MSG_64BIT_CNTXT 0x0200 -#define MSG_MULTI_TRANS 0x1000 -#define MSG_FAIL 0x2000 -#define MSG_FINAL 0x4000 -#define MSG_REPLY 0x8000 - - /* minimum size msg */ -#define THREE_WORD_MSG_SIZE 0x00030000 -#define FOUR_WORD_MSG_SIZE 0x00040000 -#define FIVE_WORD_MSG_SIZE 0x00050000 -#define SIX_WORD_MSG_SIZE 0x00060000 -#define SEVEN_WORD_MSG_SIZE 0x00070000 -#define EIGHT_WORD_MSG_SIZE 0x00080000 -#define NINE_WORD_MSG_SIZE 0x00090000 -#define TEN_WORD_MSG_SIZE 0x000A0000 -#define ELEVEN_WORD_MSG_SIZE 0x000B0000 -#define I2O_MESSAGE_SIZE(x) ((x)<<16) - -/* special TID assignments */ -#define ADAPTER_TID 0 -#define HOST_TID 1 - -/* outbound queue defines */ -#define I2O_MAX_OUTBOUND_MSG_FRAMES 128 -#define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */ - -/* inbound queue definitions */ -#define I2O_MSG_INPOOL_MIN 32 -#define I2O_INBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */ - -#define I2O_POST_WAIT_OK 0 -#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT - -#define I2O_CONTEXT_LIST_MIN_LENGTH 15 -#define I2O_CONTEXT_LIST_USED 0x01 -#define I2O_CONTEXT_LIST_DELETED 0x02 - -/* timeouts */ -#define I2O_TIMEOUT_INIT_OUTBOUND_QUEUE 15 -#define I2O_TIMEOUT_MESSAGE_GET 5 -#define I2O_TIMEOUT_RESET 30 -#define I2O_TIMEOUT_STATUS_GET 5 -#define I2O_TIMEOUT_LCT_GET 360 -#define I2O_TIMEOUT_SCSI_SCB_ABORT 240 - -/* retries */ -#define I2O_HRT_GET_TRIES 3 -#define I2O_LCT_GET_TRIES 3 - -/* defines for max_sectors and max_phys_segments */ -#define I2O_MAX_SECTORS 1024 -#define I2O_MAX_SECTORS_LIMITED 128 -#define I2O_MAX_PHYS_SEGMENTS BLK_MAX_SEGMENTS - -/* - * Message structures - */ -struct i2o_message { - union { - struct { - u8 version_offset; - u8 flags; - u16 size; - u32 target_tid:12; - u32 init_tid:12; - u32 function:8; - u32 icntxt; /* initiator context */ - u32 tcntxt; /* transaction context */ - } s; - u32 head[4]; - } u; - /* List follows */ - u32 body[0]; -}; - -/* MFA and I2O message used by mempool */ -struct i2o_msg_mfa { - u32 mfa; /* MFA returned by the controller */ - struct i2o_message msg; /* I2O message */ -}; - -/* - * Each I2O device entity has one of these. There is one per device. - */ -struct i2o_device { - i2o_lct_entry lct_data; /* Device LCT information */ - - struct i2o_controller *iop; /* Controlling IOP */ - struct list_head list; /* node in IOP devices list */ - - struct device device; - - struct mutex lock; /* device lock */ -}; - -/* - * Event structure provided to the event handling function - */ -struct i2o_event { - struct work_struct work; - struct i2o_device *i2o_dev; /* I2O device pointer from which the - event reply was initiated */ - u16 size; /* Size of data in 32-bit words */ - u32 tcntxt; /* Transaction context used at - registration */ - u32 event_indicator; /* Event indicator from reply */ - u32 data[0]; /* Event data from reply */ -}; - -/* - * I2O classes which could be handled by the OSM - */ -struct i2o_class_id { - u16 class_id:12; -}; - -/* - * I2O driver structure for OSMs - */ -struct i2o_driver { - char *name; /* OSM name */ - int context; /* Low 8 bits of the transaction info */ - struct i2o_class_id *classes; /* I2O classes that this OSM handles */ - - /* Message reply handler */ - int (*reply) (struct i2o_controller *, u32, struct i2o_message *); - - /* Event handler */ - work_func_t event; - - struct workqueue_struct *event_queue; /* Event queue */ - - struct device_driver driver; - - /* notification of changes */ - void (*notify_controller_add) (struct i2o_controller *); - void (*notify_controller_remove) (struct i2o_controller *); - void (*notify_device_add) (struct i2o_device *); - void (*notify_device_remove) (struct i2o_device *); - - struct semaphore lock; -}; - -/* - * Contains DMA mapped address information - */ -struct i2o_dma { - void *virt; - dma_addr_t phys; - size_t len; -}; - -/* - * Contains slab cache and mempool information - */ -struct i2o_pool { - char *name; - struct kmem_cache *slab; - mempool_t *mempool; -}; - -/* - * Contains IO mapped address information - */ -struct i2o_io { - void __iomem *virt; - unsigned long phys; - unsigned long len; -}; - -/* - * Context queue entry, used for 32-bit context on 64-bit systems - */ -struct i2o_context_list_element { - struct list_head list; - u32 context; - void *ptr; - unsigned long timestamp; -}; - -/* - * Each I2O controller has one of these objects - */ -struct i2o_controller { - char name[16]; - int unit; - int type; - - struct pci_dev *pdev; /* PCI device */ - - unsigned int promise:1; /* Promise controller */ - unsigned int adaptec:1; /* DPT / Adaptec controller */ - unsigned int raptor:1; /* split bar */ - unsigned int no_quiesce:1; /* dont quiesce before reset */ - unsigned int short_req:1; /* use small block sizes */ - unsigned int limit_sectors:1; /* limit number of sectors / request */ - unsigned int pae_support:1; /* controller has 64-bit SGL support */ - - struct list_head devices; /* list of I2O devices */ - struct list_head list; /* Controller list */ - - void __iomem *in_port; /* Inbout port address */ - void __iomem *out_port; /* Outbound port address */ - void __iomem *irq_status; /* Interrupt status register address */ - void __iomem *irq_mask; /* Interrupt mask register address */ - - struct i2o_dma status; /* IOP status block */ - - struct i2o_dma hrt; /* HW Resource Table */ - i2o_lct *lct; /* Logical Config Table */ - struct i2o_dma dlct; /* Temp LCT */ - struct mutex lct_lock; /* Lock for LCT updates */ - struct i2o_dma status_block; /* IOP status block */ - - struct i2o_io base; /* controller messaging unit */ - struct i2o_io in_queue; /* inbound message queue Host->IOP */ - struct i2o_dma out_queue; /* outbound message queue IOP->Host */ - - struct i2o_pool in_msg; /* mempool for inbound messages */ - - unsigned int battery:1; /* Has a battery backup */ - unsigned int io_alloc:1; /* An I/O resource was allocated */ - unsigned int mem_alloc:1; /* A memory resource was allocated */ - - struct resource io_resource; /* I/O resource allocated to the IOP */ - struct resource mem_resource; /* Mem resource allocated to the IOP */ - - struct device device; - struct i2o_device *exec; /* Executive */ -#if BITS_PER_LONG == 64 - spinlock_t context_list_lock; /* lock for context_list */ - atomic_t context_list_counter; /* needed for unique contexts */ - struct list_head context_list; /* list of context id's - and pointers */ -#endif - spinlock_t lock; /* lock for controller - configuration */ - void *driver_data[I2O_MAX_DRIVERS]; /* storage for drivers */ -}; - -/* - * I2O System table entry - * - * The system table contains information about all the IOPs in the - * system. It is sent to all IOPs so that they can create peer2peer - * connections between them. - */ -struct i2o_sys_tbl_entry { - u16 org_id; - u16 reserved1; - u32 iop_id:12; - u32 reserved2:20; - u16 seg_num:12; - u16 i2o_version:4; - u8 iop_state; - u8 msg_type; - u16 frame_size; - u16 reserved3; - u32 last_changed; - u32 iop_capabilities; - u32 inbound_low; - u32 inbound_high; -}; - -struct i2o_sys_tbl { - u8 num_entries; - u8 version; - u16 reserved1; - u32 change_ind; - u32 reserved2; - u32 reserved3; - struct i2o_sys_tbl_entry iops[0]; -}; - -extern struct list_head i2o_controllers; - -/* Message functions */ -extern struct i2o_message *i2o_msg_get_wait(struct i2o_controller *, int); -extern int i2o_msg_post_wait_mem(struct i2o_controller *, struct i2o_message *, - unsigned long, struct i2o_dma *); - -/* IOP functions */ -extern int i2o_status_get(struct i2o_controller *); - -extern int i2o_event_register(struct i2o_device *, struct i2o_driver *, int, - u32); -extern struct i2o_device *i2o_iop_find_device(struct i2o_controller *, u16); -extern struct i2o_controller *i2o_find_iop(int); - -/* Functions needed for handling 64-bit pointers in 32-bit context */ -#if BITS_PER_LONG == 64 -extern u32 i2o_cntxt_list_add(struct i2o_controller *, void *); -extern void *i2o_cntxt_list_get(struct i2o_controller *, u32); -extern u32 i2o_cntxt_list_remove(struct i2o_controller *, void *); -extern u32 i2o_cntxt_list_get_ptr(struct i2o_controller *, void *); - -static inline u32 i2o_ptr_low(void *ptr) -{ - return (u32) (u64) ptr; -}; - -static inline u32 i2o_ptr_high(void *ptr) -{ - return (u32) ((u64) ptr >> 32); -}; - -static inline u32 i2o_dma_low(dma_addr_t dma_addr) -{ - return (u32) (u64) dma_addr; -}; - -static inline u32 i2o_dma_high(dma_addr_t dma_addr) -{ - return (u32) ((u64) dma_addr >> 32); -}; -#else -static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr) -{ - return (u32) ptr; -}; - -static inline void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) -{ - return (void *)context; -}; - -static inline u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr) -{ - return (u32) ptr; -}; - -static inline u32 i2o_cntxt_list_get_ptr(struct i2o_controller *c, void *ptr) -{ - return (u32) ptr; -}; - -static inline u32 i2o_ptr_low(void *ptr) -{ - return (u32) ptr; -}; - -static inline u32 i2o_ptr_high(void *ptr) -{ - return 0; -}; - -static inline u32 i2o_dma_low(dma_addr_t dma_addr) -{ - return (u32) dma_addr; -}; - -static inline u32 i2o_dma_high(dma_addr_t dma_addr) -{ - return 0; -}; -#endif - -extern u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size); -extern dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr, - size_t size, - enum dma_data_direction direction, - u32 ** sg_ptr); -extern int i2o_dma_map_sg(struct i2o_controller *c, - struct scatterlist *sg, int sg_count, - enum dma_data_direction direction, - u32 ** sg_ptr); -extern int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len); -extern void i2o_dma_free(struct device *dev, struct i2o_dma *addr); -extern int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, - size_t len); -extern int i2o_pool_alloc(struct i2o_pool *pool, const char *name, - size_t size, int min_nr); -extern void i2o_pool_free(struct i2o_pool *pool); -/* I2O driver (OSM) functions */ -extern int i2o_driver_register(struct i2o_driver *); -extern void i2o_driver_unregister(struct i2o_driver *); - -/** - * i2o_driver_notify_controller_add - Send notification of added controller - * @drv: I2O driver - * @c: I2O controller - * - * Send notification of added controller to a single registered driver. - */ -static inline void i2o_driver_notify_controller_add(struct i2o_driver *drv, - struct i2o_controller *c) -{ - if (drv->notify_controller_add) - drv->notify_controller_add(c); -}; - -/** - * i2o_driver_notify_controller_remove - Send notification of removed controller - * @drv: I2O driver - * @c: I2O controller - * - * Send notification of removed controller to a single registered driver. - */ -static inline void i2o_driver_notify_controller_remove(struct i2o_driver *drv, - struct i2o_controller *c) -{ - if (drv->notify_controller_remove) - drv->notify_controller_remove(c); -}; - -/** - * i2o_driver_notify_device_add - Send notification of added device - * @drv: I2O driver - * @i2o_dev: the added i2o_device - * - * Send notification of added device to a single registered driver. - */ -static inline void i2o_driver_notify_device_add(struct i2o_driver *drv, - struct i2o_device *i2o_dev) -{ - if (drv->notify_device_add) - drv->notify_device_add(i2o_dev); -}; - -/** - * i2o_driver_notify_device_remove - Send notification of removed device - * @drv: I2O driver - * @i2o_dev: the added i2o_device - * - * Send notification of removed device to a single registered driver. - */ -static inline void i2o_driver_notify_device_remove(struct i2o_driver *drv, - struct i2o_device *i2o_dev) -{ - if (drv->notify_device_remove) - drv->notify_device_remove(i2o_dev); -}; - -extern void i2o_driver_notify_controller_add_all(struct i2o_controller *); -extern void i2o_driver_notify_controller_remove_all(struct i2o_controller *); -extern void i2o_driver_notify_device_add_all(struct i2o_device *); -extern void i2o_driver_notify_device_remove_all(struct i2o_device *); - -/* I2O device functions */ -extern int i2o_device_claim(struct i2o_device *); -extern int i2o_device_claim_release(struct i2o_device *); - -/* Exec OSM functions */ -extern int i2o_exec_lct_get(struct i2o_controller *); - -/* device / driver / kobject conversion functions */ -#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver) -#define to_i2o_device(dev) container_of(dev, struct i2o_device, device) -#define to_i2o_controller(dev) container_of(dev, struct i2o_controller, device) - -/** - * i2o_out_to_virt - Turn an I2O message to a virtual address - * @c: controller - * @m: message engine value - * - * Turn a receive message from an I2O controller bus address into - * a Linux virtual address. The shared page frame is a linear block - * so we simply have to shift the offset. This function does not - * work for sender side messages as they are ioremap objects - * provided by the I2O controller. - */ -static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c, - u32 m) -{ - BUG_ON(m < c->out_queue.phys - || m >= c->out_queue.phys + c->out_queue.len); - - return c->out_queue.virt + (m - c->out_queue.phys); -}; - -/** - * i2o_msg_in_to_virt - Turn an I2O message to a virtual address - * @c: controller - * @m: message engine value - * - * Turn a send message from an I2O controller bus address into - * a Linux virtual address. The shared page frame is a linear block - * so we simply have to shift the offset. This function does not - * work for receive side messages as they are kmalloc objects - * in a different pool. - */ -static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct - i2o_controller *c, - u32 m) -{ - return c->in_queue.virt + m; -}; - -/** - * i2o_msg_get - obtain an I2O message from the IOP - * @c: I2O controller - * - * This function tries to get a message frame. If no message frame is - * available do not wait until one is available (see also i2o_msg_get_wait). - * The returned pointer to the message frame is not in I/O memory, it is - * allocated from a mempool. But because a MFA is allocated from the - * controller too it is guaranteed that i2o_msg_post() will never fail. - * - * On a success a pointer to the message frame is returned. If the message - * queue is empty -EBUSY is returned and if no memory is available -ENOMEM - * is returned. - */ -static inline struct i2o_message *i2o_msg_get(struct i2o_controller *c) -{ - struct i2o_msg_mfa *mmsg = mempool_alloc(c->in_msg.mempool, GFP_ATOMIC); - if (!mmsg) - return ERR_PTR(-ENOMEM); - - mmsg->mfa = readl(c->in_port); - if (unlikely(mmsg->mfa >= c->in_queue.len)) { - u32 mfa = mmsg->mfa; - - mempool_free(mmsg, c->in_msg.mempool); - - if (mfa == I2O_QUEUE_EMPTY) - return ERR_PTR(-EBUSY); - return ERR_PTR(-EFAULT); - } - - return &mmsg->msg; -}; - -/** - * i2o_msg_post - Post I2O message to I2O controller - * @c: I2O controller to which the message should be send - * @msg: message returned by i2o_msg_get() - * - * Post the message to the I2O controller and return immediately. - */ -static inline void i2o_msg_post(struct i2o_controller *c, - struct i2o_message *msg) -{ - struct i2o_msg_mfa *mmsg; - - mmsg = container_of(msg, struct i2o_msg_mfa, msg); - memcpy_toio(i2o_msg_in_to_virt(c, mmsg->mfa), msg, - (le32_to_cpu(msg->u.head[0]) >> 16) << 2); - writel(mmsg->mfa, c->in_port); - mempool_free(mmsg, c->in_msg.mempool); -}; - -/** - * i2o_msg_post_wait - Post and wait a message and wait until return - * @c: controller - * @msg: message to post - * @timeout: time in seconds to wait - * - * This API allows an OSM to post a message and then be told whether or - * not the system received a successful reply. If the message times out - * then the value '-ETIMEDOUT' is returned. - * - * Returns 0 on success or negative error code on failure. - */ -static inline int i2o_msg_post_wait(struct i2o_controller *c, - struct i2o_message *msg, - unsigned long timeout) -{ - return i2o_msg_post_wait_mem(c, msg, timeout, NULL); -}; - -/** - * i2o_msg_nop_mfa - Returns a fetched MFA back to the controller - * @c: I2O controller from which the MFA was fetched - * @mfa: MFA which should be returned - * - * This function must be used for preserved messages, because i2o_msg_nop() - * also returns the allocated memory back to the msg_pool mempool. - */ -static inline void i2o_msg_nop_mfa(struct i2o_controller *c, u32 mfa) -{ - struct i2o_message __iomem *msg; - u32 nop[3] = { - THREE_WORD_MSG_SIZE | SGL_OFFSET_0, - I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, - 0x00000000 - }; - - msg = i2o_msg_in_to_virt(c, mfa); - memcpy_toio(msg, nop, sizeof(nop)); - writel(mfa, c->in_port); -}; - -/** - * i2o_msg_nop - Returns a message which is not used - * @c: I2O controller from which the message was created - * @msg: message which should be returned - * - * If you fetch a message via i2o_msg_get, and can't use it, you must - * return the message with this function. Otherwise the MFA is lost as well - * as the allocated memory from the mempool. - */ -static inline void i2o_msg_nop(struct i2o_controller *c, - struct i2o_message *msg) -{ - struct i2o_msg_mfa *mmsg; - mmsg = container_of(msg, struct i2o_msg_mfa, msg); - - i2o_msg_nop_mfa(c, mmsg->mfa); - mempool_free(mmsg, c->in_msg.mempool); -}; - -/** - * i2o_flush_reply - Flush reply from I2O controller - * @c: I2O controller - * @m: the message identifier - * - * The I2O controller must be informed that the reply message is not needed - * anymore. If you forget to flush the reply, the message frame can't be - * used by the controller anymore and is therefore lost. - */ -static inline void i2o_flush_reply(struct i2o_controller *c, u32 m) -{ - writel(m, c->out_port); -}; - -/* - * Endian handling wrapped into the macro - keeps the core code - * cleaner. - */ - -#define i2o_raw_writel(val, mem) __raw_writel(cpu_to_le32(val), mem) - -extern int i2o_parm_field_get(struct i2o_device *, int, int, void *, int); -extern int i2o_parm_table_get(struct i2o_device *, int, int, int, void *, int, - void *, int); - -/* debugging and troubleshooting/diagnostic helpers. */ -#define osm_printk(level, format, arg...) \ - printk(level "%s: " format, OSM_NAME , ## arg) - -#ifdef DEBUG -#define osm_debug(format, arg...) \ - osm_printk(KERN_DEBUG, format , ## arg) -#else -#define osm_debug(format, arg...) \ - do { } while (0) -#endif - -#define osm_err(format, arg...) \ - osm_printk(KERN_ERR, format , ## arg) -#define osm_info(format, arg...) \ - osm_printk(KERN_INFO, format , ## arg) -#define osm_warn(format, arg...) \ - osm_printk(KERN_WARNING, format , ## arg) - -/* debugging functions */ -extern void i2o_report_status(const char *, const char *, struct i2o_message *); -extern void i2o_dump_message(struct i2o_message *); -extern void i2o_dump_hrt(struct i2o_controller *c); -extern void i2o_debug_state(struct i2o_controller *c); - -#endif /* _I2O_H */ -- cgit v0.10.2 From b5d78b7f816ecfdf274e7673e79ce165d3f052cb Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 3 Feb 2015 13:18:03 +0000 Subject: staging: cptm1217: blow it all away We have a drivers/input layer for Synaptics products and nothing should now be using the staging driver. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 9e52bcd..1a2c281 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -68,8 +68,6 @@ source "drivers/staging/ft1000/Kconfig" source "drivers/staging/speakup/Kconfig" -source "drivers/staging/cptm1217/Kconfig" - source "drivers/staging/ste_rmi4/Kconfig" source "drivers/staging/nvec/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 6e0ac52..bd02e9b 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -28,7 +28,6 @@ obj-$(CONFIG_FB_XGI) += xgifb/ obj-$(CONFIG_USB_EMXX) += emxx_udc/ obj-$(CONFIG_FT1000) += ft1000/ obj-$(CONFIG_SPEAKUP) += speakup/ -obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_ANDROID) += android/ diff --git a/drivers/staging/cptm1217/Kconfig b/drivers/staging/cptm1217/Kconfig deleted file mode 100644 index 43b1cc0..0000000 --- a/drivers/staging/cptm1217/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config TOUCHSCREEN_CLEARPAD_TM1217 - tristate "Synaptics Clearpad TM1217" - depends on I2C - depends on GPIOLIB - depends on INPUT - help - Say Y here if you have a Synaptics Clearpad TM1217 Controller - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called clearpad_tm1217. diff --git a/drivers/staging/cptm1217/Makefile b/drivers/staging/cptm1217/Makefile deleted file mode 100644 index 8961faf..0000000 --- a/drivers/staging/cptm1217/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += clearpad_tm1217.o - diff --git a/drivers/staging/cptm1217/TODO b/drivers/staging/cptm1217/TODO deleted file mode 100644 index 3039224..0000000 --- a/drivers/staging/cptm1217/TODO +++ /dev/null @@ -1,5 +0,0 @@ -- Wait for the official upstream general clearpad drivers as promised over - the past few months -- Merge any device support needed from this driver into it -- Delete this driver - diff --git a/drivers/staging/cptm1217/clearpad_tm1217.c b/drivers/staging/cptm1217/clearpad_tm1217.c deleted file mode 100644 index 4304604..0000000 --- a/drivers/staging/cptm1217/clearpad_tm1217.c +++ /dev/null @@ -1,671 +0,0 @@ -/* - * clearpad_tm1217.c - Touch Screen driver for Synaptics Clearpad - * TM1217 controller - * - * Copyright (C) 2008 Intel Corp - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; ifnot, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * Questions/Comments/Bug fixes to Ramesh Agarwal (ramesh.agarwal@intel.com) - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "cp_tm1217.h" - -#define CPTM1217_DEVICE_NAME "cptm1217" -#define CPTM1217_DRIVER_NAME CPTM1217_DEVICE_NAME - -#define MAX_TOUCH_SUPPORTED 2 -#define TOUCH_SUPPORTED 1 -#define SAMPLING_FREQ 80 /* Frequency in HZ */ -#define DELAY_BTWIN_SAMPLE (1000 / SAMPLING_FREQ) -#define WAIT_FOR_RESPONSE 5 /* 5msec just works */ -#define MAX_RETRIES 5 /* As above */ -#define INCREMENTAL_DELAY 5 /* As above */ - -/* Regster Definitions */ -#define TMA1217_DEV_STATUS 0x13 /* Device Status */ -#define TMA1217_INT_STATUS 0x14 /* Interrupt Status */ - -/* Controller can detect up to 2 possible finger touches. - * Each finger touch provides 12 bit X Y co-ordinates, the values are split - * across 2 registers, and an 8 bit Z value */ -#define TMA1217_FINGER_STATE 0x18 /* Finger State */ -#define TMA1217_FINGER1_X_HIGHER8 0x19 /* Higher 8 bit of X coordinate */ -#define TMA1217_FINGER1_Y_HIGHER8 0x1A /* Higher 8 bit of Y coordinate */ -#define TMA1217_FINGER1_XY_LOWER4 0x1B /* Lower 4 bits of X and Y */ -#define TMA1217_FINGER1_Z_VALUE 0x1D /* 8 bit Z value for finger 1 */ -#define TMA1217_FINGER2_X_HIGHER8 0x1E /* Higher 8 bit of X coordinate */ -#define TMA1217_FINGER2_Y_HIGHER8 0x1F /* Higher 8 bit of Y coordinate */ -#define TMA1217_FINGER2_XY_LOWER4 0x20 /* Lower 4 bits of X and Y */ -#define TMA1217_FINGER2_Z_VALUE 0x22 /* 8 bit Z value for finger 2 */ -#define TMA1217_DEVICE_CTRL 0x23 /* Device Control */ -#define TMA1217_INTERRUPT_ENABLE 0x24 /* Interrupt Enable */ -#define TMA1217_REPORT_MODE 0x2B /* Reporting Mode */ -#define TMA1217_MAX_X_LOWER8 0x31 /* Bit 0-7 for Max X */ -#define TMA1217_MAX_X_HIGHER4 0x32 /* Bit 8-11 for Max X */ -#define TMA1217_MAX_Y_LOWER8 0x33 /* Bit 0-7 for Max Y */ -#define TMA1217_MAX_Y_HIGHER4 0x34 /* Bit 8-11 for Max Y */ -#define TMA1217_DEVICE_CMD_RESET 0x67 /* Device CMD reg for reset */ -#define TMA1217_DEVICE_CMD_REZERO 0x69 /* Device CMD reg for rezero */ - -#define TMA1217_MANUFACTURER_ID 0x73 /* Manufacturer Id */ -#define TMA1217_PRODUCT_FAMILY 0x75 /* Product Family */ -#define TMA1217_FIRMWARE_REVISION 0x76 /* Firmware Revision */ -#define TMA1217_SERIAL_NO_HIGH 0x7C /* Bit 8-15 of device serial no. */ -#define TMA1217_SERIAL_NO_LOW 0x7D /* Bit 0-7 of device serial no. */ -#define TMA1217_PRODUCT_ID_START 0x7E /* Start address for 10 byte ID */ -#define TMA1217_DEVICE_CAPABILITY 0x8B /* Reporting capability */ - - -/* - * The touch position structure. - */ -struct touch_state { - int x; - int y; - bool button; -}; - -/* Device Specific info given by the controller */ -struct cp_dev_info { - u16 maxX; - u16 maxY; -}; - -/* Vendor related info given by the controller */ -struct cp_vendor_info { - u8 vendor_id; - u8 product_family; - u8 firmware_rev; - u16 serial_no; -}; - -/* - * Private structure to store the device details - */ -struct cp_tm1217_device { - struct i2c_client *client; - struct device *dev; - struct cp_vendor_info vinfo; - struct cp_dev_info dinfo; - struct input_dev_info { - char phys[32]; - char name[128]; - struct input_dev *input; - struct touch_state touch; - } cp_input_info[MAX_TOUCH_SUPPORTED]; - - int thread_running; - struct mutex thread_mutex; - - int gpio; -}; - - -/* The following functions are used to read/write registers on the device - * as per the RMI prorocol. Technically, a page select should be written - * before doing read/write but since the register offsets are below 0xFF - * we can use the default value of page which is 0x00 - */ -static int cp_tm1217_read(struct cp_tm1217_device *ts, - u8 *req, int size) -{ - int i, retval; - - /* Send the address */ - retval = i2c_master_send(ts->client, &req[0], 1); - if (retval != 1) { - dev_err(ts->dev, "cp_tm1217: I2C send failed\n"); - return retval; - } - msleep(WAIT_FOR_RESPONSE); - for (i = 0; i < MAX_RETRIES; i++) { - retval = i2c_master_recv(ts->client, &req[1], size); - if (retval == size) - break; - - msleep(INCREMENTAL_DELAY); - dev_dbg(ts->dev, "cp_tm1217: Retry count is %d\n", i); - } - if (retval != size) - dev_err(ts->dev, "cp_tm1217: Read from device failed\n"); - - return retval; -} - -static int cp_tm1217_write(struct cp_tm1217_device *ts, - u8 *req, int size) -{ - int retval; - - /* Send the address and the data to be written */ - retval = i2c_master_send(ts->client, &req[0], size + 1); - if (retval != size + 1) { - dev_err(ts->dev, "cp_tm1217: I2C write failed: %d\n", retval); - return retval; - } - /* Wait for the write to complete. TBD why this is required */ - msleep(WAIT_FOR_RESPONSE); - - return size; -} - -static int cp_tm1217_mask_interrupt(struct cp_tm1217_device *ts) -{ - u8 req[2]; - int retval; - - req[0] = TMA1217_INTERRUPT_ENABLE; - req[1] = 0x0; - retval = cp_tm1217_write(ts, req, 1); - if (retval != 1) - return -EIO; - - return 0; -} - -static int cp_tm1217_unmask_interrupt(struct cp_tm1217_device *ts) -{ - u8 req[2]; - int retval; - - req[0] = TMA1217_INTERRUPT_ENABLE; - req[1] = 0xa; - retval = cp_tm1217_write(ts, req, 1); - if (retval != 1) - return -EIO; - - return 0; -} - -static void process_touch(struct cp_tm1217_device *ts, int index) -{ - int retval; - struct input_dev_info *input_info = - (struct input_dev_info *)&ts->cp_input_info[index]; - u8 xy_data[6]; - - if (index == 0) - xy_data[0] = TMA1217_FINGER1_X_HIGHER8; - else - xy_data[0] = TMA1217_FINGER2_X_HIGHER8; - - retval = cp_tm1217_read(ts, xy_data, 5); - if (retval < 5) { - dev_err(ts->dev, "cp_tm1217: XY read from device failed\n"); - return; - } - - /* Note: Currently not using the Z values but may be requried in - the future. */ - input_info->touch.x = (xy_data[1] << 4) - | (xy_data[3] & 0x0F); - input_info->touch.y = (xy_data[2] << 4) - | ((xy_data[3] & 0xF0) >> 4); - input_report_abs(input_info->input, ABS_X, input_info->touch.x); - input_report_abs(input_info->input, ABS_Y, input_info->touch.y); - input_sync(input_info->input); -} - -static void cp_tm1217_get_data(struct cp_tm1217_device *ts) -{ - u8 req[2]; - int retval, i, finger_touched = 0; - - do { - req[0] = TMA1217_FINGER_STATE; - retval = cp_tm1217_read(ts, req, 1); - if (retval != 1) { - dev_err(ts->dev, - "cp_tm1217: Read from device failed\n"); - continue; - } - finger_touched = 0; - /* Start sampling until the pressure is below - threshold */ - for (i = 0; i < TOUCH_SUPPORTED; i++) { - if (req[1] & 0x3) { - finger_touched++; - if (ts->cp_input_info[i].touch.button == 0) { - /* send the button touch event */ - input_report_key( - ts->cp_input_info[i].input, - BTN_TOUCH, 1); - ts->cp_input_info[i].touch.button = 1; - } - process_touch(ts, i); - } else { - if (ts->cp_input_info[i].touch.button == 1) { - /* send the button release event */ - input_report_key( - ts->cp_input_info[i].input, - BTN_TOUCH, 0); - input_sync(ts->cp_input_info[i].input); - ts->cp_input_info[i].touch.button = 0; - } - } - req[1] = req[1] >> 2; - } - msleep(DELAY_BTWIN_SAMPLE); - } while (finger_touched > 0); -} - -static irqreturn_t cp_tm1217_sample_thread(int irq, void *handle) -{ - struct cp_tm1217_device *ts = handle; - u8 req[2]; - int retval; - - /* Chedk if another thread is already running */ - mutex_lock(&ts->thread_mutex); - if (ts->thread_running == 1) { - mutex_unlock(&ts->thread_mutex); - return IRQ_HANDLED; - } - - ts->thread_running = 1; - mutex_unlock(&ts->thread_mutex); - - /* Mask the interrupts */ - retval = cp_tm1217_mask_interrupt(ts); - - /* Read the Interrupt Status register to find the cause of the - Interrupt */ - req[0] = TMA1217_INT_STATUS; - retval = cp_tm1217_read(ts, req, 1); - if (retval != 1) - goto exit_thread; - - if (!(req[1] & 0x8)) - goto exit_thread; - - cp_tm1217_get_data(ts); - -exit_thread: - /* Unmask the interrupts before going to sleep */ - retval = cp_tm1217_unmask_interrupt(ts); - - mutex_lock(&ts->thread_mutex); - ts->thread_running = 0; - mutex_unlock(&ts->thread_mutex); - - return IRQ_HANDLED; -} - -static int cp_tm1217_init_data(struct cp_tm1217_device *ts) -{ - int retval; - u8 req[2]; - - /* Read the vendor id/ fw revision etc. Ignoring return check as this - is non critical info */ - req[0] = TMA1217_MANUFACTURER_ID; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.vendor_id = req[1]; - - req[0] = TMA1217_PRODUCT_FAMILY; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.product_family = req[1]; - - req[0] = TMA1217_FIRMWARE_REVISION; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.firmware_rev = req[1]; - - req[0] = TMA1217_SERIAL_NO_HIGH; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.serial_no = (req[1] << 8); - - req[0] = TMA1217_SERIAL_NO_LOW; - retval = cp_tm1217_read(ts, req, 1); - ts->vinfo.serial_no = ts->vinfo.serial_no | req[1]; - - req[0] = TMA1217_MAX_X_HIGHER4; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxX = (req[1] & 0xF) << 8; - - req[0] = TMA1217_MAX_X_LOWER8; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxX = ts->dinfo.maxX | req[1]; - - req[0] = TMA1217_MAX_Y_HIGHER4; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxY = (req[1] & 0xF) << 8; - - req[0] = TMA1217_MAX_Y_LOWER8; - retval = cp_tm1217_read(ts, req, 1); - ts->dinfo.maxY = ts->dinfo.maxY | req[1]; - - return 0; - -} - -/* - * Set up a GPIO for use as the interrupt. We can't simply do this at - * boot time because the GPIO drivers themselves may not be around at - * boot/firmware set up time to do the work. Instead defer it to driver - * detection. - */ - -static int cp_tm1217_setup_gpio_irq(struct cp_tm1217_device *ts) -{ - int retval; - - /* Hook up the irq handler */ - retval = gpio_request(ts->gpio, "cp_tm1217_touch"); - if (retval < 0) { - dev_err(ts->dev, "cp_tm1217: GPIO request failed error %d\n", - retval); - return retval; - } - - retval = gpio_direction_input(ts->gpio); - if (retval < 0) { - dev_err(ts->dev, - "cp_tm1217: GPIO direction configuration failed, error %d\n", - retval); - gpio_free(ts->gpio); - return retval; - } - - retval = gpio_to_irq(ts->gpio); - if (retval < 0) { - dev_err(ts->dev, - "cp_tm1217: GPIO to IRQ failed, error %d\n", retval); - gpio_free(ts->gpio); - } - dev_dbg(ts->dev, - "cp_tm1217: Got IRQ number is %d for GPIO %d\n", - retval, ts->gpio); - return retval; -} - -static int cp_tm1217_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct cp_tm1217_device *ts; - struct input_dev *input_dev; - struct input_dev_info *input_info; - struct cp_tm1217_platform_data *pdata; - u8 req[2]; - int i, retval; - - /* No pdata is fine - we then use "normal" IRQ mode */ - - pdata = client->dev.platform_data; - - ts = kzalloc(sizeof(struct cp_tm1217_device), GFP_KERNEL); - if (!ts) - return -ENOMEM; - - ts->client = client; - ts->dev = &client->dev; - i2c_set_clientdata(client, ts); - - ts->thread_running = 0; - mutex_init(&ts->thread_mutex); - - /* Reset the Controller */ - req[0] = TMA1217_DEVICE_CMD_RESET; - req[1] = 0x1; - retval = cp_tm1217_write(ts, req, 1); - if (retval != 1) { - dev_err(ts->dev, "cp_tm1217: Controller reset failed\n"); - kfree(ts); - return -EIO; - } - - /* Clear up the interrupt status from reset. */ - req[0] = TMA1217_INT_STATUS; - retval = cp_tm1217_read(ts, req, 1); - - /* Mask all the interrupts */ - retval = cp_tm1217_mask_interrupt(ts); - if (retval) { - dev_err(ts->dev, "failed to mask interrupts, error: %d\n", - retval); - kfree(ts); - return retval; - } - - /* Read the controller information */ - cp_tm1217_init_data(ts); - - /* The following code will register multiple event devices when - multi-pointer is enabled, the code has not been tested - with MPX */ - for (i = 0; i < TOUCH_SUPPORTED; i++) { - input_dev = input_allocate_device(); - if (input_dev == NULL) { - retval = -ENOMEM; - goto fail; - } - input_info = &ts->cp_input_info[i]; - snprintf(input_info->name, sizeof(input_info->name), - "cp_tm1217_touchscreen_%d", i); - input_dev->name = input_info->name; - snprintf(input_info->phys, sizeof(input_info->phys), - "%s/input%d", dev_name(&client->dev), i); - - input_dev->phys = input_info->phys; - input_dev->id.bustype = BUS_I2C; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - - input_set_abs_params(input_dev, ABS_X, 0, ts->dinfo.maxX, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, ts->dinfo.maxY, 0, 0); - - retval = input_register_device(input_dev); - if (retval) { - dev_err(ts->dev, - "Input dev registration failed for %s\n", - input_dev->name); - input_free_device(input_dev); - goto fail; - } - input_info->input = input_dev; - } - - /* Setup the reporting mode to send an interrupt only when - finger arrives or departs. */ - req[0] = TMA1217_REPORT_MODE; - req[1] = 0x02; - retval = cp_tm1217_write(ts, req, 1); - - /* Setup the device to no sleep mode for now and make it configured */ - req[0] = TMA1217_DEVICE_CTRL; - req[1] = 0x84; - retval = cp_tm1217_write(ts, req, 1); - - /* Check for the status of the device */ - req[0] = TMA1217_DEV_STATUS; - retval = cp_tm1217_read(ts, req, 1); - if (req[1] != 0) { - dev_err(ts->dev, - "cp_tm1217: Device Status 0x%x != 0: config failed\n", - req[1]); - - retval = -EIO; - goto fail; - } - - if (pdata && pdata->gpio) { - ts->gpio = pdata->gpio; - retval = cp_tm1217_setup_gpio_irq(ts); - } else - retval = client->irq; - - if (retval < 0) { - dev_err(ts->dev, "cp_tm1217: GPIO request failed error %d\n", - retval); - goto fail; - } - - client->irq = retval; - - - retval = request_threaded_irq(client->irq, - NULL, cp_tm1217_sample_thread, - IRQF_TRIGGER_FALLING, "cp_tm1217_touch", ts); - if (retval < 0) { - dev_err(ts->dev, "cp_tm1217: Request IRQ error %d\n", retval); - goto fail_gpio; - } - - /* Unmask the interrupts */ - retval = cp_tm1217_unmask_interrupt(ts); - if (retval == 0) - return 0; - - free_irq(client->irq, ts); -fail_gpio: - if (ts->gpio) - gpio_free(ts->gpio); -fail: - /* Clean up before returning failure */ - for (i = 0; i < TOUCH_SUPPORTED; i++) { - if (ts->cp_input_info[i].input) - input_unregister_device(ts->cp_input_info[i].input); - } - kfree(ts); - return retval; - -} - -#ifdef CONFIG_PM_SLEEP - -/* - * cp_tm1217 suspend - * - */ -static int cp_tm1217_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct cp_tm1217_device *ts = i2c_get_clientdata(client); - u8 req[2]; - int retval; - - /* Put the controller to sleep */ - req[0] = TMA1217_DEVICE_CTRL; - retval = cp_tm1217_read(ts, req, 1); - req[1] = (req[1] & 0xF8) | 0x1; - retval = cp_tm1217_write(ts, req, 1); - - if (device_may_wakeup(&client->dev)) - enable_irq_wake(client->irq); - - return 0; -} - -/* - * cp_tm1217_resume - * - */ -static int cp_tm1217_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct cp_tm1217_device *ts = i2c_get_clientdata(client); - u8 req[2]; - int retval; - - /* Take the controller out of sleep */ - req[0] = TMA1217_DEVICE_CTRL; - retval = cp_tm1217_read(ts, req, 1); - req[1] = (req[1] & 0xF8) | 0x4; - retval = cp_tm1217_write(ts, req, 1); - - /* Restore the register settings sinc the power to the - could have been cut off */ - - /* Setup the reporting mode to send an interrupt only when - finger arrives or departs. */ - req[0] = TMA1217_REPORT_MODE; - req[1] = 0x02; - retval = cp_tm1217_write(ts, req, 1); - - /* Setup the device to no sleep mode for now and make it configured */ - req[0] = TMA1217_DEVICE_CTRL; - req[1] = 0x84; - retval = cp_tm1217_write(ts, req, 1); - - /* Setup the interrupt mask */ - retval = cp_tm1217_unmask_interrupt(ts); - - if (device_may_wakeup(&client->dev)) - disable_irq_wake(client->irq); - - return 0; -} - -#endif - -static SIMPLE_DEV_PM_OPS(cp_tm1217_pm_ops, cp_tm1217_suspend, - cp_tm1217_resume); - -/* - * cp_tm1217_remove - * - */ -static int cp_tm1217_remove(struct i2c_client *client) -{ - struct cp_tm1217_device *ts = i2c_get_clientdata(client); - int i; - - free_irq(client->irq, ts); - if (ts->gpio) - gpio_free(ts->gpio); - for (i = 0; i < TOUCH_SUPPORTED; i++) - input_unregister_device(ts->cp_input_info[i].input); - kfree(ts); - return 0; -} - -static struct i2c_device_id cp_tm1217_idtable[] = { - { CPTM1217_DEVICE_NAME, 0 }, - { } -}; - -MODULE_DEVICE_TABLE(i2c, cp_tm1217_idtable); - -static struct i2c_driver cp_tm1217_driver = { - .driver = { - .owner = THIS_MODULE, - .name = CPTM1217_DRIVER_NAME, - .pm = &cp_tm1217_pm_ops, - }, - .id_table = cp_tm1217_idtable, - .probe = cp_tm1217_probe, - .remove = cp_tm1217_remove, -}; - -module_i2c_driver(cp_tm1217_driver); - -MODULE_AUTHOR("Ramesh Agarwal "); -MODULE_DESCRIPTION("Synaptics TM1217 TouchScreen Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/cptm1217/cp_tm1217.h b/drivers/staging/cptm1217/cp_tm1217.h deleted file mode 100644 index 30bad35..0000000 --- a/drivers/staging/cptm1217/cp_tm1217.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __LINUX_I2C_CP_TM1217_H -#define __LINUX_I2C_CP_TM1217_H - -struct cp_tm1217_platform_data { - int gpio; /* If not set uses the IRQ resource 0 */ -}; - -#endif -- cgit v0.10.2 From 76925260a8edba2b62b1639d651b0f3072e7c01b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 28 Jan 2015 09:58:56 -0700 Subject: staging: comedi: addi_apci_1500: fix array access out of bounds error The private data 'pm', 'pt', and 'pp' array members hold the trigger mode parameters for ports A and B. Both ports are 8-bits and the arrays are 16-bits. Array index 0 defines the AND mode and index 1 the OR mode parameters for both ports. The valid triggers to start the async command are 0 to 3 which select the AND/OR mode for each port. The 'pb_trig' (the array index for port B) in apci1500_di_inttrig_start() is incorrect and results in an index of 0 or 2. Fix the calc so that the correct index (0/1) is used. Signed-off-by: H Hartley Sweeten Reported-by: Asaf Vertz Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index fc7db1d..f15aa1f 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -296,7 +296,7 @@ static int apci1500_di_inttrig_start(struct comedi_device *dev, unsigned int pa_mode = Z8536_PAB_MODE_PMS_DISABLE; unsigned int pb_mode = Z8536_PAB_MODE_PMS_DISABLE; unsigned int pa_trig = trig_num & 0x01; - unsigned int pb_trig = trig_num & 0x02; + unsigned int pb_trig = (trig_num >> 1) & 0x01; bool valid_trig = false; unsigned int val; -- cgit v0.10.2 From 14ae190aed8e711614e69d57985ad9fb6e0e8eb3 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Wed, 28 Jan 2015 23:37:01 +0100 Subject: staging: comedi: drivers: ni_atmio: Removed variables that is never used Variable ar assigned a value that is never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 0c5ff28..301f154 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -300,7 +300,6 @@ static int ni_atmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct ni_board_struct *boardtype; - struct ni_private *devpriv; struct pnp_dev *isapnp_dev; int ret; unsigned long iobase; @@ -310,7 +309,6 @@ static int ni_atmio_attach(struct comedi_device *dev, ret = ni_alloc_private(dev); if (ret) return ret; - devpriv = dev->private; iobase = it->options[0]; irq = it->options[1]; -- cgit v0.10.2 From e876e3509701a3ff048725f44a85f7d420b4ec63 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Wed, 28 Jan 2015 23:37:40 +0100 Subject: staging: comedi: drivers: ni_mio_cs: Removed variables that is never used Variable ar assigned a value that is never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index 9b201e4..b152330 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -163,7 +163,6 @@ static int mio_cs_auto_attach(struct comedi_device *dev, { struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); static const struct ni_board_struct *board; - struct ni_private *devpriv; int ret; board = ni_getboardtype(dev, link); @@ -188,8 +187,6 @@ static int mio_cs_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = dev->private; - return ni_E_init(dev, 0, 1); } -- cgit v0.10.2 From e9ba6ec2322319a59d60b14b65fe6fc19e9a40e4 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 29 Jan 2015 23:25:51 +0100 Subject: staging: comedi: drivers: mite: Removed variables that is never used Variable was assigned a value that was never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index ffc9e61..1e537a5 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -494,9 +494,7 @@ EXPORT_SYMBOL_GPL(mite_bytes_read_from_memory_ub); unsigned mite_dma_tcr(struct mite_channel *mite_chan) { struct mite_struct *mite = mite_chan->mite; - int lkar; - lkar = readl(mite->mite_io_addr + MITE_LKAR(mite_chan->channel)); return readl(mite->mite_io_addr + MITE_TCR(mite_chan->channel)); } EXPORT_SYMBOL_GPL(mite_dma_tcr); -- cgit v0.10.2 From 451d61f99583fe8b82b03c3a52cc1619edd45817 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 29 Jan 2015 23:30:47 +0100 Subject: staging: comedi: drivers: addi-data: hwdrv_apci3501: Removed variables that is never used Variable was assigned a value that was never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c index 339519a..1f2f781 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c @@ -93,7 +93,6 @@ static int apci3501_write_insn_timer(struct comedi_device *dev, { struct apci3501_private *devpriv = dev->private; unsigned int ul_Command1 = 0; - int i_Temp; if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) { @@ -135,7 +134,7 @@ static int apci3501_write_insn_timer(struct comedi_device *dev, } } - i_Temp = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1; + inl(dev->iobase + APCI3501_TIMER_STATUS_REG); return insn->n; } -- cgit v0.10.2 From fa0ca8e7c93442a2cb6be895cfb3f067079c4f0a Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 29 Jan 2015 23:43:36 +0100 Subject: staging: comedi: drivers: rtd520: Removed variables that is never used Variable was assigned a value that was never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 3ccdade..c94ad12 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1027,8 +1027,6 @@ static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct rtd_private *devpriv = dev->private; - u32 overrun; - u16 status; /* pacer stop source: SOFTWARE */ writel(0, dev->mmio + LAS0_PACER_STOP); @@ -1036,8 +1034,6 @@ static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) writel(0, dev->mmio + LAS0_ADC_CONVERSION); writew(0, dev->mmio + LAS0_IT); devpriv->ai_count = 0; /* stop and don't transfer any more */ - status = readw(dev->mmio + LAS0_IT); - overrun = readl(dev->mmio + LAS0_OVERRUN) & 0xffff; writel(0, dev->mmio + LAS0_ADC_FIFO_CLEAR); return 0; } -- cgit v0.10.2 From ba9b6ef4058a065558b2d55b943fa10cd8540207 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 29 Jan 2015 23:34:55 +0100 Subject: staging: comedi: drivers: addi_apci_3501: Removed variables that is never used Variable was assigned a value that was never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index a726efc..5961f19 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -267,7 +267,6 @@ static irqreturn_t apci3501_interrupt(int irq, void *d) struct apci3501_private *devpriv = dev->private; unsigned int ui_Timer_AOWatchdog; unsigned long ul_Command1; - int i_temp; /* Disable Interrupt */ ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); @@ -285,7 +284,7 @@ static irqreturn_t apci3501_interrupt(int irq, void *d) ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG); ul_Command1 = ((ul_Command1 & 0xFFFFF9FDul) | 1 << 1); outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG); - i_temp = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1; + inl(dev->iobase + APCI3501_TIMER_STATUS_REG); return IRQ_HANDLED; } -- cgit v0.10.2 From 3caef5a4cac9d7c27d7362be63e799c199111a62 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 29 Jan 2015 23:50:09 +0100 Subject: staging: comedi: drivers: usbduxsigma: Removed variables that is never used Variable was assigned a value that was never used. I have also removed all the code that thereby serves no purpose. This was found using a static code analysis program called cppcheck Signed-off-by: Rickard Strandqvist Reviewed-by: Ian Abbott Reviewed-by: Bernd Porr Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 378c449..394969b 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -214,7 +214,6 @@ static void usbduxsigma_ai_handle_urb(struct comedi_device *dev, struct usbduxsigma_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - unsigned int dio_state; uint32_t val; int ret; int i; @@ -223,9 +222,6 @@ static void usbduxsigma_ai_handle_urb(struct comedi_device *dev, if (devpriv->ai_counter == 0) { devpriv->ai_counter = devpriv->ai_timer; - /* get the state of the dio pins to allow external trigger */ - dio_state = be32_to_cpu(devpriv->in_buf[0]); - /* get the data from the USB bus and hand it over to comedi */ for (i = 0; i < cmd->chanlist_len; i++) { /* transfer data, note first byte is the DIO state */ -- cgit v0.10.2 From f6fef5df1accf2851d4c357eddcde8bcaf8349d6 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:45 +0000 Subject: staging: comedi: comedi_fops.c: reformat copyright header Use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 68bfe92..bb2e796 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1,20 +1,20 @@ /* - comedi/comedi_fops.c - comedi kernel module - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-2000 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/comedi_fops.c + * comedi kernel module + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -- cgit v0.10.2 From dd630cdeb160fc4f219481a68771d683d59178ee Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:46 +0000 Subject: staging: comedi: comedi_fops.c: document exported functions Add kerneldoc for exported functions `comedi_dev_put()`, `comedi_dev_get_from_minor()`, `comedi_is_subdevice_running()`, and `comedi_event()`. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index bb2e796..8f65097 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -113,6 +113,18 @@ static void comedi_dev_kref_release(struct kref *kref) kfree(dev); } +/** + * comedi_dev_put - release a use of a comedi device structure + * @dev: comedi_device struct + * + * Must be called when a user of a comedi device is finished with it. + * When the last user of the comedi device calls this function, the + * comedi device is destroyed. + * + * Return 1 if the comedi device is destroyed by this call or dev is + * NULL, otherwise return 0. Callers must not assume the comedi + * device is still valid if this function returns 0. + */ int comedi_dev_put(struct comedi_device *dev) { if (dev) @@ -220,6 +232,18 @@ static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor) return dev; } +/** + * comedi_dev_get_from_minor - get comedi device by minor device number + * @minor: minor device number + * + * Finds the comedi device associated by the minor device number, if any, + * and increments its reference count. The comedi device is prevented from + * being freed until a matching call is made to comedi_dev_put(). + * + * Return a pointer to the comedi device if it exists, with its usage + * reference incremented. Return NULL if no comedi device exists with the + * specified minor device number. + */ struct comedi_device *comedi_dev_get_from_minor(unsigned minor) { if (minor < COMEDI_NUM_BOARD_MINORS) @@ -600,6 +624,13 @@ static unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s) return runflags; } +/** + * comedi_is_subdevice_running - check if async command running on subdevice + * @s: comedi_subdevice struct + * + * Return true if an asynchronous comedi command is active on the comedi + * subdevice, else return false. + */ bool comedi_is_subdevice_running(struct comedi_subdevice *s) { unsigned runflags = comedi_get_subdevice_runflags(s); @@ -2584,6 +2615,17 @@ static const struct file_operations comedi_fops = { .llseek = noop_llseek, }; +/** + * comedi_event - handle events for asynchronous comedi command + * @dev: comedi_device struct + * @s: comedi_subdevice struct associated with dev + * Context: interrupt (usually), s->spin_lock spin-lock not held + * + * If an asynchronous comedi command is active on the subdevice, process + * any COMEDI_CB_... event flags that have been set, usually by an + * interrupt handler. These may change the run state of the asynchronous + * command, wake a task, and/or send a SIGIO signal. + */ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_async *async = s->async; -- cgit v0.10.2 From 18e01b24a7b60534a1871085a27bfee7d694bc55 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:47 +0000 Subject: staging: comedi: comedi_fops.c: reformat ioctl handler comments The unlocked_ioctl handler calls a different function to handle each supported ioctl command code. Most of these have a block comment indicating which command code it handles, a brief description, and an informal description of the inputs and outputs. These block comments are formatted in various styles. Reformat them to the usual block comment style and do a bit of rewording for consistency. The comment block for the `COMEDI_CMD` ioctl is missing, so add one. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 8f65097..5403af1 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -740,18 +740,18 @@ static int is_device_busy(struct comedi_device *dev) } /* - COMEDI_DEVCONFIG - device config ioctl - - arg: - pointer to devconfig structure - - reads: - devconfig structure at arg - - writes: - none -*/ + * COMEDI_DEVCONFIG ioctl + * attaches (and configures) or detaches a legacy device + * + * arg: + * pointer to comedi_devconfig structure (NULL if detaching) + * + * reads: + * comedi_devconfig structure (if attaching) + * + * writes: + * nothing + */ static int do_devconfig_ioctl(struct comedi_device *dev, struct comedi_devconfig __user *arg) { @@ -792,19 +792,18 @@ static int do_devconfig_ioctl(struct comedi_device *dev, } /* - COMEDI_BUFCONFIG - buffer configuration ioctl - - arg: - pointer to bufconfig structure - - reads: - bufconfig at arg - - writes: - modified bufconfig at arg - -*/ + * COMEDI_BUFCONFIG ioctl + * buffer configuration + * + * arg: + * pointer to comedi_bufconfig structure + * + * reads: + * comedi_bufconfig structure + * + * writes: + * modified comedi_bufconfig structure + */ static int do_bufconfig_ioctl(struct comedi_device *dev, struct comedi_bufconfig __user *arg) { @@ -854,19 +853,18 @@ copyback: } /* - COMEDI_DEVINFO - device info ioctl - - arg: - pointer to devinfo structure - - reads: - none - - writes: - devinfo structure - -*/ + * COMEDI_DEVINFO ioctl + * device info + * + * arg: + * pointer to comedi_devinfo structure + * + * reads: + * nothing + * + * writes: + * comedi_devinfo structure + */ static int do_devinfo_ioctl(struct comedi_device *dev, struct comedi_devinfo __user *arg, struct file *file) @@ -901,19 +899,18 @@ static int do_devinfo_ioctl(struct comedi_device *dev, } /* - COMEDI_SUBDINFO - subdevice info ioctl - - arg: - pointer to array of subdevice info structures - - reads: - none - - writes: - array of subdevice info structures at arg - -*/ + * COMEDI_SUBDINFO ioctl + * subdevices info + * + * arg: + * pointer to array of comedi_subdinfo structures + * + * reads: + * nothing + * + * writes: + * array of comedi_subdinfo structures + */ static int do_subdinfo_ioctl(struct comedi_device *dev, struct comedi_subdinfo __user *arg, void *file) { @@ -975,19 +972,19 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, } /* - COMEDI_CHANINFO - subdevice info ioctl - - arg: - pointer to chaninfo structure - - reads: - chaninfo structure at arg - - writes: - arrays at elements of chaninfo structure - -*/ + * COMEDI_CHANINFO ioctl + * subdevice channel info + * + * arg: + * pointer to comedi_chaninfo structure + * + * reads: + * comedi_chaninfo structure + * + * writes: + * array of maxdata values to chaninfo->maxdata_list if requested + * array of range table lengths to chaninfo->range_table_list if requested + */ static int do_chaninfo_ioctl(struct comedi_device *dev, struct comedi_chaninfo __user *arg) { @@ -1035,20 +1032,19 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, return 0; } - /* - COMEDI_BUFINFO - buffer information ioctl - - arg: - pointer to bufinfo structure - - reads: - bufinfo at arg - - writes: - modified bufinfo at arg - - */ +/* + * COMEDI_BUFINFO ioctl + * buffer information + * + * arg: + * pointer to comedi_bufinfo structure + * + * reads: + * comedi_bufinfo structure + * + * writes: + * modified comedi_bufinfo structure + */ static int do_bufinfo_ioctl(struct comedi_device *dev, struct comedi_bufinfo __user *arg, void *file) { @@ -1357,19 +1353,19 @@ out: } /* - * COMEDI_INSNLIST - * synchronous instructions + * COMEDI_INSNLIST ioctl + * synchronous instruction list * - * arg: - * pointer to sync cmd structure + * arg: + * pointer to comedi_insnlist structure * - * reads: - * sync cmd struct at arg - * instruction list - * data (for writes) + * reads: + * comedi_insnlist structure + * array of comedi_insn structures from insnlist->insns pointer + * data (for writes) from insns[].data pointers * - * writes: - * data (for reads) + * writes: + * data (for reads) to insns[].data pointers */ /* arbitrary limits */ #define MAX_SAMPLES 256 @@ -1446,18 +1442,18 @@ error: } /* - * COMEDI_INSN - * synchronous instructions + * COMEDI_INSN ioctl + * synchronous instruction * - * arg: - * pointer to insn + * arg: + * pointer to comedi_insn structure * - * reads: - * struct comedi_insn struct at arg - * data (for writes) + * reads: + * comedi_insn structure + * data (for writes) from insn->data pointer * - * writes: - * data (for reads) + * writes: + * data (for reads) to insn->data pointer */ static int do_insn_ioctl(struct comedi_device *dev, struct comedi_insn __user *arg, void *file) @@ -1589,6 +1585,20 @@ static int __comedi_get_user_chanlist(struct comedi_device *dev, return 0; } +/* + * COMEDI_CMD ioctl + * asynchronous acquisition command set-up + * + * arg: + * pointer to comedi_cmd structure + * + * reads: + * comedi_cmd structure + * channel/range list from cmd->chanlist pointer + * + * writes: + * possibly modified comedi_cmd structure (when -EAGAIN returned) + */ static int do_cmd_ioctl(struct comedi_device *dev, struct comedi_cmd __user *arg, void *file) { @@ -1684,20 +1694,19 @@ cleanup: } /* - COMEDI_CMDTEST - command testing ioctl - - arg: - pointer to cmd structure - - reads: - cmd structure at arg - channel/range list - - writes: - modified cmd structure at arg - -*/ + * COMEDI_CMDTEST ioctl + * asynchronous aquisition command testing + * + * arg: + * pointer to comedi_cmd structure + * + * reads: + * comedi_cmd structure + * channel/range list from cmd->chanlist pointer + * + * writes: + * possibly modified comedi_cmd structure + */ static int do_cmdtest_ioctl(struct comedi_device *dev, struct comedi_cmd __user *arg, void *file) { @@ -1740,20 +1749,18 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, } /* - COMEDI_LOCK - lock subdevice - - arg: - subdevice number - - reads: - none - - writes: - none - -*/ - + * COMEDI_LOCK ioctl + * lock subdevice + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_lock_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { @@ -1776,21 +1783,18 @@ static int do_lock_ioctl(struct comedi_device *dev, unsigned long arg, } /* - COMEDI_UNLOCK - unlock subdevice - - arg: - subdevice number - - reads: - none - - writes: - none - - This function isn't protected by the semaphore, since - we already own the lock. -*/ + * COMEDI_UNLOCK ioctl + * unlock subdevice + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_unlock_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { @@ -1813,19 +1817,18 @@ static int do_unlock_ioctl(struct comedi_device *dev, unsigned long arg, } /* - COMEDI_CANCEL - cancel acquisition ioctl - - arg: - subdevice number - - reads: - nothing - - writes: - nothing - -*/ + * COMEDI_CANCEL ioctl + * cancel asynchronous acquisition + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { @@ -1847,19 +1850,18 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg, } /* - COMEDI_POLL ioctl - instructs driver to synchronize buffers - - arg: - subdevice number - - reads: - nothing - - writes: - nothing - -*/ + * COMEDI_POLL ioctl + * instructs driver to synchronize buffers + * + * arg: + * subdevice number + * + * reads: + * nothing + * + * writes: + * nothing + */ static int do_poll_ioctl(struct comedi_device *dev, unsigned long arg, void *file) { -- cgit v0.10.2 From 1a4f01b74f8c26a97e343ba8a93000781b3eb76d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:48 +0000 Subject: staging: comedi: range.c: reformat ioctl handler comment The unlocked_ioctl handler in "comedi_fops.c" calls a different function to handle each supported ioctl command code. Most of these have a block comment indicating which command code it handles, a brief description, and an informal description of the inputs and outputs. These block comments were formatted in various styles, but have been reformatted to use the usual block comment style. The block comment for the handler function for the `COMEDI_RANGEINFO` ioctl code is in "range.c". Reformat it to use the usual block command style to match the others. Reword it a bit for consistency. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index 9a1dc56..00e71c7 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -42,18 +42,18 @@ const struct comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none} } }; EXPORT_SYMBOL_GPL(range_unknown); /* - COMEDI_RANGEINFO - range information ioctl - - arg: - pointer to rangeinfo structure - - reads: - range info structure - - writes: - n struct comedi_krange structures to rangeinfo->range_ptr -*/ + * COMEDI_RANGEINFO ioctl + * range information + * + * arg: + * pointer to comedi_rangeinfo structure + * + * reads: + * comedi_rangeinfo structure + * + * writes: + * array of comedi_krange structures to rangeinfo->range_ptr pointer + */ int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo __user *arg) { -- cgit v0.10.2 From 5824ec7fe71c1da49a170fb18bfba3d1097caa39 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:49 +0000 Subject: staging: comedi: range.c: reformat copyright comment Use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index 00e71c7..6a393b2 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -1,20 +1,20 @@ /* - module/range.c - comedi routines for voltage ranges - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1997-8 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedi/range.c + * comedi routines for voltage ranges + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-8 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #include #include "comedidev.h" -- cgit v0.10.2 From a2aab8b481eb85ec445c2b50cfa263236aad07bd Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Wed, 28 Jan 2015 18:41:50 +0000 Subject: staging: comedi: comedi_fops.c: reformat remaining block comments Reformat remaining block comments to use the usual block comment style. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 5403af1..727640e 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -347,8 +347,7 @@ static int resize_async_buffer(struct comedi_device *dev, return -EBUSY; } - /* make sure buffer is an integral number of pages - * (we round up) */ + /* make sure buffer is an integral number of pages (we round up) */ new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; retval = comedi_buf_alloc(dev, s, new_size); @@ -671,7 +670,7 @@ void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size) EXPORT_SYMBOL_GPL(comedi_alloc_spriv); /* - This function restores a subdevice to an idle state. + * This function restores a subdevice to an idle state. */ static void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s) @@ -1162,8 +1161,10 @@ static int check_insn_config_length(struct comedi_insn *insn, if (insn->n == 6) return 0; break; - /* by default we allow the insn since we don't have checks for - * all possible cases yet */ + /* + * by default we allow the insn since we don't have checks for + * all possible cases yet + */ default: pr_warn("No check for data length of config insn id %i is implemented\n", data[0]); @@ -1314,9 +1315,11 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, if (insn->n != 2) { ret = -EINVAL; } else { - /* Most drivers ignore the base channel in + /* + * Most drivers ignore the base channel in * insn->chanspec. Fix this here if - * the subdevice has <= 32 channels. */ + * the subdevice has <= 32 channels. + */ unsigned int orig_mask = data[0]; unsigned int shift = 0; @@ -1977,8 +1980,10 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, mutex_lock(&dev->mutex); - /* Device config is special, because it must work on - * an unconfigured device. */ + /* + * Device config is special, because it must work on + * an unconfigured device. + */ if (cmd == COMEDI_DEVCONFIG) { if (minor >= COMEDI_NUM_BOARD_MINORS) { /* Device config not appropriate on non-board minors. */ @@ -1990,8 +1995,10 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, if (rc == 0) { if (arg == 0 && dev->minor >= comedi_num_legacy_minors) { - /* Successfully unconfigured a dynamically - * allocated device. Try and remove it. */ + /* + * Successfully unconfigured a dynamically + * allocated device. Try and remove it. + */ if (comedi_clear_board_dev(dev)) { mutex_unlock(&dev->mutex); comedi_free_board_dev(dev); -- cgit v0.10.2 From 00f457b5755824cb5fc91584644c1831eb6d536e Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:17 +0000 Subject: staging: comedi: add comedi_pcmcia.h Add a new header that Comedi PCMCIA drivers can include instead of "comedidev.h". Currently, it just pulls in , and "comedidev.h", but the plan is to migrate the PCMCIA-specific stuff from "comedidev.h" here. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_pcmcia.h b/drivers/staging/comedi/comedi_pcmcia.h new file mode 100644 index 0000000..ba073af --- /dev/null +++ b/drivers/staging/comedi/comedi_pcmcia.h @@ -0,0 +1,31 @@ +/* + * comedi_pcmcia.h + * header file for Comedi PCMCIA drivers + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1997-2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _COMEDI_PCMCIA_H +#define _COMEDI_PCMCIA_H + +#include +#include + +#include "comedidev.h" + +/* + * TODO: Move PCMCIA-specific stuff into here from "comedidev.h". + */ + +#endif /* _COMEDI_PCMCIA_H */ -- cgit v0.10.2 From a1d49aeed0035adebb874ca30336ba2160321063 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:18 +0000 Subject: staging: comedi: comedi_pcmcia.c: include new "comedi_pcmcia.h" header Include the new "comedi_pcmcia.h" header instead of , and "comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_pcmcia.c b/drivers/staging/comedi/comedi_pcmcia.c index 0529bae..7e78439 100644 --- a/drivers/staging/comedi/comedi_pcmcia.c +++ b/drivers/staging/comedi/comedi_pcmcia.c @@ -19,10 +19,7 @@ #include #include -#include -#include - -#include "comedidev.h" +#include "comedi_pcmcia.h" /** * comedi_to_pcmcia_dev() - comedi_device pointer to pcmcia_device pointer. -- cgit v0.10.2 From 5df18b6c05fb44d08919ca53f1fb4fb283a279da Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:19 +0000 Subject: staging: comedi: cb_das16_cs: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 0a48d2a..1079b6c 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -38,10 +38,7 @@ Status: experimental #include #include -#include "../comedidev.h" - -#include -#include +#include "../comedi_pcmcia.h" #include "comedi_fc.h" #include "8253.h" -- cgit v0.10.2 From 0519c8f686150fc1a0676eeb0e7aee3620724c3f Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:20 +0000 Subject: staging: comedi: das08_cs: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index f3ccc2c..93fab68 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -41,10 +41,7 @@ Command support does not exist, but could be added for this board. #include -#include "../comedidev.h" - -#include -#include +#include "../comedi_pcmcia.h" #include "das08.h" -- cgit v0.10.2 From a411febedebeeb61f264daa9d62b456ad1a7a072 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:21 +0000 Subject: staging: comedi: ni_daq_700: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 5e472cb..8f6396e 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -51,10 +51,7 @@ #include #include -#include "../comedidev.h" - -#include -#include +#include "../comedi_pcmcia.h" /* daqcard700 registers */ #define DIO_W 0x04 /* WO 8bit */ -- cgit v0.10.2 From 51d5483f7b7b753dfada03408c3aaf6610b46137 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:22 +0000 Subject: staging: comedi: ni_daq_dio24: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , , and "../comedidev.h". isn't needed and the others will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index 8cfabdb..a208cb3 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -32,11 +32,7 @@ the PCMCIA interface. */ #include -#include "../comedidev.h" - -#include -#include -#include +#include "../comedi_pcmcia.h" #include "8255.h" -- cgit v0.10.2 From 778edf45e666a936581cc29ad71c7d1d0efc4d92 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:23 +0000 Subject: staging: comedi: ni_labpc_cs: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , , and "../comedidev.h". isn't needed and the others will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index ece0010..746c4cd9 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -55,11 +55,7 @@ NI manuals: #include -#include "../comedidev.h" - -#include -#include -#include +#include "../comedi_pcmcia.h" #include "ni_labpc.h" -- cgit v0.10.2 From 064c654465a6c48d7d7c91d59c449c85fd14e6fa Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:24 +0000 Subject: staging: comedi: ni_mio_cs: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , and "../comedidev.h", which will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index b152330..e3d821b 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -37,16 +37,12 @@ See the notes in the ni_atmio.o driver. */ #include -#include "../comedidev.h" - #include +#include "../comedi_pcmcia.h" #include "ni_stc.h" #include "8255.h" -#include -#include - /* * AT specific setup */ -- cgit v0.10.2 From f0dff1a4b1fb21c499eb25969abea41dcabf9987 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:25 +0000 Subject: staging: comedi: quatech_daqp_cs: include new "comedi_pcmcia.h" header Include the new "../comedi_pcmcia.h" header instead of , , and "../comedidev.h". isn't needed and the others will now get included indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index dd06734..8387fd0 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -48,15 +48,10 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308 */ #include -#include "../comedidev.h" #include - -#include -#include -#include - #include +#include "../comedi_pcmcia.h" #include "comedi_fc.h" struct daqp_private { -- cgit v0.10.2 From aedd2e80c9409084b68b1c3a5a4e25ddc212d64a Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 30 Jan 2015 09:57:26 +0000 Subject: staging: comedi: comedi_pcmcia.h: move PCMCIA stuff out of comedidev.h Move the PCMCIA-specific stuff out of "comedidev.h" into "comedi_pcmcia.h". Comedi PCMCIA drivers now include "comedi_pcmcia.h" instead of "comedidev.h", which now gets pulled in indirectly. Signed-off-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/comedi_pcmcia.h b/drivers/staging/comedi/comedi_pcmcia.h index ba073af..5d3db2b 100644 --- a/drivers/staging/comedi/comedi_pcmcia.h +++ b/drivers/staging/comedi/comedi_pcmcia.h @@ -24,8 +24,32 @@ #include "comedidev.h" -/* - * TODO: Move PCMCIA-specific stuff into here from "comedidev.h". +struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *); + +int comedi_pcmcia_enable(struct comedi_device *, + int (*conf_check)(struct pcmcia_device *, void *)); +void comedi_pcmcia_disable(struct comedi_device *); + +int comedi_pcmcia_auto_config(struct pcmcia_device *, struct comedi_driver *); +void comedi_pcmcia_auto_unconfig(struct pcmcia_device *); + +int comedi_pcmcia_driver_register(struct comedi_driver *, + struct pcmcia_driver *); +void comedi_pcmcia_driver_unregister(struct comedi_driver *, + struct pcmcia_driver *); + +/** + * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver + * @__comedi_driver: comedi_driver struct + * @__pcmcia_driver: pcmcia_driver struct + * + * Helper macro for comedi PCMCIA drivers which do not do anything special + * in module init/exit. This eliminates a lot of boilerplate. Each + * module may only use this macro once, and calling it replaces + * module_init() and module_exit() */ +#define module_comedi_pcmcia_driver(__comedi_driver, __pcmcia_driver) \ + module_driver(__comedi_driver, comedi_pcmcia_driver_register, \ + comedi_pcmcia_driver_unregister, &(__pcmcia_driver)) #endif /* _COMEDI_PCMCIA_H */ diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index bc1dfc1..e138eb0 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -596,37 +596,4 @@ void comedi_pci_driver_unregister(struct comedi_driver *, struct pci_driver *); module_driver(__comedi_driver, comedi_pci_driver_register, \ comedi_pci_driver_unregister, &(__pci_driver)) -/* comedi_pcmcia.c - comedi PCMCIA driver specific functions */ - -struct pcmcia_driver; -struct pcmcia_device; - -struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *); - -int comedi_pcmcia_enable(struct comedi_device *, - int (*conf_check)(struct pcmcia_device *, void *)); -void comedi_pcmcia_disable(struct comedi_device *); - -int comedi_pcmcia_auto_config(struct pcmcia_device *, struct comedi_driver *); -void comedi_pcmcia_auto_unconfig(struct pcmcia_device *); - -int comedi_pcmcia_driver_register(struct comedi_driver *, - struct pcmcia_driver *); -void comedi_pcmcia_driver_unregister(struct comedi_driver *, - struct pcmcia_driver *); - -/** - * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver - * @__comedi_driver: comedi_driver struct - * @__pcmcia_driver: pcmcia_driver struct - * - * Helper macro for comedi PCMCIA drivers which do not do anything special - * in module init/exit. This eliminates a lot of boilerplate. Each - * module may only use this macro once, and calling it replaces - * module_init() and module_exit() - */ -#define module_comedi_pcmcia_driver(__comedi_driver, __pcmcia_driver) \ - module_driver(__comedi_driver, comedi_pcmcia_driver_register, \ - comedi_pcmcia_driver_unregister, &(__pcmcia_driver)) - #endif /* _COMEDIDEV_H */ -- cgit v0.10.2 From 369ba5b8310b401bd04d73d39f57d50a06ef8c09 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Wed, 4 Feb 2015 12:02:33 -0500 Subject: staging: comedi: dt282x: condition with no effect - if identical to else The if and the else branch code are identical - so the condition has no effect on the effective code - this patch removes the condition and the duplicated code. Signed-off-by: Nicholas Mc Guire Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 051dfb2..db21d21 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -685,14 +685,7 @@ static int dt282x_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); - if (cmd->scan_begin_src == TRIG_FOLLOW) { - /* internal trigger */ - err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - } else { - /* external trigger */ - /* should be level/edge, hi/lo specification here */ - err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); - } + err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 4000); -- cgit v0.10.2 From d0e9ed58f46b5aa101f90834a87c4464814e1721 Mon Sep 17 00:00:00 2001 From: Bastian Plettner Date: Wed, 28 Jan 2015 20:25:02 +0100 Subject: staging: speakup: Remove unnecessary space This patch fixes the checkpath.pl warning: ERROR: space prohibited before that ',' (ctx:WxE) + MSG_FIRST_INDEX , And removes the unnecessary space. Signed-off-by: Bastian Plettner Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/speakup/i18n.h b/drivers/staging/speakup/i18n.h index 16a0871..326d086 100644 --- a/drivers/staging/speakup/i18n.h +++ b/drivers/staging/speakup/i18n.h @@ -3,7 +3,7 @@ /* Internationalization declarations */ enum msg_index_t { - MSG_FIRST_INDEX , + MSG_FIRST_INDEX, MSG_ANNOUNCEMENTS_START = MSG_FIRST_INDEX, MSG_BLANK = MSG_ANNOUNCEMENTS_START, MSG_IAM_ALIVE, -- cgit v0.10.2 From 25ef8072fbea1843c29c24cf82e6913c504db55c Mon Sep 17 00:00:00 2001 From: Simon Guo Date: Thu, 29 Jan 2015 13:33:17 +0800 Subject: STAGING: Fix pcl818.c coding style issue: code indent should use tabs where possible Correct one coding style problem(detected by checkpatch.pl) in pcl818.c. - code indent should use tabs where possible It is fixed by reformatting the comment block to usual comment style. And with the reformatting, following coding style problem is also fixed: - please, no space before tabs Signed-off-by: Simon Guo Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index a10ce41..47a2f7b 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1,102 +1,95 @@ /* - comedi/drivers/pcl818.c - - Author: Michal Dobes - - hardware driver for Advantech cards: - card: PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818, PCL-718 - driver: pcl818l, pcl818h, pcl818hd, pcl818hg, pcl818, pcl718 -*/ -/* -Driver: pcl818 -Description: Advantech PCL-818 cards, PCL-718 -Author: Michal Dobes -Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h), - PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818), - PCL-718 (pcl718) -Status: works - -All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO. -Differences are only at maximal sample speed, range list and FIFO -support. -The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support -only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0. -PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO -but this code is untested. -A word or two about DMA. Driver support DMA operations at two ways: -1) DMA uses two buffers and after one is filled then is generated - INT and DMA restart with second buffer. With this mode I'm unable run - more that 80Ksamples/secs without data dropouts on K6/233. -2) DMA uses one buffer and run in autoinit mode and the data are - from DMA buffer moved on the fly with 2kHz interrupts from RTC. - This mode is used if the interrupt 8 is available for allocation. - If not, then first DMA mode is used. With this I can run at - full speed one card (100ksamples/secs) or two cards with - 60ksamples/secs each (more is problem on account of ISA limitations). - To use this mode you must have compiled kernel with disabled - "Enhanced Real Time Clock Support". - Maybe you can have problems if you use xntpd or similar. - If you've data dropouts with DMA mode 2 then: - a) disable IDE DMA - b) switch text mode console to fb. - - Options for PCL-818L: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA (0=disable, 1, 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0, 5=A/D input -5V.. +5V - 1, 10=A/D input -10V..+10V - [5] - 0, 5=D/A output 0-5V (internal reference -5V) - 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknown (external reference) - - Options for PCL-818, PCL-818H: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA (0=disable, 1, 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0, 5=D/A output 0-5V (internal reference -5V) - 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknown (external reference) - - Options for PCL-818HD, PCL-818HG: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA/FIFO (-1=use FIFO, 0=disable both FIFO and DMA, - 1=use DMA ch 1, 3=use DMA ch 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0, 5=D/A output 0-5V (internal reference -5V) - 1, 10=D/A output 0-10V (internal reference -10V) - 2 =D/A output unknown (external reference) - - Options for PCL-718: - [0] - IO Base - [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) - [2] - DMA (0=disable, 1, 3) - [3] - 0, 10=10MHz clock for 8254 - 1= 1MHz clock for 8254 - [4] - 0=A/D Range is +/-10V - 1= +/-5V - 2= +/-2.5V - 3= +/-1V - 4= +/-0.5V - 5= user defined bipolar - 6= 0-10V - 7= 0-5V - 8= 0-2V - 9= 0-1V - 10= user defined unipolar - [5] - 0, 5=D/A outputs 0-5V (internal reference -5V) - 1, 10=D/A outputs 0-10V (internal reference -10V) - 2=D/A outputs unknown (external reference) - [6] - 0, 60=max 60kHz A/D sampling - 1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed) - -*/ + * comedi/drivers/pcl818.c + * + * Driver: pcl818 + * Description: Advantech PCL-818 cards, PCL-718 + * Author: Michal Dobes + * Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h), + * PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818), + * PCL-718 (pcl718) + * Status: works + * + * All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO. + * Differences are only at maximal sample speed, range list and FIFO + * support. + * The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support + * only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0. + * PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO + * but this code is untested. + * A word or two about DMA. Driver support DMA operations at two ways: + * 1) DMA uses two buffers and after one is filled then is generated + * INT and DMA restart with second buffer. With this mode I'm unable run + * more that 80Ksamples/secs without data dropouts on K6/233. + * 2) DMA uses one buffer and run in autoinit mode and the data are + * from DMA buffer moved on the fly with 2kHz interrupts from RTC. + * This mode is used if the interrupt 8 is available for allocation. + * If not, then first DMA mode is used. With this I can run at + * full speed one card (100ksamples/secs) or two cards with + * 60ksamples/secs each (more is problem on account of ISA limitations). + * To use this mode you must have compiled kernel with disabled + * "Enhanced Real Time Clock Support". + * Maybe you can have problems if you use xntpd or similar. + * If you've data dropouts with DMA mode 2 then: + * a) disable IDE DMA + * b) switch text mode console to fb. + * + * Options for PCL-818L: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0, 5=A/D input -5V.. +5V + * 1, 10=A/D input -10V..+10V + * [5] - 0, 5=D/A output 0-5V (internal reference -5V) + * 1, 10=D/A output 0-10V (internal reference -10V) + * 2 =D/A output unknown (external reference) + * + * Options for PCL-818, PCL-818H: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0, 5=D/A output 0-5V (internal reference -5V) + * 1, 10=D/A output 0-10V (internal reference -10V) + * 2 =D/A output unknown (external reference) + * + * Options for PCL-818HD, PCL-818HG: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA/FIFO (-1=use FIFO, 0=disable both FIFO and DMA, + * 1=use DMA ch 1, 3=use DMA ch 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0, 5=D/A output 0-5V (internal reference -5V) + * 1, 10=D/A output 0-10V (internal reference -10V) + * 2 =D/A output unknown (external reference) + * + * Options for PCL-718: + * [0] - IO Base + * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7) + * [2] - DMA (0=disable, 1, 3) + * [3] - 0, 10=10MHz clock for 8254 + * 1= 1MHz clock for 8254 + * [4] - 0=A/D Range is +/-10V + * 1= +/-5V + * 2= +/-2.5V + * 3= +/-1V + * 4= +/-0.5V + * 5= user defined bipolar + * 6= 0-10V + * 7= 0-5V + * 8= 0-2V + * 9= 0-1V + * 10= user defined unipolar + * [5] - 0, 5=D/A outputs 0-5V (internal reference -5V) + * 1, 10=D/A outputs 0-10V (internal reference -10V) + * 2=D/A outputs unknown (external reference) + * [6] - 0, 60=max 60kHz A/D sampling + * 1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed) + * + */ #include #include -- cgit v0.10.2 From 8004a0c9b0e694c25e1ea7e058c64dff459f19f9 Mon Sep 17 00:00:00 2001 From: Simon Guo Date: Thu, 29 Jan 2015 13:34:28 +0800 Subject: STAGING: Fix pcl818.c coding style issue: line over 80 characters Correct one coding style problem(detected by checkpatch.pl) in pcl818.c. - line over 80 characters Signed-off-by: Simon Guo Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 47a2f7b..7e4cdea 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -297,9 +297,11 @@ static const struct pcl818_board boardtypes[] = { struct pcl818_private { struct comedi_isadma *dma; - unsigned int ns_min; /* manimal allowed delay between samples (in us) for actual card */ + /* manimal allowed delay between samples (in us) for actual card */ + unsigned int ns_min; int i8253_osc_base; /* 1/frequency of on board oscilator in ns */ - unsigned int act_chanlist[16]; /* MUX setting for actual AI operations */ + /* MUX setting for actual AI operations */ + unsigned int act_chanlist[16]; unsigned int act_chanlist_len; /* how long is actual MUX list */ unsigned int act_chanlist_pos; /* actual position in MUX list */ unsigned int divisor1; @@ -618,7 +620,8 @@ static int check_channel_list(struct comedi_device *dev, break; nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; - if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continuous :-( */ + if (nowmustbechan != CR_CHAN(chanlist[i])) { + /* channel list isn't continuous :-( */ dev_dbg(dev->class_dev, "channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", i, CR_CHAN(chanlist[i]), nowmustbechan, @@ -1124,8 +1127,10 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->ns_min = board->ns_min; if (!board->is_818) { - if ((it->options[6] == 1) || (it->options[6] == 100)) - devpriv->ns_min = 10000; /* extended PCL718 to 100kHz DAC */ + if ((it->options[6] == 1) || (it->options[6] == 100)) { + /* extended PCL718 to 100kHz DAC */ + devpriv->ns_min = 10000; + } } pcl818_reset(dev); -- cgit v0.10.2 From 36e4d8826b317080e283e4edd08bf8d5ac706f38 Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Fri, 30 Jan 2015 00:11:36 +0200 Subject: staging: rtl8712: fix Prefer ether_addr_copy() over memcpy() This patch fixes the following checkpatch.pl warning: Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2) pahole showed that the struct used pnetdev->dev_addr is aligned to u16. Moreover mac is a simple array, pdata is a pointer that starts from an even offset. Signed-off-by: Heba Aamer Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index f1fd7e8..f8b5b33 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -462,7 +462,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, /* Use the mac address stored in the Efuse * offset = 0x12 for usb in efuse */ - memcpy(mac, &pdata[0x12], ETH_ALEN); + ether_addr_copy(mac, &pdata[0x12]); } eeprom_CustomerID = pdata[0x52]; switch (eeprom_CustomerID) { @@ -579,7 +579,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, } else dev_info(&udev->dev, "r8712u: MAC Address from efuse = %pM\n", mac); - memcpy(pnetdev->dev_addr, mac, ETH_ALEN); + ether_addr_copy(pnetdev->dev_addr, mac); } /* step 6. Load the firmware asynchronously */ if (rtl871x_load_fw(padapter)) -- cgit v0.10.2 From 737fee1bf699635060caa1e940fd30153ff592de Mon Sep 17 00:00:00 2001 From: Chris Rorvick Date: Fri, 30 Jan 2015 17:45:45 -0600 Subject: staging: emxx_udc: Remove nbu2ss_drv_set_dp_info() This function is an awkward helper for nbu2ss_drv_ep_init(). Most of its logic is devoted to determining if the current endpoint is ep0, something the caller can easily do in a single line. And there is not a lot going on beyond that. Move this logic up into nbu2ss_drv_ep_init(). The result is much easier to understand and the resulting function is still viewable within a single screen. Signed-off-by: Chris Rorvick Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index eb178fc..82c492f 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -3249,42 +3249,6 @@ static const char *gp_ep_name[NUM_ENDPOINTS] = { }; /*-------------------------------------------------------------------------*/ -static void __init nbu2ss_drv_set_ep_info( - struct nbu2ss_udc *udc, - struct nbu2ss_ep *ep, - const char *name) -{ - ep->udc = udc; - ep->desc = NULL; - - ep->ep.driver_data = NULL; - ep->ep.name = name; - ep->ep.ops = &nbu2ss_ep_ops; - - if (isdigit(name[2])) { - - long num; - int res; - char tempbuf[2]; - - tempbuf[0] = name[2]; - tempbuf[1] = '\0'; - res = kstrtol(tempbuf, 16, &num); - - if (num == 0) - ep->ep.maxpacket = EP0_PACKETSIZE; - else - ep->ep.maxpacket = EP_PACKETSIZE; - - } else { - ep->ep.maxpacket = EP_PACKETSIZE; - } - - list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); - INIT_LIST_HEAD(&ep->queue); -} - -/*-------------------------------------------------------------------------*/ static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc) { int i; @@ -3292,9 +3256,21 @@ static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc) INIT_LIST_HEAD(&udc->gadget.ep_list); udc->gadget.ep0 = &udc->ep[0].ep; + for (i = 0; i < NUM_ENDPOINTS; i++) { + struct nbu2ss_ep *ep = &udc->ep[i]; - for (i = 0; i < NUM_ENDPOINTS; i++) - nbu2ss_drv_set_ep_info(udc, &udc->ep[i], gp_ep_name[i]); + ep->udc = udc; + ep->desc = NULL; + + ep->ep.driver_data = NULL; + ep->ep.name = gp_ep_name[i]; + ep->ep.ops = &nbu2ss_ep_ops; + + ep->ep.maxpacket = (i == 0 ? EP0_PACKETSIZE : EP_PACKETSIZE); + + list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); + INIT_LIST_HEAD(&ep->queue); + } list_del_init(&udc->ep[0].ep.ep_list); } -- cgit v0.10.2 From e6aa864f01a10689a1e8e4c584bee6d00f4264dc Mon Sep 17 00:00:00 2001 From: Heba Aamer Date: Sat, 31 Jan 2015 04:48:00 +0200 Subject: staging: lustre: lustre: osc: modifying seq_printf statements This patch modifies the seq_printf statements in drivers/staging/lustre/lustre/osc/lproc_osc.c file. It changes it to seq_puts and seq_putc wherever applicable. Signed-off-by: Heba Aamer Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 8e22e45..1795d3a 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -364,7 +364,7 @@ static int osc_checksum_type_seq_show(struct seq_file *m, void *v) else seq_printf(m, "%s ", cksum_name[i]); } - seq_printf(m, "\n"); + seq_putc(m, '\n'); return 0; } @@ -601,9 +601,9 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "pending read pages: %d\n", atomic_read(&cli->cl_pending_r_pages)); - seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); - seq_printf(seq, "pages per rpc rpcs %% cum %% |"); - seq_printf(seq, " rpcs %% cum %%\n"); + seq_puts(seq, "\n\t\t\tread\t\t\twrite\n"); + seq_puts(seq, "pages per rpc rpcs % cum % |"); + seq_puts(seq, " rpcs % cum %\n"); read_tot = lprocfs_oh_sum(&cli->cl_read_page_hist); write_tot = lprocfs_oh_sum(&cli->cl_write_page_hist); @@ -624,9 +624,9 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) break; } - seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); - seq_printf(seq, "rpcs in flight rpcs %% cum %% |"); - seq_printf(seq, " rpcs %% cum %%\n"); + seq_puts(seq, "\n\t\t\tread\t\t\twrite\n"); + seq_puts(seq, "rpcs in flight rpcs % cum % |"); + seq_puts(seq, " rpcs % cum %\n"); read_tot = lprocfs_oh_sum(&cli->cl_read_rpc_hist); write_tot = lprocfs_oh_sum(&cli->cl_write_rpc_hist); @@ -647,9 +647,9 @@ static int osc_rpc_stats_seq_show(struct seq_file *seq, void *v) break; } - seq_printf(seq, "\n\t\t\tread\t\t\twrite\n"); - seq_printf(seq, "offset rpcs %% cum %% |"); - seq_printf(seq, " rpcs %% cum %%\n"); + seq_puts(seq, "\n\t\t\tread\t\t\twrite\n"); + seq_puts(seq, "offset rpcs % cum % |"); + seq_puts(seq, " rpcs % cum %\n"); read_tot = lprocfs_oh_sum(&cli->cl_read_offset_hist); write_tot = lprocfs_oh_sum(&cli->cl_write_offset_hist); -- cgit v0.10.2 From 187e2a81805f4b7ba1acf118aed8937a718d894c Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:38 +0000 Subject: staging: vt6655: move setting of PSTxDesc->buff_addr to vnt_tx_packet Keep setting of this part of the structure with the others. Only pTDInfo needs carried in the buffer structure. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 58559fa..9a80144 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1217,6 +1217,8 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) head_td->m_td1TD1.wReqCount = cpu_to_le16((u16)head_td->pTDInfo->dwReqCount); + head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma); + head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB; if (dma_idx == TYPE_AC0DMA) diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c index 9cade85..07ce3fd 100644 --- a/drivers/staging/vt6655/rxtx.c +++ b/drivers/staging/vt6655/rxtx.c @@ -1207,7 +1207,6 @@ s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType, ptdCurr->pTDInfo->dwReqCount = cbReqCount; ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength; ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma; - ptdCurr->buff_addr = cpu_to_le32(ptdCurr->pTDInfo->skb_dma); return cbHeaderLength; } -- cgit v0.10.2 From 64e4fd51421ffe750ea483f32370f60ca8435657 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:39 +0000 Subject: staging: vt6655: parse bb vga code out of device_intr. Reordering the code and reversing the priv->byBBVGANew verses priv->byBBVGACurrent check and using dev_dbg for pr_debug. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 9a80144..870cafd 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1008,6 +1008,58 @@ static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc) pTDInfo->byFlags = 0; } +static void vnt_check_bb_vga(struct vnt_private *priv) +{ + long dbm; + int i; + + if (!priv->bUpdateBBVGA) + return; + + if (priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + return; + + if (!(priv->vif->bss_conf.assoc && priv->uCurrRSSI)) + return; + + RFvRSSITodBm(priv, (u8)priv->uCurrRSSI, &dbm); + + for (i = 0; i < BB_VGA_LEVEL; i++) { + if (dbm < priv->ldBmThreshold[i]) { + priv->byBBVGANew = priv->abyBBVGA[i]; + break; + } + } + + if (priv->byBBVGANew == priv->byBBVGACurrent) { + priv->uBBVGADiffCount = 1; + return; + } + + priv->uBBVGADiffCount++; + + if (priv->uBBVGADiffCount == 1) { + /* first VGA diff gain */ + BBvSetVGAGainOffset(priv, priv->byBBVGANew); + + dev_dbg(&priv->pcid->dev, + "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)dbm, priv->byBBVGANew, + priv->byBBVGACurrent, + (int)priv->uBBVGADiffCount); + } + + if (priv->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { + dev_dbg(&priv->pcid->dev, + "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)dbm, priv->byBBVGANew, + priv->byBBVGACurrent, + (int)priv->uBBVGADiffCount); + + BBvSetVGAGainOffset(priv, priv->byBBVGANew); + } +} + static irqreturn_t device_intr(int irq, void *dev_instance) { struct vnt_private *pDevice = dev_instance; @@ -1015,7 +1067,6 @@ static irqreturn_t device_intr(int irq, void *dev_instance) unsigned long dwMIBCounter = 0; unsigned char byOrgPageSel = 0; int handled = 0; - int ii = 0; unsigned long flags; MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); @@ -1059,44 +1110,8 @@ static irqreturn_t device_intr(int irq, void *dev_instance) if (pDevice->dwIsr & ISR_TBTT) { if (pDevice->vif && - pDevice->op_mode != NL80211_IFTYPE_ADHOC) { - if (pDevice->bUpdateBBVGA && - !(pDevice->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && - pDevice->vif->bss_conf.assoc && - pDevice->uCurrRSSI) { - long ldBm; - - RFvRSSITodBm(pDevice, (unsigned char) pDevice->uCurrRSSI, &ldBm); - for (ii = 0; ii < BB_VGA_LEVEL; ii++) { - if (ldBm < pDevice->ldBmThreshold[ii]) { - pDevice->byBBVGANew = pDevice->abyBBVGA[ii]; - break; - } - } - if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) { - pDevice->uBBVGADiffCount++; - if (pDevice->uBBVGADiffCount == 1) { - // first VGA diff gain - BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); - pr_debug("First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", - (int)ldBm, - pDevice->byBBVGANew, - pDevice->byBBVGACurrent, - (int)pDevice->uBBVGADiffCount); - } - if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { - pr_debug("RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", - (int)ldBm, - pDevice->byBBVGANew, - pDevice->byBBVGACurrent, - (int)pDevice->uBBVGADiffCount); - BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); - } - } else { - pDevice->uBBVGADiffCount = 1; - } - } - } + pDevice->op_mode != NL80211_IFTYPE_ADHOC) + vnt_check_bb_vga(pDevice); pDevice->bBeaconSent = false; if (pDevice->bEnablePSMode) -- cgit v0.10.2 From d17f4c8a42256dae6aa598bdbc00eff8b38cc949 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:40 +0000 Subject: staging: vt6655: Fix TD_FLAGS_NETIF_SKB only on TYPE_AC0DMA Allow only TD_FLAGS_NETIF_SKB on ring buffer TYPE_AC0DMA for data only transfers for correct reporting of tx rates. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 870cafd..4324282a 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -1234,12 +1234,13 @@ static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma); - head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB; + if (dma_idx == TYPE_AC0DMA) { + head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB; - if (dma_idx == TYPE_AC0DMA) MACvTransmitAC0(priv->PortOffset); - else + } else { MACvTransmit0(priv->PortOffset); + } spin_unlock_irqrestore(&priv->lock, flags); -- cgit v0.10.2 From 6d854127268010f98c66c9e93fd278c2d76a6562 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:41 +0000 Subject: staging: vt6655: vnt_rx_data add track rsr and new_rsr errors If not rsr & RSR_CRCOK report RX_FLAG_FAILED_FCS_CRC If not rsr & (RSR_IVLDTYP | RSR_IVLDLEN) drop packet If not NEWRSR_DECRYPTOK on new_rsr drop packet. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c index 11cc090..3c5b87f 100644 --- a/drivers/staging/vt6655/dpc.c +++ b/drivers/staging/vt6655/dpc.c @@ -91,6 +91,8 @@ static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, new_rsr = skb_data + bytes_received - 3; rssi = skb_data + bytes_received - 2; rsr = skb_data + bytes_received - 1; + if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN)) + return false; RFvRSSITodBm(priv, *rssi, &rx_dbm); @@ -106,6 +108,9 @@ static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, rx_status.flag = 0; rx_status.freq = hw->conf.chandef.chan->center_freq; + if (!(*rsr & RSR_CRCOK)) + rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; + hdr = (struct ieee80211_hdr *)(skb->data); fc = hdr->frame_control; @@ -113,7 +118,11 @@ static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb, if (ieee80211_has_protected(fc)) { if (priv->byLocalID > REV_ID_VT3253_A1) - rx_status.flag = RX_FLAG_DECRYPTED; + rx_status.flag |= RX_FLAG_DECRYPTED; + + /* Drop packet */ + if (!(*new_rsr & NEWRSR_DECRYPTOK)) + return false; } memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); -- cgit v0.10.2 From 5c9b063a0ae48acaba69ebffc43ea8214ff70c64 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:42 +0000 Subject: staging: vt6656: vnt_fill_cts_head remove unneeded NULL check. union vnt_tx_data_head is nolonger detached from main vnt_tx_buffer structure so this check is unnecessary. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index b74f672..3b90497 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -525,9 +525,6 @@ static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, u32 cts_frame_len = 14; u16 current_rate = tx_context->tx_rate; - if (!head) - return 0; - if (tx_context->fb_option) { /* Auto Fall back */ struct vnt_cts_fb *buf = &head->cts_g_fb; -- cgit v0.10.2 From 1bdee7063533df3e2918138b42d32ca3958a85fd Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 1 Feb 2015 11:59:43 +0000 Subject: staging: vt6656: parse cts fall back out of vnt_fill_cts_head Creating new function vnt_fill_cts_fb_head for the fall back rates. The check for fb_option is now done in vnt_rxtx_cts. This fixes checkpatch warning WARNING: else is not generally useful after a break or return 559: FILE: drivers/staging/vt6656/rxtx.c:559: Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 3b90497..33baf26 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -518,60 +518,66 @@ static u16 vnt_rxtx_rts_a_fb_head(struct vnt_usb_send_context *tx_context, return vnt_rxtx_datahead_a_fb(tx_context, &buf->data_head); } -static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, - union vnt_tx_data_head *head) +static u16 vnt_fill_cts_fb_head(struct vnt_usb_send_context *tx_context, + union vnt_tx_data_head *head) { struct vnt_private *priv = tx_context->priv; + struct vnt_cts_fb *buf = &head->cts_g_fb; u32 cts_frame_len = 14; u16 current_rate = tx_context->tx_rate; - if (tx_context->fb_option) { - /* Auto Fall back */ - struct vnt_cts_fb *buf = &head->cts_g_fb; - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, cts_frame_len, - priv->top_cck_basic_rate, PK_TYPE_11B, &buf->b); - buf->duration_ba = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, - tx_context->pkt_type, - current_rate); - /* Get CTSDuration_ba_f0 */ - buf->cts_duration_ba_f0 = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F0, - tx_context->pkt_type, - priv->tx_rate_fb0); - /* Get CTSDuration_ba_f1 */ - buf->cts_duration_ba_f1 = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F1, - tx_context->pkt_type, - priv->tx_rate_fb1); - /* Get CTS Frame body */ - buf->data.duration = buf->duration_ba; - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); + /* Get SignalField,ServiceField,Length */ + vnt_get_phy_field(priv, cts_frame_len, priv->top_cck_basic_rate, + PK_TYPE_11B, &buf->b); - ether_addr_copy(buf->data.ra, priv->current_net_addr); + buf->duration_ba = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, + tx_context->pkt_type, + current_rate); + /* Get CTSDuration_ba_f0 */ + buf->cts_duration_ba_f0 = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F0, + tx_context->pkt_type, + priv->tx_rate_fb0); + /* Get CTSDuration_ba_f1 */ + buf->cts_duration_ba_f1 = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F1, + tx_context->pkt_type, + priv->tx_rate_fb1); + /* Get CTS Frame body */ + buf->data.duration = buf->duration_ba; + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); - return vnt_rxtx_datahead_g_fb(tx_context, &buf->data_head); - } else { - struct vnt_cts *buf = &head->cts_g; - /* Get SignalField,ServiceField,Length */ - vnt_get_phy_field(priv, cts_frame_len, - priv->top_cck_basic_rate, PK_TYPE_11B, &buf->b); - /* Get CTSDuration_ba */ - buf->duration_ba = - vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, - tx_context->pkt_type, - current_rate); - /*Get CTS Frame body*/ - buf->data.duration = buf->duration_ba; - buf->data.frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); + ether_addr_copy(buf->data.ra, priv->current_net_addr); - ether_addr_copy(buf->data.ra, priv->current_net_addr); + return vnt_rxtx_datahead_g_fb(tx_context, &buf->data_head); +} - return vnt_rxtx_datahead_g(tx_context, &buf->data_head); - } +static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context, + union vnt_tx_data_head *head) +{ + struct vnt_private *priv = tx_context->priv; + struct vnt_cts *buf = &head->cts_g; + u32 cts_frame_len = 14; + u16 current_rate = tx_context->tx_rate; + + /* Get SignalField,ServiceField,Length */ + vnt_get_phy_field(priv, cts_frame_len, priv->top_cck_basic_rate, + PK_TYPE_11B, &buf->b); + /* Get CTSDuration_ba */ + buf->duration_ba = + vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA, + tx_context->pkt_type, + current_rate); + /*Get CTS Frame body*/ + buf->data.duration = buf->duration_ba; + buf->data.frame_control = + cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); + + ether_addr_copy(buf->data.ra, priv->current_net_addr); + + return vnt_rxtx_datahead_g(tx_context, &buf->data_head); } static u16 vnt_rxtx_rts(struct vnt_usb_send_context *tx_context, @@ -628,6 +634,9 @@ static u16 vnt_rxtx_cts(struct vnt_usb_send_context *tx_context, head = &tx_head->tx_cts.tx.mic.head; /* Fill CTS */ + if (tx_context->fb_option) + return vnt_fill_cts_fb_head(tx_context, head); + return vnt_fill_cts_head(tx_context, head); } -- cgit v0.10.2 From 2cc1a1b3eeee793e68f27efde9f0519c233b944f Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 31 Jan 2015 12:02:08 +0100 Subject: staging: unisys: use msecs_to_jiffies for conversions This is only an API consolidation to make things more readable. Instances of var * HZ / 1000 are replaced by msecs_to_jiffies(var). Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 82e259d..f606ee9 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -1594,7 +1594,7 @@ parahotplug_next_id(void) static unsigned long parahotplug_next_expiration(void) { - return jiffies + PARAHOTPLUG_TIMEOUT_MS * HZ / 1000; + return jiffies + msecs_to_jiffies(PARAHOTPLUG_TIMEOUT_MS); } /* -- cgit v0.10.2 From 048035bf8c7b752e9fe608ff3069e41c460efda5 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Delgado Date: Mon, 2 Feb 2015 19:26:32 +0100 Subject: staging/unisys/visorutil/procobjecttree: Code Style Lines should not be over 80 characters Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorutil/procobjecttree.c b/drivers/staging/unisys/visorutil/procobjecttree.c index 195772d..637c5ef 100644 --- a/drivers/staging/unisys/visorutil/procobjecttree.c +++ b/drivers/staging/unisys/visorutil/procobjecttree.c @@ -260,9 +260,9 @@ MYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type, ERRDRV("out of memory\n"); goto Away; } - obj->procDirProperties = - kzalloc((type->nProperties + 1) * sizeof(struct proc_dir_entry *), - GFP_KERNEL | __GFP_NORETRY); + obj->procDirProperties = kzalloc((type->nProperties + 1) * + sizeof(struct proc_dir_entry *), + GFP_KERNEL | __GFP_NORETRY); if (obj->procDirProperties == NULL) { ERRDRV("out of memory\n"); goto Away; @@ -276,8 +276,8 @@ MYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type, /* only create properties that have names */ obj->procDirProperties[i] = createProcFile(type->propertyNames[i], - obj->procDir, &proc_fops, - &obj->procDirPropertyContexts[i]); + obj->procDir, &proc_fops, + &obj->procDirPropertyContexts[i]); if (obj->procDirProperties[i] == NULL) { rc = NULL; goto Away; -- cgit v0.10.2 From 4abfc1f5fb846bbc8b151aa35eae2c2fea686e89 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Delgado Date: Mon, 2 Feb 2015 19:55:46 +0100 Subject: staging/unisys/visorutil/procobjecttree: Replace typedef Instead of declaring a new type, define a new struct. Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/visorutil/procobjecttree.c b/drivers/staging/unisys/visorutil/procobjecttree.c index 637c5ef..82279ca 100644 --- a/drivers/staging/unisys/visorutil/procobjecttree.c +++ b/drivers/staging/unisys/visorutil/procobjecttree.c @@ -25,12 +25,12 @@ * need in order to call the callback function that supplies the /proc read * info for that file. */ -typedef struct { +struct proc_dir_entry_context { void (*show_property)(struct seq_file *, void *, int); MYPROCOBJECT *procObject; int propertyIndex; -} PROCDIRENTRYCONTEXT; +}; /** This describes the attributes of a tree rooted at * ///... @@ -86,7 +86,7 @@ struct MYPROCOBJECT_Tag { /** this is a holding area for the context information that is needed * to run the /proc callback function */ - PROCDIRENTRYCONTEXT *procDirPropertyContexts; + struct proc_dir_entry_context *procDirPropertyContexts; }; @@ -254,7 +254,8 @@ MYPROCOBJECT *visor_proc_CreateObject(MYPROCTYPE *type, goto Away; } obj->procDirPropertyContexts = - kzalloc((type->nProperties + 1) * sizeof(PROCDIRENTRYCONTEXT), + kzalloc((type->nProperties + 1) * + sizeof(struct proc_dir_entry_context), GFP_KERNEL | __GFP_NORETRY); if (obj->procDirPropertyContexts == NULL) { ERRDRV("out of memory\n"); @@ -340,7 +341,7 @@ EXPORT_SYMBOL_GPL(visor_proc_DestroyObject); static int seq_show(struct seq_file *seq, void *offset) { - PROCDIRENTRYCONTEXT *ctx = (PROCDIRENTRYCONTEXT *)(seq->private); + struct proc_dir_entry_context *ctx = seq->private; if (ctx == NULL) { ERRDRV("I don't have a freakin' clue..."); -- cgit v0.10.2 From 659688a51a0e7427be2b2e38baeaa7f30ba16bcb Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 5 Feb 2015 14:35:54 +0100 Subject: staging: unisys: Fix typo in comment Signed-off-by: Bastien Nocera Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/unisys/virthba/virthba.c b/drivers/staging/unisys/virthba/virthba.c index 8cd090b..e6ecea5 100644 --- a/drivers/staging/unisys/virthba/virthba.c +++ b/drivers/staging/unisys/virthba/virthba.c @@ -479,7 +479,7 @@ virthba_probe(struct virtpci_dev *virtpcidev, const struct pci_device_id *id) * instance - this virthba that has just been created is an * instance of a scsi host adapter. This scsi_host_alloc * function allocates a new Scsi_Host struct & performs basic - * initializatoin. The host is not published to the scsi + * initialization. The host is not published to the scsi * midlayer until scsi_add_host is called. */ DBGINF("calling scsi_host_alloc.\n"); -- cgit v0.10.2 From 509031dd5f5ae008ef5d4d04226ce63ca8c84354 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 1 Feb 2015 17:01:33 +0200 Subject: staging: xgifb: fix colours on big-endian machines other than powerpc XGI framebuffer supports big-endian machines, but it's currently enabled based on __powerpc__ define (which is wrong, as powerpc can be also little-endian now). Use __BIG_ENDIAN instead. This will fix wrong colours on such machines. Tested on parisc with XGI Z7. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 74a8db8..935c714 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -930,7 +930,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, + var->hsync_len; unsigned int vtotal = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) u8 cr_data; #endif unsigned int drate = 0, hrate = 0; @@ -1044,7 +1044,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, xgifb_info->DstColor = 0x0000; xgifb_info->XGI310_AccelDepth = 0x00000000; xgifb_info->video_cmap_len = 256; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) cr_data = xgifb_reg_get(XGICR, 0x4D); xgifb_reg_set(XGICR, 0x4D, (cr_data & 0xE0)); #endif @@ -1052,7 +1052,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, case 16: xgifb_info->DstColor = 0x8000; xgifb_info->XGI310_AccelDepth = 0x00010000; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) cr_data = xgifb_reg_get(XGICR, 0x4D); xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x0B)); #endif @@ -1062,7 +1062,7 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive, xgifb_info->DstColor = 0xC000; xgifb_info->XGI310_AccelDepth = 0x00020000; xgifb_info->video_cmap_len = 16; -#if defined(__powerpc__) +#if defined(__BIG_ENDIAN) cr_data = xgifb_reg_get(XGICR, 0x4D); xgifb_reg_set(XGICR, 0x4D, ((cr_data & 0xE0) | 0x15)); #endif -- cgit v0.10.2 From 7dfb6d2ec4547a6fd83571f6beeee47db9184847 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 31 Jan 2015 11:51:54 +0100 Subject: staging: rtl8712: cleanup of timeout conversions This is only an API consolidation to make things more readable. Instances of var * HZ / 1000 are replaced by msecs_to_jiffies(var). As msecs_to_jiffies will return > 0 if it is passed a value > 0 the == 0 check is not needed. Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h index 5153ad9..f933713 100644 --- a/drivers/staging/rtl8712/osdep_service.h +++ b/drivers/staging/rtl8712/osdep_service.h @@ -71,7 +71,7 @@ static inline void _init_timer(struct timer_list *ptimer, static inline void _set_timer(struct timer_list *ptimer, u32 delay_time) { - mod_timer(ptimer, (jiffies+(delay_time*HZ/1000))); + mod_timer(ptimer, (jiffies+msecs_to_jiffies(delay_time))); } static inline void _cancel_timer(struct timer_list *ptimer, u8 *bcancelled) @@ -101,9 +101,7 @@ static inline void sleep_schedulable(int ms) { u32 delta; - delta = (ms * HZ) / 1000;/*(ms)*/ - if (delta == 0) - delta = 1;/* 1 ms */ + delta = msecs_to_jiffies(ms);/*(ms)*/ set_current_state(TASK_INTERRUPTIBLE); if (schedule_timeout(delta) != 0) return; -- cgit v0.10.2 From 1ba2c5a8087b8760087ff29a30b0aa4ae9802bb2 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 31 Jan 2015 11:52:14 +0100 Subject: staging: rtl8712: condition with no effect removed The check for return of schedule_timeout() has no effect on the effective control flow of sleep_schedulable() so it can be dropped. Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h index f933713..36348d9 100644 --- a/drivers/staging/rtl8712/osdep_service.h +++ b/drivers/staging/rtl8712/osdep_service.h @@ -103,8 +103,7 @@ static inline void sleep_schedulable(int ms) delta = msecs_to_jiffies(ms);/*(ms)*/ set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout(delta) != 0) - return; + schedule_timeout(delta); } static inline unsigned char _cancel_timer_ex(struct timer_list *ptimer) -- cgit v0.10.2 From 37257276a47696aac3ef11aa90f95cfaa723dddf Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 31 Jan 2015 12:10:07 +0100 Subject: staging: rtl8188eu: use msecs_to_jiffies for conversions This is only an API consolidation to make things more readable. Instances of var * HZ / 1000 are replaced by msecs_to_jiffies(var). Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h index 82f58f8..3a27477 100644 --- a/drivers/staging/rtl8188eu/include/osdep_service.h +++ b/drivers/staging/rtl8188eu/include/osdep_service.h @@ -87,7 +87,7 @@ static inline void _init_timer(struct timer_list *ptimer, static inline void _set_timer(struct timer_list *ptimer, u32 delay_time) { - mod_timer(ptimer , (jiffies+(delay_time*HZ/1000))); + mod_timer(ptimer , (jiffies+msecs_to_jiffies(delay_time))); } #define RTW_TIMER_HDL_ARGS void *FunctionContext -- cgit v0.10.2 From 98ab6ff914b367bfd4aff30e2e94e01fb8a443af Mon Sep 17 00:00:00 2001 From: Kolbeinn Karlsson Date: Sat, 31 Jan 2015 13:14:33 -0500 Subject: Staging: rtl8192e: Fixed unnecessary line continuation. Fixed a coding style issue. Signed-off-by: Kolbeinn Karlsson Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c index 91e98e8..0cf3809 100644 --- a/drivers/staging/rtl8192e/rtllib_module.c +++ b/drivers/staging/rtl8192e/rtllib_module.c @@ -202,9 +202,7 @@ void free_rtllib(struct net_device *dev) EXPORT_SYMBOL(free_rtllib); u32 rtllib_debug_level; -static int debug = \ - RTLLIB_DL_ERR - ; +static int debug = RTLLIB_DL_ERR; static struct proc_dir_entry *rtllib_proc; static int show_debug_level(struct seq_file *m, void *v) -- cgit v0.10.2 From b47ea4bbfefac60ba24ae4ada637f997ed694716 Mon Sep 17 00:00:00 2001 From: Andreas Ruprecht Date: Mon, 2 Feb 2015 20:24:14 +0100 Subject: staging: lustre: osc: Make osc_init() static osc_init() is marked as the module_init function in osc_request.c and is never used anywhere else. Hence, it can (and should) be declared static. sparse also complained about this with the following warning, which is fixed by this patch. andreas@workbox:~/linux-next$ make C=1 M=drivers/staging/lustre/lustre/osc/ [...] drivers/staging/lustre/lustre/osc/osc_request.c:3335:12: warning: symbol 'osc_init' was not declared. Should it be static? [...] Signed-off-by: Andreas Ruprecht Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index b9450b9..0adfa70 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -3332,7 +3332,7 @@ extern struct lu_kmem_descr osc_caches[]; extern spinlock_t osc_ast_guard; extern struct lock_class_key osc_ast_guard_class; -int __init osc_init(void) +static int __init osc_init(void) { struct lprocfs_static_vars lvars = { NULL }; int rc; -- cgit v0.10.2 From fa55c6a4b41cd4fd240debe719b205056b04a0bf Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Sun, 1 Feb 2015 21:52:00 -0500 Subject: staging/lustre/ptlrpc: avoid list scan in ptlrpcd_check ptlrpcd_check() always scan all requests on ptlrpc_request_set and try to finish completed requests, this is low efficiency. Even worse, l_wait_event() always checks condition for twice before sleeping and one more time after waking up, which means it will call ptlrpcd_check() for three times in each loop. This patch will move completed requests at the head of list in ptlrpc_check_set(), with this change ptlrpcd_check doesn't need to scan all requests anymore. Signed-off-by: Liang Zhen Reviewed-on: http://review.whamcloud.com/11513 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5548 Reviewed-by: Bobi Jam Reviewed-by: Andreas Dilger Reviewed-by: Johann Lombardi Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index dc9e406..8c1ec83 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1497,11 +1497,13 @@ static inline int ptlrpc_set_producer(struct ptlrpc_request_set *set) int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) { struct list_head *tmp, *next; + struct list_head comp_reqs; int force_timer_recalc = 0; if (atomic_read(&set->set_remaining) == 0) return 1; + INIT_LIST_HEAD(&comp_reqs); list_for_each_safe(tmp, next, &set->set_requests) { struct ptlrpc_request *req = list_entry(tmp, struct ptlrpc_request, @@ -1576,8 +1578,10 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) ptlrpc_rqphase_move(req, req->rq_next_phase); } - if (req->rq_phase == RQ_PHASE_COMPLETE) + if (req->rq_phase == RQ_PHASE_COMPLETE) { + list_move_tail(&req->rq_set_chain, &comp_reqs); continue; + } if (req->rq_phase == RQ_PHASE_INTERPRET) goto interpret; @@ -1860,9 +1864,15 @@ interpret: if (req->rq_status != 0) set->set_rc = req->rq_status; ptlrpc_req_finished(req); + } else { + list_move_tail(&req->rq_set_chain, &comp_reqs); } } + /* move completed request at the head of list so it's easier for + * caller to find them */ + list_splice(&comp_reqs, &set->set_requests); + /* If we hit an error, we want to recover promptly. */ return atomic_read(&set->set_remaining) == 0 || force_timer_recalc; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index cbcc541..4621b71 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -306,21 +306,16 @@ static int ptlrpcd_check(struct lu_env *env, struct ptlrpcd_ctl *pc) if (atomic_read(&set->set_remaining)) rc |= ptlrpc_check_set(env, set); - if (!list_empty(&set->set_requests)) { - /* - * XXX: our set never completes, so we prune the completed - * reqs after each iteration. boy could this be smarter. - */ - list_for_each_safe(pos, tmp, &set->set_requests) { - req = list_entry(pos, struct ptlrpc_request, - rq_set_chain); - if (req->rq_phase != RQ_PHASE_COMPLETE) - continue; + /* NB: ptlrpc_check_set has already moved completed request at the + * head of seq::set_requests */ + list_for_each_safe(pos, tmp, &set->set_requests) { + req = list_entry(pos, struct ptlrpc_request, rq_set_chain); + if (req->rq_phase != RQ_PHASE_COMPLETE) + break; - list_del_init(&req->rq_set_chain); - req->rq_set = NULL; - ptlrpc_req_finished(req); - } + list_del_init(&req->rq_set_chain); + req->rq_set = NULL; + ptlrpc_req_finished(req); } if (rc == 0) { -- cgit v0.10.2 From c00266e369b945945316dad3869342d07f4be868 Mon Sep 17 00:00:00 2001 From: Alexander Boyko Date: Sun, 1 Feb 2015 21:52:01 -0500 Subject: staging/lustre/osc: split different type of IO Do not allow different type of pages at the same rpc. Signed-off-by: Alexander Boyko Signed-off-by: Vitaly Fertman Xyratex-bug-id: MRP-859 Reviewed-on: http://review.whamcloud.com/10930 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3192 Reviewed-by: Jinshan Xiong Reviewed-by: Niu Yawei Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 370e6d4..7022ed4 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1820,6 +1820,9 @@ static int try_to_add_extent_for_io(struct client_obd *cli, int *pc, unsigned int *max_pages) { struct osc_extent *tmp; + struct osc_async_page *oap = list_first_entry(&ext->oe_pages, + struct osc_async_page, + oap_pending_item); EASSERT((ext->oe_state == OES_CACHE || ext->oe_state == OES_LOCK_DONE), ext); @@ -1829,6 +1832,10 @@ static int try_to_add_extent_for_io(struct client_obd *cli, return 0; list_for_each_entry(tmp, rpclist, oe_link) { + struct osc_async_page *oap2; + + oap2 = list_first_entry(&tmp->oe_pages, struct osc_async_page, + oap_pending_item); EASSERT(tmp->oe_owner == current, tmp); #if 0 if (overlapped(tmp, ext)) { @@ -1836,6 +1843,11 @@ static int try_to_add_extent_for_io(struct client_obd *cli, EASSERT(0, ext); } #endif + if (oap2cl_page(oap)->cp_type != oap2cl_page(oap2)->cp_type) { + CDEBUG(D_CACHE, "Do not permit different type of IO" + " for a same RPC\n"); + return 0; + } if (tmp->oe_srvlock != ext->oe_srvlock || !tmp->oe_grants != !ext->oe_grants) -- cgit v0.10.2 From 4d2c7b309d17a5609a5d4ede628d16828262ca00 Mon Sep 17 00:00:00 2001 From: Li Xi Date: Sun, 1 Feb 2015 21:52:02 -0500 Subject: staging/lustre/ldlm: high load because of negative timeout When the time of LRU resizing exceeds waiting period of recalculation, the ldlm daemon will keep on resizing without any interval of rest. That will cause high CPU load. This patch fixes the problem by setting the recalculation timestamp after LRU resizing finishes rather than before it. What is more, an interval of one second is enforced between each recalculation. Signed-off-by: Li Xi Reviewed-on: http://review.whamcloud.com/11227 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5415 Reviewed-by: Dmitry Eremin Reviewed-by: Bobi Jam Reviewed-by: Lai Siyao Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 142b3dd..d20d277 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -470,6 +470,7 @@ static void ldlm_cli_pool_pop_slv(struct ldlm_pool *pl) static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) { time_t recalc_interval_sec; + int ret; recalc_interval_sec = get_seconds() - pl->pl_recalc_time; if (recalc_interval_sec < pl->pl_recalc_period) @@ -490,16 +491,15 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) */ ldlm_cli_pool_pop_slv(pl); - pl->pl_recalc_time = get_seconds(); - lprocfs_counter_add(pl->pl_stats, LDLM_POOL_TIMING_STAT, - recalc_interval_sec); spin_unlock(&pl->pl_lock); /* * Do not cancel locks in case lru resize is disabled for this ns. */ - if (!ns_connect_lru_resize(ldlm_pl2ns(pl))) - return 0; + if (!ns_connect_lru_resize(ldlm_pl2ns(pl))) { + ret = 0; + goto out; + } /* * In the time of canceling locks on client we do not need to maintain @@ -507,7 +507,19 @@ static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) * It may be called when SLV has changed much, this is why we do not * take into account pl->pl_recalc_time here. */ - return ldlm_cancel_lru(ldlm_pl2ns(pl), 0, LCF_ASYNC, LDLM_CANCEL_LRUR); + ret = ldlm_cancel_lru(ldlm_pl2ns(pl), 0, LCF_ASYNC, LDLM_CANCEL_LRUR); + +out: + spin_lock(&pl->pl_lock); + /* + * Time of LRU resizing might be longer than period, + * so update after LRU resizing rather than before it. + */ + pl->pl_recalc_time = get_seconds(); + lprocfs_counter_add(pl->pl_stats, LDLM_POOL_TIMING_STAT, + recalc_interval_sec); + spin_unlock(&pl->pl_lock); + return ret; } /** @@ -591,6 +603,14 @@ int ldlm_pool_recalc(struct ldlm_pool *pl) } recalc_interval_sec = pl->pl_recalc_time - get_seconds() + pl->pl_recalc_period; + if (recalc_interval_sec <= 0) { + /* Prevent too frequent recalculation. */ + CDEBUG(D_DLMTRACE, "Negative interval(%ld), " + "too short period(%ld)", + recalc_interval_sec, + pl->pl_recalc_period); + recalc_interval_sec = 1; + } return recalc_interval_sec; } -- cgit v0.10.2 From 89975ff91e1a1a9396804976e49b794755168c6a Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Fri, 30 Jan 2015 19:47:36 -0500 Subject: staging/lustre: remove unused lustre_update.h header lustre_update.h containts various server-side structures that are not really relevant for the client. Also remove the only user of this file that does not actually need it. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/include/lustre_update.h b/drivers/staging/lustre/lustre/include/lustre_update.h deleted file mode 100644 index 84defce..0000000 --- a/drivers/staging/lustre/lustre/include/lustre_update.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.gnu.org/licenses/gpl-2.0.htm - * - * GPL HEADER END - */ -/* - * Copyright (c) 2013, Intel Corporation. - */ -/* - * lustre/include/lustre_update.h - * - * Author: Di Wang - */ - -#ifndef _LUSTRE_UPDATE_H -#define _LUSTRE_UPDATE_H - -#define UPDATE_BUFFER_SIZE 8192 -struct update_request { - struct dt_device *ur_dt; - struct list_head ur_list; /* attached itself to thandle */ - int ur_flags; - int ur_rc; /* request result */ - int ur_batchid; /* Current batch(trans) id */ - struct update_buf *ur_buf; /* Holding the update req */ -}; - -static inline unsigned long update_size(struct update *update) -{ - unsigned long size; - int i; - - size = cfs_size_round(offsetof(struct update, u_bufs[0])); - for (i = 0; i < UPDATE_BUF_COUNT; i++) - size += cfs_size_round(update->u_lens[i]); - - return size; -} - -static inline void *update_param_buf(struct update *update, int index, - int *size) -{ - int i; - void *ptr; - - if (index >= UPDATE_BUF_COUNT) - return NULL; - - ptr = (char *)update + cfs_size_round(offsetof(struct update, - u_bufs[0])); - for (i = 0; i < index; i++) { - LASSERT(update->u_lens[i] > 0); - ptr += cfs_size_round(update->u_lens[i]); - } - - if (size != NULL) - *size = update->u_lens[index]; - - return ptr; -} - -static inline unsigned long update_buf_size(struct update_buf *buf) -{ - unsigned long size; - int i = 0; - - size = cfs_size_round(offsetof(struct update_buf, ub_bufs[0])); - for (i = 0; i < buf->ub_count; i++) { - struct update *update; - - update = (struct update *)((char *)buf + size); - size += update_size(update); - } - LASSERT(size <= UPDATE_BUFFER_SIZE); - return size; -} - -static inline void *update_buf_get(struct update_buf *buf, int index, int *size) -{ - int count = buf->ub_count; - void *ptr; - int i = 0; - - if (index >= count) - return NULL; - - ptr = (char *)buf + cfs_size_round(offsetof(struct update_buf, - ub_bufs[0])); - for (i = 0; i < index; i++) - ptr += update_size((struct update *)ptr); - - if (size != NULL) - *size = update_size((struct update *)ptr); - - return ptr; -} - -static inline void update_init_reply_buf(struct update_reply *reply, int count) -{ - reply->ur_version = UPDATE_REPLY_V1; - reply->ur_count = count; -} - -static inline void *update_get_buf_internal(struct update_reply *reply, - int index, int *size) -{ - char *ptr; - int count = reply->ur_count; - int i; - - if (index >= count) - return NULL; - - ptr = (char *)reply + cfs_size_round(offsetof(struct update_reply, - ur_lens[count])); - for (i = 0; i < index; i++) { - LASSERT(reply->ur_lens[i] > 0); - ptr += cfs_size_round(reply->ur_lens[i]); - } - - if (size != NULL) - *size = reply->ur_lens[index]; - - return ptr; -} - -static inline void update_insert_reply(struct update_reply *reply, void *data, - int data_len, int index, int rc) -{ - char *ptr; - - ptr = update_get_buf_internal(reply, index, NULL); - LASSERT(ptr != NULL); - - *(int *)ptr = cpu_to_le32(rc); - ptr += sizeof(int); - if (data_len > 0) { - LASSERT(data != NULL); - memcpy(ptr, data, data_len); - } - reply->ur_lens[index] = data_len + sizeof(int); -} - -static inline int update_get_reply_buf(struct update_reply *reply, void **buf, - int index) -{ - char *ptr; - int size = 0; - int result; - - ptr = update_get_buf_internal(reply, index, &size); - result = *(int *)ptr; - - if (result < 0) - return result; - - LASSERT((ptr != NULL && size >= sizeof(int))); - *buf = ptr + sizeof(int); - return size - sizeof(int); -} - -static inline int update_get_reply_result(struct update_reply *reply, - void **buf, int index) -{ - void *ptr; - int size; - - ptr = update_get_buf_internal(reply, index, &size); - LASSERT(ptr != NULL && size > sizeof(int)); - return *(int *)ptr; -} - -#endif diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index dc5ceb5..bbef666b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -65,7 +65,6 @@ #endif /* struct ptlrpc_request, lustre_msg* */ #include "../include/lustre_req_layout.h" -#include "../include/lustre_update.h" #include "../include/lustre_acl.h" #include "../include/lustre_debug.h" -- cgit v0.10.2 From c5ce36f6b06217d6d03006a5fe2aef19918b9081 Mon Sep 17 00:00:00 2001 From: Asaf Vertz Date: Sun, 1 Feb 2015 13:28:46 +0200 Subject: staging: lustre: osc: fix space prohibited after that '!' Fixed a coding style error, space prohibited after that '!' Signed-off-by: Asaf Vertz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index a7f08bc..4456557 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -100,14 +100,14 @@ static int osc_lock_invariant(struct osc_lock *ols) /* * If all the following "ergo"s are true, return 1, otherwise 0 */ - if (! ergo(olock != NULL, handle_used)) + if (!ergo(olock != NULL, handle_used)) return 0; - if (! ergo(olock != NULL, + if (!ergo(olock != NULL, olock->l_handle.h_cookie == ols->ols_handle.cookie)) return 0; - if (! ergo(handle_used, + if (!ergo(handle_used, ergo(lock != NULL && olock != NULL, lock == olock) && ergo(lock == NULL, olock == NULL))) return 0; @@ -115,18 +115,18 @@ static int osc_lock_invariant(struct osc_lock *ols) * Check that ->ols_handle and ->ols_lock are consistent, but * take into account that they are set at the different time. */ - if (! ergo(ols->ols_state == OLS_CANCELLED, + if (!ergo(ols->ols_state == OLS_CANCELLED, olock == NULL && !handle_used)) return 0; /* * DLM lock is destroyed only after we have seen cancellation * ast. */ - if (! ergo(olock != NULL && ols->ols_state < OLS_CANCELLED, + if (!ergo(olock != NULL && ols->ols_state < OLS_CANCELLED, ((olock->l_flags & LDLM_FL_DESTROYED) == 0))) return 0; - if (! ergo(ols->ols_state == OLS_GRANTED, + if (!ergo(ols->ols_state == OLS_GRANTED, olock != NULL && olock->l_req_mode == olock->l_granted_mode && ols->ols_hold)) -- cgit v0.10.2 From 13534f8f310bcc2a0ac3184a160c72a17c244684 Mon Sep 17 00:00:00 2001 From: Asaf Vertz Date: Sun, 1 Feb 2015 13:29:23 +0200 Subject: staging: lustre: lnet: fix space prohibited before that '++' Fixed a coding style error, space prohibited before that '++' Signed-off-by: Asaf Vertz Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 3bb47fa..1e0afc2 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -46,17 +46,17 @@ #include "console.h" #include "conrpc.h" -#define LST_NODE_STATE_COUNTER(nd, p) \ -do { \ - if ((nd)->nd_state == LST_NODE_ACTIVE) \ - (p)->nle_nactive ++; \ +#define LST_NODE_STATE_COUNTER(nd, p) \ +do { \ + if ((nd)->nd_state == LST_NODE_ACTIVE) \ + (p)->nle_nactive++; \ else if ((nd)->nd_state == LST_NODE_BUSY) \ - (p)->nle_nbusy ++; \ + (p)->nle_nbusy++; \ else if ((nd)->nd_state == LST_NODE_DOWN) \ - (p)->nle_ndown ++; \ - else \ - (p)->nle_nunknown ++; \ - (p)->nle_nnode ++; \ + (p)->nle_ndown++; \ + else \ + (p)->nle_nunknown++; \ + (p)->nle_nnode++; \ } while (0) lstcon_session_t console_session; @@ -223,7 +223,7 @@ lstcon_group_alloc(char *name, lstcon_group_t **grpp) static void lstcon_group_addref(lstcon_group_t *grp) { - grp->grp_ref ++; + grp->grp_ref++; } static void lstcon_group_ndlink_release(lstcon_group_t *, lstcon_ndlink_t *); @@ -298,7 +298,7 @@ lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, return 0; list_add_tail(&(*ndlpp)->ndl_link, &grp->grp_ndl_list); - grp->grp_nnode ++; + grp->grp_nnode++; return 0; } @@ -324,7 +324,7 @@ lstcon_group_ndlink_move(lstcon_group_t *old, list_add_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]); list_add_tail(&ndl->ndl_link, &new->grp_ndl_list); - new->grp_nnode ++; + new->grp_nnode++; return; } @@ -767,7 +767,7 @@ lstcon_nodes_getent(struct list_head *head, int *index_p, &nd->nd_state, sizeof(nd->nd_state))) return -EFAULT; - count ++; + count++; } if (index <= *index_p) @@ -1343,7 +1343,7 @@ lstcon_test_add(char *batch_name, int type, int loop, /* add to test list anyway, so user can check what's going on */ list_add_tail(&test->tes_link, &batch->bat_test_list); - batch->bat_ntest ++; + batch->bat_ntest++; test->tes_hdr.tsb_index = batch->bat_ntest; /* hold groups so nobody can change them */ -- cgit v0.10.2 From 2661e6c45625abd32d6447cafb8d9b99839ce408 Mon Sep 17 00:00:00 2001 From: Li Xi Date: Sun, 1 Feb 2015 21:52:03 -0500 Subject: staging/lustre/libcfs: fix illegal page access of tracefiled() After failure happens and put_pages_back() returns the pages, tracefiled() should not go on itering on the page list. Otherwise, some pages might be accessed illegally. Signed-off-by: Li Xi Signed-off-by: Jian Yu Reviewed-on: http://review.whamcloud.com/11454 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5126 Reviewed-by: Emoly Liu Reviewed-by: Niu Yawei Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.c b/drivers/staging/lustre/lustre/libcfs/tracefile.c index d18de04..eb65b50 100644 --- a/drivers/staging/lustre/lustre/libcfs/tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/tracefile.c @@ -1037,6 +1037,7 @@ static int tracefiled(void *arg) tage->used, rc); put_pages_back(&pc); __LASSERT(list_empty(&pc.pc_pages)); + break; } } MMSPACE_CLOSE; -- cgit v0.10.2 From 62e4941354c38c968474a909a5a89395ccff0067 Mon Sep 17 00:00:00 2001 From: Hongchao Zhang Date: Sun, 1 Feb 2015 21:52:04 -0500 Subject: staging/lustre/obdclass: fix a race in recovery in "class_export_recovery_cleanup", the check of the flag "exp->exp_req_replay_needed" should be protected by "exp_lock". Signed-off-by: Hongchao Zhang Reviewed-on: http://review.whamcloud.com/10849 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5128 Reviewed-by: Fan Yong Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index 736ca410..8250821 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -1151,22 +1151,24 @@ void class_export_recovery_cleanup(struct obd_export *exp) exp->exp_obd->obd_stale_clients++; } spin_unlock(&obd->obd_recovery_task_lock); + + spin_lock(&exp->exp_lock); /** Cleanup req replay fields */ if (exp->exp_req_replay_needed) { - spin_lock(&exp->exp_lock); exp->exp_req_replay_needed = 0; - spin_unlock(&exp->exp_lock); + LASSERT(atomic_read(&obd->obd_req_replay_clients)); atomic_dec(&obd->obd_req_replay_clients); } + /** Cleanup lock replay data */ if (exp->exp_lock_replay_needed) { - spin_lock(&exp->exp_lock); exp->exp_lock_replay_needed = 0; - spin_unlock(&exp->exp_lock); + LASSERT(atomic_read(&obd->obd_lock_replay_clients)); atomic_dec(&obd->obd_lock_replay_clients); } + spin_unlock(&exp->exp_lock); } /* This function removes 1-3 references from the export: -- cgit v0.10.2 From af3fa7c71bf61a4ff8e9203860c24795183f9da4 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Sun, 1 Feb 2015 21:52:06 -0500 Subject: staging/lustre/lnet: peer aliveness status and NI status A couple of changes to improve aliveness detection: - When LNet received a message, it can determine peer of this message is alive - When LNet received a message from remote network, it can determine router is alive and NI status on router is UP. Signed-off-by: Liang Zhen Reviewed-on: http://review.whamcloud.com/12453 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5485 Reviewed-by: James Simmons Reviewed-by: Isaac Huang Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index 99fb52a..0038d29 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -636,6 +636,7 @@ lnet_net2rnethash(__u32 net) } extern lnd_t the_lolnd; +extern int avoid_asym_router_failure; int lnet_cpt_of_nid_locked(lnet_nid_t nid); int lnet_cpt_of_nid(lnet_nid_t nid); @@ -851,6 +852,7 @@ int lnet_peer_buffer_credits(lnet_ni_t *ni); int lnet_router_checker_start(void); void lnet_router_checker_stop(void); +void lnet_router_ni_update_locked(lnet_peer_t *gw, __u32 net); void lnet_swap_pinginfo(lnet_ping_info_t *info); int lnet_ping_target_init(void); @@ -870,4 +872,12 @@ void lnet_peer_tables_destroy(void); int lnet_peer_tables_create(void); void lnet_debug_peer(lnet_nid_t nid); +static inline void lnet_peer_set_alive(lnet_peer_t *lp) +{ + lp->lp_last_alive = lp->lp_last_query = get_seconds(); + if (!lp->lp_alive) + lnet_notify_locked(lp, 0, 1, lp->lp_last_alive); +} + + #endif diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index ed6eec9..0f53c76 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -1877,6 +1877,19 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, goto drop; } + if (lnet_isrouter(msg->msg_rxpeer)) { + lnet_peer_set_alive(msg->msg_rxpeer); + if (avoid_asym_router_failure && + LNET_NIDNET(src_nid) != LNET_NIDNET(from_nid)) { + /* received a remote message from router, update + * remote NI status on this router. + * NB: multi-hop routed message will be ignored. + */ + lnet_router_ni_update_locked(msg->msg_rxpeer, + LNET_NIDNET(src_nid)); + } + } + lnet_msg_commit(msg, cpt); if (!for_me) { diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index 1bbaa5b..52ec0ab 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -84,7 +84,7 @@ static int check_routers_before_use; module_param(check_routers_before_use, int, 0444); MODULE_PARM_DESC(check_routers_before_use, "Assume routers are down and ping them before use"); -static int avoid_asym_router_failure = 1; +int avoid_asym_router_failure = 1; module_param(avoid_asym_router_failure, int, 0644); MODULE_PARM_DESC(avoid_asym_router_failure, "Avoid asymmetrical router failures (0 to disable)"); @@ -783,6 +783,21 @@ lnet_wait_known_routerstate(void) } } +void +lnet_router_ni_update_locked(lnet_peer_t *gw, __u32 net) +{ + lnet_route_t *rte; + + if ((gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) != 0) { + list_for_each_entry(rte, &gw->lp_routes, lr_gwlist) { + if (rte->lr_net == net) { + rte->lr_downis = 0; + break; + } + } + } +} + static void lnet_update_ni_status_locked(void) { -- cgit v0.10.2 From c2fcdf6c427c9c2e305320d6ee82a8ca9f4fa961 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Sun, 1 Feb 2015 21:52:07 -0500 Subject: staging/lustre/llite: to configure max_cached_mb correctly If there exists MGS conf_param to reduce the memory cache max_cached_mb it will fail because dt_exp is not initialized yet. It should just go ahead and configure it because certainly it have enough free LRU slot to deduct ccc_lru_left. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/11783 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3676 Reviewed-by: Bobi Jam Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index e6a909e..aaa13bd 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -399,9 +399,6 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, return -ERANGE; } - if (sbi->ll_dt_exp == NULL) - return -ENODEV; - spin_lock(&sbi->ll_lock); diff = pages_number - cache->ccc_lru_max; spin_unlock(&sbi->ll_lock); @@ -437,6 +434,11 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, if (diff <= 0) break; + if (sbi->ll_dt_exp == NULL) { /* being initialized */ + rc = -ENODEV; + break; + } + /* difficult - have to ask OSCs to drop LRU slots. */ tmp = diff << 1; rc = obd_set_info_async(NULL, sbi->ll_dt_exp, -- cgit v0.10.2 From 081fa9dffcde7c9fc4d9fdf18fe277dfa3f675aa Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 1 Feb 2015 21:52:08 -0500 Subject: staging/lustre/llite: remove llite proc root on init failure In init_lustre_lite() ensure that /proc/fs/lustre/llite is removed in case of failure. Generally rework the cleanup code in this function. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/6420 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3331 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c index 6aff155..7c1e02a 100644 --- a/drivers/staging/lustre/lustre/llite/super25.c +++ b/drivers/staging/lustre/lustre/llite/super25.c @@ -72,21 +72,6 @@ static void ll_destroy_inode(struct inode *inode) call_rcu(&inode->i_rcu, ll_inode_destroy_callback); } -static int ll_init_inodecache(void) -{ - ll_inode_cachep = kmem_cache_create("lustre_inode_cache", - sizeof(struct ll_inode_info), - 0, SLAB_HWCACHE_ALIGN, NULL); - if (ll_inode_cachep == NULL) - return -ENOMEM; - return 0; -} - -static void ll_destroy_inodecache(void) -{ - kmem_cache_destroy(ll_inode_cachep); -} - /* exported operations */ struct super_operations lustre_super_operations = { .alloc_inode = ll_alloc_inode, @@ -104,9 +89,10 @@ void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg)); static int __init init_lustre_lite(void) { - int i, rc, seed[2]; - struct timeval tv; + struct proc_dir_entry *entry; lnet_process_id_t lnet_id; + struct timeval tv; + int i, rc, seed[2]; CLASSERT(sizeof(LUSTRE_VOLATILE_HDR) == LUSTRE_VOLATILE_HDR_LEN + 1); @@ -116,59 +102,52 @@ static int __init init_lustre_lite(void) CDEBUG(D_INFO, "Lustre client module (%p).\n", &lustre_super_operations); - rc = ll_init_inodecache(); - if (rc) - return -ENOMEM; + rc = -ENOMEM; + ll_inode_cachep = kmem_cache_create("lustre_inode_cache", + sizeof(struct ll_inode_info), + 0, SLAB_HWCACHE_ALIGN, NULL); + if (ll_inode_cachep == NULL) + goto out_cache; + ll_file_data_slab = kmem_cache_create("ll_file_data", sizeof(struct ll_file_data), 0, SLAB_HWCACHE_ALIGN, NULL); - if (ll_file_data_slab == NULL) { - ll_destroy_inodecache(); - return -ENOMEM; - } + if (ll_file_data_slab == NULL) + goto out_cache; ll_remote_perm_cachep = kmem_cache_create("ll_remote_perm_cache", sizeof(struct ll_remote_perm), 0, 0, NULL); - if (ll_remote_perm_cachep == NULL) { - kmem_cache_destroy(ll_file_data_slab); - ll_file_data_slab = NULL; - ll_destroy_inodecache(); - return -ENOMEM; - } + if (ll_remote_perm_cachep == NULL) + goto out_cache; ll_rmtperm_hash_cachep = kmem_cache_create("ll_rmtperm_hash_cache", REMOTE_PERM_HASHSIZE * sizeof(struct list_head), 0, 0, NULL); - if (ll_rmtperm_hash_cachep == NULL) { - kmem_cache_destroy(ll_remote_perm_cachep); - ll_remote_perm_cachep = NULL; - kmem_cache_destroy(ll_file_data_slab); - ll_file_data_slab = NULL; - ll_destroy_inodecache(); - return -ENOMEM; + if (ll_rmtperm_hash_cachep == NULL) + goto out_cache; + + entry = lprocfs_register("llite", proc_lustre_root, NULL, NULL); + if (IS_ERR(entry)) { + rc = PTR_ERR(entry); + CERROR("cannot register '/proc/fs/lustre/llite': rc = %d\n", + rc); + goto out_cache; } - proc_lustre_fs_root = proc_lustre_root ? - lprocfs_register("llite", proc_lustre_root, NULL, NULL) : NULL; - - lustre_register_client_fill_super(ll_fill_super); - lustre_register_kill_super_cb(ll_kill_super); - - lustre_register_client_process_config(ll_process_config); + proc_lustre_fs_root = entry; cfs_get_random_bytes(seed, sizeof(seed)); - /* Nodes with small feet have little entropy - * the NID for this node gives the most entropy in the low bits */ - for (i = 0; ; i++) { - if (LNetGetId(i, &lnet_id) == -ENOENT) { + /* Nodes with small feet have little entropy. The NID for this + * node gives the most entropy in the low bits */ + for (i = 0;; i++) { + if (LNetGetId(i, &lnet_id) == -ENOENT) break; - } - if (LNET_NETTYP(LNET_NIDNET(lnet_id.nid)) != LOLND) { + + if (LNET_NETTYP(LNET_NIDNET(lnet_id.nid)) != LOLND) seed[0] ^= LNET_NIDADDR(lnet_id.nid); - } } do_gettimeofday(&tv); @@ -177,20 +156,54 @@ static int __init init_lustre_lite(void) init_timer(&ll_capa_timer); ll_capa_timer.function = ll_capa_timer_callback; rc = ll_capa_thread_start(); - /* - * XXX normal cleanup is needed here. - */ - if (rc == 0) - rc = vvp_global_init(); + if (rc != 0) + goto out_proc; - if (rc == 0) - rc = ll_xattr_init(); + rc = vvp_global_init(); + if (rc != 0) + goto out_capa; + + rc = ll_xattr_init(); + if (rc != 0) + goto out_vvp; + + lustre_register_client_fill_super(ll_fill_super); + lustre_register_kill_super_cb(ll_kill_super); + lustre_register_client_process_config(ll_process_config); + + return 0; + +out_vvp: + vvp_global_fini(); +out_capa: + del_timer(&ll_capa_timer); + ll_capa_thread_stop(); +out_proc: + lprocfs_remove(&proc_lustre_fs_root); +out_cache: + if (ll_inode_cachep != NULL) + kmem_cache_destroy(ll_inode_cachep); + + if (ll_file_data_slab != NULL) + kmem_cache_destroy(ll_file_data_slab); + + if (ll_remote_perm_cachep != NULL) + kmem_cache_destroy(ll_remote_perm_cachep); + + if (ll_rmtperm_hash_cachep != NULL) + kmem_cache_destroy(ll_rmtperm_hash_cachep); return rc; } static void __exit exit_lustre_lite(void) { + lustre_register_client_fill_super(NULL); + lustre_register_kill_super_cb(NULL); + lustre_register_client_process_config(NULL); + + lprocfs_remove(&proc_lustre_fs_root); + ll_xattr_fini(); vvp_global_fini(); del_timer(&ll_capa_timer); @@ -199,22 +212,12 @@ static void __exit exit_lustre_lite(void) "client remaining capa count %d\n", capa_count[CAPA_SITE_CLIENT]); - lustre_register_client_fill_super(NULL); - lustre_register_kill_super_cb(NULL); - - lustre_register_client_process_config(NULL); - - ll_destroy_inodecache(); - + kmem_cache_destroy(ll_inode_cachep); kmem_cache_destroy(ll_rmtperm_hash_cachep); - ll_rmtperm_hash_cachep = NULL; kmem_cache_destroy(ll_remote_perm_cachep); - ll_remote_perm_cachep = NULL; kmem_cache_destroy(ll_file_data_slab); - if (proc_lustre_fs_root && !IS_ERR(proc_lustre_fs_root)) - lprocfs_remove(&proc_lustre_fs_root); } MODULE_AUTHOR("Sun Microsystems, Inc. "); -- cgit v0.10.2 From dbab2d8563d8a988dd4ec740ab9c06a4f86890ea Mon Sep 17 00:00:00 2001 From: Henri Doreau Date: Sun, 1 Feb 2015 21:52:09 -0500 Subject: staging/lustre/obdclass: Proper swabbing of llog_rec_tail. A variable-length structure preceeds llog_rec_tail within an llog block. Thus cr_tail shouldn't be accessed directly as a structure member but its actual location should be computed dynamically. Signed-off-by: Henri Doreau Reviewed-on: http://review.whamcloud.com/11937 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5631 Reviewed-by: jacques-Charles Lafoucriere Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index d3ec90e..a2d5aa1 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -168,7 +168,8 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) } case CHANGELOG_REC: { - struct llog_changelog_rec *cr = (struct llog_changelog_rec *)rec; + struct llog_changelog_rec *cr = + (struct llog_changelog_rec *)rec; __swab16s(&cr->cr.cr_namelen); __swab16s(&cr->cr.cr_flags); @@ -188,6 +189,8 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) } else { tail = &cr->cr_tail; } + tail = (struct llog_rec_tail *)((char *)tail + + cr->cr.cr_namelen); break; } case CHANGELOG_USER_REC: -- cgit v0.10.2 From 70c86ace9008f83f3b3b0dd995c60942e1057347 Mon Sep 17 00:00:00 2001 From: Liang Zhen Date: Sun, 1 Feb 2015 21:52:10 -0500 Subject: staging/lustre/lnet: portal spreading rotor should be unsigned Portal spreading rotor should be unsigned, otherwise lnet may get negative CPT number and access invalid addresses. Signed-off-by: Liang Zhen Reviewed-on: http://review.whamcloud.com/11936 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5639 Reviewed-by: Amir Shehata Reviewed-by: Isaac Huang Reviewed-by: Doug Oucharek Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index ba1876f..50537668 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -622,7 +622,7 @@ typedef struct lnet_portal { /* Match table for each CPT */ struct lnet_match_table **ptl_mtables; /* spread rotor of incoming "PUT" */ - int ptl_rotor; + unsigned int ptl_rotor; /* # active entries for this portal */ int ptl_mt_nmaps; /* array of active entries' cpu-partition-id */ diff --git a/drivers/staging/lustre/lnet/lnet/lib-ptl.c b/drivers/staging/lustre/lnet/lnet/lib-ptl.c index 19ed696..3ba0da9 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-ptl.c +++ b/drivers/staging/lustre/lnet/lnet/lib-ptl.c @@ -262,10 +262,10 @@ lnet_mt_of_match(struct lnet_match_info *info, struct lnet_msg *msg) { struct lnet_match_table *mtable; struct lnet_portal *ptl; - int nmaps; - int rotor; - int routed; - int cpt; + unsigned int nmaps; + unsigned int rotor; + unsigned int cpt; + bool routed; /* NB: called w/o lock */ LASSERT(info->mi_portal < the_lnet.ln_nportals); -- cgit v0.10.2 From d27f9b077e113b0fa46e466465233a5e51085228 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Sun, 1 Feb 2015 21:52:12 -0500 Subject: staging/lustre/ptlrpc: hold rq_lock when modify rq_flags In after_reply(), take the rq_lock for changing the rq_resend. Signed-off-by: Niu Yawei Reviewed-on: http://review.whamcloud.com/11957 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5633 Reviewed-by: Fan Yong Reviewed-by: Johann Lombardi Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 8c1ec83..4882dd0 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1247,7 +1247,9 @@ static int after_reply(struct ptlrpc_request *req) time_t now = get_seconds(); DEBUG_REQ(D_RPCTRACE, req, "Resending request on EINPROGRESS"); + spin_lock(&req->rq_lock); req->rq_resend = 1; + spin_unlock(&req->rq_lock); req->rq_nr_resend++; /* allocate new xid to avoid reply reconstruction */ -- cgit v0.10.2 From 4c309612ddb9107c3fdbd5233198d59708114bc4 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Sun, 1 Feb 2015 21:52:13 -0500 Subject: staging/lustre/llite: Solve a race to access lli_has_smd in read case In vvp_io_read_lock(), it used to decide if to add read lock by checking lli_has_smd. Accessing lli_has_smd is racy when an empty file is turned into raid0, therefore, it may result in read requests are issued without corresponding lock. Signed-off-by: Jinshan Xiong Reviewed-on: http://review.whamcloud.com/12139 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5062 Reviewed-by: Bobi Jam Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h index 316500c..c5c3a8d 100644 --- a/drivers/staging/lustre/lustre/include/lclient.h +++ b/drivers/staging/lustre/lustre/include/lclient.h @@ -325,6 +325,7 @@ void ccc_lock_fini(const struct lu_env *env, struct cl_lock_slice *slice); int ccc_lock_enqueue(const struct lu_env *env, const struct cl_lock_slice *slice, struct cl_io *io, __u32 enqflags); +int ccc_lock_use(const struct lu_env *env, const struct cl_lock_slice *slice); int ccc_lock_unuse(const struct lu_env *env, const struct cl_lock_slice *slice); int ccc_lock_wait(const struct lu_env *env, const struct cl_lock_slice *slice); int ccc_lock_fits_into(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c index 24d26ab..23095bb 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c @@ -586,6 +586,12 @@ int ccc_lock_enqueue(const struct lu_env *env, return 0; } +int ccc_lock_use(const struct lu_env *env, const struct cl_lock_slice *slice) +{ + CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); + return 0; +} + int ccc_lock_unuse(const struct lu_env *env, const struct cl_lock_slice *slice) { CLOBINVRNT(env, slice->cls_obj, ccc_object_invariant(slice->cls_obj)); diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 65d610a..91bba79 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -307,18 +307,13 @@ static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io, static int vvp_io_read_lock(const struct lu_env *env, const struct cl_io_slice *ios) { - struct cl_io *io = ios->cis_io; - struct ll_inode_info *lli = ll_i2info(ccc_object_inode(io->ci_obj)); + struct cl_io *io = ios->cis_io; + struct cl_io_rw_common *rd = &io->u.ci_rd.rd; int result; - /* XXX: Layer violation, we shouldn't see lsm at llite level. */ - if (lli->lli_has_smd) /* lsm-less file doesn't need to lock */ - result = vvp_io_rw_lock(env, io, CLM_READ, - io->u.ci_rd.rd.crw_pos, - io->u.ci_rd.rd.crw_pos + - io->u.ci_rd.rd.crw_count - 1); - else - result = 0; + result = vvp_io_rw_lock(env, io, CLM_READ, rd->crw_pos, + rd->crw_pos + rd->crw_count - 1); + return result; } diff --git a/drivers/staging/lustre/lustre/llite/vvp_lock.c b/drivers/staging/lustre/lustre/llite/vvp_lock.c index 372633e..f354e82 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_lock.c +++ b/drivers/staging/lustre/lustre/llite/vvp_lock.c @@ -71,6 +71,7 @@ static const struct cl_lock_operations vvp_lock_ops = { .clo_fini = ccc_lock_fini, .clo_enqueue = ccc_lock_enqueue, .clo_wait = ccc_lock_wait, + .clo_use = ccc_lock_use, .clo_unuse = ccc_lock_unuse, .clo_fits_into = ccc_lock_fits_into, .clo_state = ccc_lock_state, -- cgit v0.10.2 From b7fb222b8acb13672fe37ba1da79f75263781edf Mon Sep 17 00:00:00 2001 From: wang di Date: Sun, 1 Feb 2015 21:52:14 -0500 Subject: staging/lustre/fld: refer to MDT0 for fld lookup in some cases It is possible that when fld client is trying to lookup seq on one of MDT, but the connection between the client and the MDT is not being initialized yet, especially during striped dir creation, because client will only send create req to the master MDT, then master MDT will distribute the operation to all of other MDT, instead of client distributing these requests, which will usually trigger the connection. In this case, we will send the fld request to MDT0, since it has all of location information. Signed-off-by: wang di Reviewed-on: http://review.whamcloud.com/11780 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4855 Reviewed-by: Fan Yong Reviewed-by: Mike Pershin Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index 7801db0..b8d17e1 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -131,11 +131,20 @@ fld_rrb_scan(struct lu_client_fld *fld, u64 seq) else hash = 0; +again: list_for_each_entry(target, &fld->lcf_targets, ft_chain) { if (target->ft_idx == hash) return target; } + if (hash != 0) { + /* It is possible the remote target(MDT) are not connected to + * with client yet, so we will refer this to MDT0, which should + * be connected during mount */ + hash = 0; + goto again; + } + CERROR("%s: Can't find target by hash %d (seq %#llx). Targets (%d):\n", fld->lcf_name, hash, seq, fld->lcf_count); -- cgit v0.10.2 From 7dd1107ad37a89e849f4fcbdb34fce775ce56db1 Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Sun, 1 Feb 2015 21:52:15 -0500 Subject: staging/lustre/libcfs: protect kkuc_groups from write access Since reg->kr_fp can be changed inside the foreach loop, kkuc_groups must be write protected, and not just read protected. This should fix the following oops, which could happen if two different threads simultaneously execute the function, and EPIPE is returned. PID: 24385 TASK: ffff88012da5f500 CPU: 1 COMMAND: "ldlm_cb00_056" #0 [ffff88012db55810] machine_kexec at ffffffff81038f3b #1 [ffff88012db55870] crash_kexec at ffffffff810c59f2 #2 [ffff88012db55940] oops_end at ffffffff8152b7f0 #3 [ffff88012db55970] no_context at ffffffff8104a00b #4 [ffff88012db559c0] __bad_area_nosemaphore at ffffffff8104a295 #5 [ffff88012db55a10] bad_area_nosemaphore at ffffffff8104a363 #6 [ffff88012db55a20] __do_page_fault at ffffffff8104aabf #7 [ffff88012db55b40] do_page_fault at ffffffff8152d73e #8 [ffff88012db55b70] page_fault at ffffffff8152aaf5 [exception RIP: fput+9] RIP: ffffffff8118a509 RSP: ffff88012db55c20 RFLAGS: 00010246 RAX: 00000000ffffffe0 RBX: ffff8800a8ea4fc0 RCX: 0000000000000000 RDX: ffffffffa03c9eb0 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffff88012db55c20 R8: 00000000ffffff0a R9: 00000000fffffffc R10: 0000000000000001 R11: 282064656c696166 R12: ffffffffa03c9c60 R13: ffff88005df240f8 R14: 0000000000000000 R15: ffff88013b4ca000 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #9 [ffff88012db55c28] libcfs_kkuc_group_put at ffffffffa0388044 [libcfs] [ptlrpc] Signed-off-by: frank zago Reviewed-on: http://review.whamcloud.com/11355 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5458 Reviewed-by: Patrick Farrell Reviewed-by: James Simmons Reviewed-by: Dmitry Eremin Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c index e2aa637..d9b7c6b 100644 --- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c +++ b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c @@ -228,12 +228,12 @@ int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, if (kkuc_groups[group].next == NULL) return 0; - down_read(&kg_sem); + down_write(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { if (reg->kr_fp != NULL) rc = cb_func(reg->kr_data, cb_arg); } - up_read(&kg_sem); + up_write(&kg_sem); return rc; } -- cgit v0.10.2 From 437dfb201a55ff73954ae7455ef3d17be4b1c0f6 Mon Sep 17 00:00:00 2001 From: Yang Sheng Date: Sun, 1 Feb 2015 21:52:16 -0500 Subject: staging/lustre/llite: Add exception entry check after radix_tree We need to check for an exception entry after radix_tree lookup. Signed-off-by: Yang Sheng Signed-off-by: Oleg Drokin Reviewed-on: http://review.whamcloud.com/10709 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5162 Reviewed-by: Bob Glossman Reviewed-by: James Simmons Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index babba60..69a4a63 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -278,7 +278,7 @@ static struct page *ll_dir_page_locate(struct inode *dir, __u64 *hash, spin_lock_irq(&mapping->tree_lock); found = radix_tree_gang_lookup(&mapping->page_tree, (void **)&page, offset, 1); - if (found > 0) { + if (found > 0 && !radix_tree_exceptional_entry(page)) { struct lu_dirpage *dp; page_cache_get(page); -- cgit v0.10.2 From c67587a74847a27965ca1c6a4362c3b39e9943e1 Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Sun, 1 Feb 2015 21:52:17 -0500 Subject: staging/lustre/llite: don't add to page cache upon failure Reading directory pages may fail on MDS, in this case client should not cache a non-up-to-date directory page, because it will cause a later read on the same page fail. Signed-off-by: Lai Siyao Signed-off-by: Oleg Drokin Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5461 Reviewed-on: http://review.whamcloud.com/11450 Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 69a4a63..a182019 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -183,7 +183,10 @@ static int ll_dir_filler(void *_hash, struct page *page0) op_data->op_offset = hash; rc = md_readpage(exp, op_data, page_pool, &request); ll_finish_md_op_data(op_data); - if (rc == 0) { + if (rc < 0) { + /* page0 is special, which was added into page cache early */ + delete_from_page_cache(page0); + } else if (rc == 0) { body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); /* Checked by mdc_readpage() */ LASSERT(body != NULL); -- cgit v0.10.2 From 431b567856875536c7f574f30cd870d758aa6c2f Mon Sep 17 00:00:00 2001 From: Patrick Farrell Date: Sun, 1 Feb 2015 21:52:18 -0500 Subject: staging/lustre/clio: Do not allow group locks with gid 0 When a group lock with GID=0 is released (put_grouplock is called), an assertion in cl_put_grouplock is hit. We should not allow group lock requests with GID=0, instead we should return -EINVAL. Signed-off-by: Patrick Farrell Reviewed-on: http://review.whamcloud.com/12459 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5817 Reviewed-by: Andreas Dilger Reviewed-by: frank zago Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index ca270f4..7c7ef7e 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1553,6 +1553,11 @@ ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) struct ccc_grouplock grouplock; int rc; + if (arg == 0) { + CWARN("group id for group lock must not be 0\n"); + return -EINVAL; + } + if (ll_file_nolock(file)) return -EOPNOTSUPP; -- cgit v0.10.2 From 3a09f36efd8f0c5c5d968fbbbb0967121076a25b Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 1 Feb 2015 21:52:19 -0500 Subject: staging/lustre/mdc: Initialize req in mdc_enqueue for !it case Commit ab909585b813 ("staging: lustre: Cleanup variable declarations in mdc_enqueue()") broke Lustre flock handling introducing access to uninitialized req variable, leading to bizzare crash in a later call to __req_capsule_offset with invalid pill value. Set req to NULL just for this case as in all other cases req is explicitly initialized with request packing call. Signed-off-by: Oleg Drokin CC: Srikrishan Malik Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 8c9b4f5..d1c224e 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -828,6 +828,7 @@ resend: einfo->ei_type); policy = (ldlm_policy_data_t *)lmm; res_id.name[3] = LDLM_FLOCK; + req = NULL; } else if (it->it_op & IT_OPEN) { req = mdc_intent_open_pack(exp, it, op_data, lmm, lmmsize, einfo->ei_cbdata); -- cgit v0.10.2 From 11862b36ce380211362a4845e479c8d7d220ce8c Mon Sep 17 00:00:00 2001 From: Max Perepelitsyn Date: Tue, 3 Feb 2015 14:44:28 +0600 Subject: staging: sm7xxfb: make smtc_scr_info static This symbol is never used anywhere else besides sm7xxfb.c Signed-off-by: Max Perepelitsyn Tested-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index 2ae9fd0..72036c2 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -111,7 +111,7 @@ static struct vesa_mode vesa_mode_table[] = { {"0x31B", 1280, 1024, 24}, }; -struct screen_info smtc_scr_info; +static struct screen_info smtc_scr_info; /* process command line options, get vga parameter */ static int __init sm7xx_vga_setup(char *options) -- cgit v0.10.2 From ceb2f735e826a410ba507948cf2a2b9d1f565181 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Tue, 3 Feb 2015 08:08:16 -0500 Subject: staging: rtl8723au: multiple condition with no effect - if identical to else A number if/else if/else branches are identical - so the condition has no effect on the effective code and can be significantly simplified - this patch removes the condition and the duplicated code. Signed-off-by: Nicholas Mc Guire Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c index 412d8cf..73cfddd 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c @@ -7255,63 +7255,19 @@ btdm_2AntTdmaDurationAdjust(struct rtw_adapter *padapter, u8 bScoHid, RTPRINT(FBT, BT_TRACE, ("[BTCoex], first run TdmaDurationAdjust()!!\n")); if (bScoHid) { if (bTxPause) { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } else { - btdm_2AntPsTdma(padapter, true, 15); - pBtdm8723->psTdmaDuAdjType = 15; - } + btdm_2AntPsTdma(padapter, true, 15); + pBtdm8723->psTdmaDuAdjType = 15; } else { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } else { - btdm_2AntPsTdma(padapter, true, 11); - pBtdm8723->psTdmaDuAdjType = 11; - } + btdm_2AntPsTdma(padapter, true, 11); + pBtdm8723->psTdmaDuAdjType = 11; } } else { if (bTxPause) { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } else { - btdm_2AntPsTdma(padapter, true, 7); - pBtdm8723->psTdmaDuAdjType = 7; - } + btdm_2AntPsTdma(padapter, true, 7); + pBtdm8723->psTdmaDuAdjType = 7; } else { - if (maxInterval == 1) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (maxInterval == 2) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else if (maxInterval == 3) { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } else { - btdm_2AntPsTdma(padapter, true, 3); - pBtdm8723->psTdmaDuAdjType = 3; - } + btdm_2AntPsTdma(padapter, true, 3); + pBtdm8723->psTdmaDuAdjType = 3; } } up = 0; -- cgit v0.10.2 From 741218984e472f6a8d4ace8d28eed5b163309443 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 3 Feb 2015 20:23:33 +0530 Subject: staging: sm7xxfb: fix CamelCase since mixed case names are not encouraged in coding, so those has been changed to their corresponding lowercase version. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/staging/sm7xxfb/sm7xx.h index 8599861..fe63cd7 100644 --- a/drivers/staging/sm7xxfb/sm7xx.h +++ b/drivers/staging/sm7xxfb/sm7xx.h @@ -29,14 +29,14 @@ #define dac_reg (0x3c8) #define dac_val (0x3c9) -extern void __iomem *smtc_RegBaseAddress; -#define smtc_mmiowb(dat, reg) writeb(dat, smtc_RegBaseAddress + reg) -#define smtc_mmioww(dat, reg) writew(dat, smtc_RegBaseAddress + reg) -#define smtc_mmiowl(dat, reg) writel(dat, smtc_RegBaseAddress + reg) +extern void __iomem *smtc_regbaseaddress; +#define smtc_mmiowb(dat, reg) writeb(dat, smtc_regbaseaddress + reg) +#define smtc_mmioww(dat, reg) writew(dat, smtc_regbaseaddress + reg) +#define smtc_mmiowl(dat, reg) writel(dat, smtc_regbaseaddress + reg) -#define smtc_mmiorb(reg) readb(smtc_RegBaseAddress + reg) -#define smtc_mmiorw(reg) readw(smtc_RegBaseAddress + reg) -#define smtc_mmiorl(reg) readl(smtc_RegBaseAddress + reg) +#define smtc_mmiorb(reg) readb(smtc_regbaseaddress + reg) +#define smtc_mmiorw(reg) readw(smtc_regbaseaddress + reg) +#define smtc_mmiorl(reg) readl(smtc_regbaseaddress + reg) #define SIZE_SR00_SR04 (0x04 - 0x00 + 1) #define SIZE_SR10_SR24 (0x24 - 0x10 + 1) diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index 72036c2..f8ecb69 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -56,7 +56,7 @@ struct smtcfb_info { u32 colreg[17]; }; -void __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */ +void __iomem *smtc_regbaseaddress; /* Memory Map IO starting address */ static struct fb_var_screeninfo smtcfb_var = { .xres = 1024, @@ -711,8 +711,8 @@ static void smtc_free_fb_info(struct smtcfb_info *sfb) static void smtc_unmap_mmio(struct smtcfb_info *sfb) { - if (sfb && smtc_RegBaseAddress) - smtc_RegBaseAddress = NULL; + if (sfb && smtc_regbaseaddress) + smtc_regbaseaddress = NULL; } /* @@ -823,7 +823,7 @@ static int smtcfb_pci_probe(struct pci_dev *pdev, #else sfb->lfb = ioremap(mmio_base, 0x00800000); #endif - sfb->mmio = (smtc_RegBaseAddress = + sfb->mmio = (smtc_regbaseaddress = sfb->lfb + 0x00700000); sfb->dp_regs = sfb->lfb + 0x00408000; sfb->vp_regs = sfb->lfb + 0x0040c000; @@ -833,7 +833,7 @@ static int smtcfb_pci_probe(struct pci_dev *pdev, dev_info(&pdev->dev, "sfb->lfb=%p", sfb->lfb); } #endif - if (!smtc_RegBaseAddress) { + if (!smtc_regbaseaddress) { dev_err(&pdev->dev, "%s: unable to map memory mapped IO!", sfb->fb.fix.id); @@ -859,7 +859,7 @@ static int smtcfb_pci_probe(struct pci_dev *pdev, smem_size = SM722_VIDEOMEMORYSIZE; sfb->dp_regs = ioremap(mmio_base, 0x00a00000); sfb->lfb = sfb->dp_regs + 0x00200000; - sfb->mmio = (smtc_RegBaseAddress = + sfb->mmio = (smtc_regbaseaddress = sfb->dp_regs + 0x000c0000); sfb->vp_regs = sfb->dp_regs + 0x800; -- cgit v0.10.2 From c4d507677fe0913cb4f14338b990ae8229d37940 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 3 Feb 2015 20:23:34 +0530 Subject: staging: sm7xxfb: fix remaining CamelCase since mixed case names are not encouraged in coding, so those has been changed to their corresponding lowercase version. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/staging/sm7xxfb/sm7xx.h index fe63cd7..7cc1896 100644 --- a/drivers/staging/sm7xxfb/sm7xx.h +++ b/drivers/staging/sm7xxfb/sm7xx.h @@ -99,27 +99,27 @@ static inline unsigned int smtc_seqr(int reg) */ struct ModeInit { - int mmSizeX; - int mmSizeY; + int mmsizex; + int mmsizey; int bpp; int hz; - unsigned char Init_MISC; - unsigned char Init_SR00_SR04[SIZE_SR00_SR04]; - unsigned char Init_SR10_SR24[SIZE_SR10_SR24]; - unsigned char Init_SR30_SR75[SIZE_SR30_SR75]; - unsigned char Init_SR80_SR93[SIZE_SR80_SR93]; - unsigned char Init_SRA0_SRAF[SIZE_SRA0_SRAF]; - unsigned char Init_GR00_GR08[SIZE_GR00_GR08]; - unsigned char Init_AR00_AR14[SIZE_AR00_AR14]; - unsigned char Init_CR00_CR18[SIZE_CR00_CR18]; - unsigned char Init_CR30_CR4D[SIZE_CR30_CR4D]; - unsigned char Init_CR90_CRA7[SIZE_CR90_CRA7]; + unsigned char init_misc; + unsigned char init_sr00_sr04[SIZE_SR00_SR04]; + unsigned char init_sr10_sr24[SIZE_SR10_SR24]; + unsigned char init_sr30_sr75[SIZE_SR30_SR75]; + unsigned char init_sr80_sr93[SIZE_SR80_SR93]; + unsigned char init_sra0_sraf[SIZE_SRA0_SRAF]; + unsigned char init_gr00_gr08[SIZE_GR00_GR08]; + unsigned char init_ar00_ar14[SIZE_AR00_AR14]; + unsigned char init_cr00_cr18[SIZE_CR00_CR18]; + unsigned char init_cr30_cr4d[SIZE_CR30_CR4D]; + unsigned char init_cr90_cra7[SIZE_CR90_CRA7]; }; /********************************************************************** SM712 Mode table. **********************************************************************/ -struct ModeInit VGAMode[] = { +struct ModeInit vgamode[] = { { /* mode#0: 640 x 480 16Bpp 60Hz */ 640, 480, 16, 60, @@ -776,4 +776,4 @@ struct ModeInit VGAMode[] = { }, }; -#define numVGAModes ARRAY_SIZE(VGAMode) +#define numvgamodes ARRAY_SIZE(vgamode) diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index f8ecb69..ebd9536 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -470,38 +470,38 @@ smtcfb_write(struct fb_info *info, const char __user *buf, size_t count, static void sm7xx_set_timing(struct smtcfb_info *sfb) { int i = 0, j = 0; - u32 m_nScreenStride; + u32 m_nscreenstride; dev_dbg(&sfb->pdev->dev, "sfb->width=%d sfb->height=%d sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n", sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz); - for (j = 0; j < numVGAModes; j++) { - if (VGAMode[j].mmSizeX == sfb->width && - VGAMode[j].mmSizeY == sfb->height && - VGAMode[j].bpp == sfb->fb.var.bits_per_pixel && - VGAMode[j].hz == sfb->hz) { + for (j = 0; j < numvgamodes; j++) { + if (vgamode[j].mmsizex == sfb->width && + vgamode[j].mmsizey == sfb->height && + vgamode[j].bpp == sfb->fb.var.bits_per_pixel && + vgamode[j].hz == sfb->hz) { dev_dbg(&sfb->pdev->dev, - "VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d VGAMode[j].bpp=%d VGAMode[j].hz=%d\n", - VGAMode[j].mmSizeX, VGAMode[j].mmSizeY, - VGAMode[j].bpp, VGAMode[j].hz); + "vgamode[j].mmsizex=%d vgamode[j].mmSizeY=%d vgamode[j].bpp=%d vgamode[j].hz=%d\n", + vgamode[j].mmsizex, vgamode[j].mmsizey, + vgamode[j].bpp, vgamode[j].hz); - dev_dbg(&sfb->pdev->dev, "VGAMode index=%d\n", j); + dev_dbg(&sfb->pdev->dev, "vgamode index=%d\n", j); smtc_mmiowb(0x0, 0x3c6); smtc_seqw(0, 0x1); - smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2); + smtc_mmiowb(vgamode[j].init_misc, 0x3c2); /* init SEQ register SR00 - SR04 */ for (i = 0; i < SIZE_SR00_SR04; i++) - smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]); + smtc_seqw(i, vgamode[j].init_sr00_sr04[i]); /* init SEQ register SR10 - SR24 */ for (i = 0; i < SIZE_SR10_SR24; i++) smtc_seqw(i + 0x10, - VGAMode[j].Init_SR10_SR24[i]); + vgamode[j].init_sr10_sr24[i]); /* init SEQ register SR30 - SR75 */ for (i = 0; i < SIZE_SR30_SR75; i++) @@ -509,39 +509,39 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb) (i + 0x30) != 0x6a && (i + 0x30) != 0x6b) smtc_seqw(i + 0x30, - VGAMode[j].Init_SR30_SR75[i]); + vgamode[j].init_sr30_sr75[i]); /* init SEQ register SR80 - SR93 */ for (i = 0; i < SIZE_SR80_SR93; i++) smtc_seqw(i + 0x80, - VGAMode[j].Init_SR80_SR93[i]); + vgamode[j].init_sr80_sr93[i]); /* init SEQ register SRA0 - SRAF */ for (i = 0; i < SIZE_SRA0_SRAF; i++) smtc_seqw(i + 0xa0, - VGAMode[j].Init_SRA0_SRAF[i]); + vgamode[j].init_sra0_sraf[i]); /* init Graphic register GR00 - GR08 */ for (i = 0; i < SIZE_GR00_GR08; i++) - smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]); + smtc_grphw(i, vgamode[j].init_gr00_gr08[i]); /* init Attribute register AR00 - AR14 */ for (i = 0; i < SIZE_AR00_AR14; i++) - smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]); + smtc_attrw(i, vgamode[j].init_ar00_ar14[i]); /* init CRTC register CR00 - CR18 */ for (i = 0; i < SIZE_CR00_CR18; i++) - smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]); + smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]); /* init CRTC register CR30 - CR4D */ for (i = 0; i < SIZE_CR30_CR4D; i++) smtc_crtcw(i + 0x30, - VGAMode[j].Init_CR30_CR4D[i]); + vgamode[j].init_cr30_cr4d[i]); /* init CRTC register CR90 - CRA7 */ for (i = 0; i < SIZE_CR90_CRA7; i++) smtc_crtcw(i + 0x90, - VGAMode[j].Init_CR90_CRA7[i]); + vgamode[j].init_cr90_cra7[i]); } } smtc_mmiowb(0x67, 0x3c2); @@ -551,7 +551,7 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb) writel(0x0, sfb->vp_regs + 0x40); /* set data width */ - m_nScreenStride = + m_nscreenstride = (sfb->width * sfb->fb.var.bits_per_pixel) / 64; switch (sfb->fb.var.bits_per_pixel) { case 8: @@ -567,7 +567,7 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb) writel(0x00030000, sfb->vp_regs + 0x0); break; } - writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride), + writel((u32) (((m_nscreenstride + 2) << 16) | m_nscreenstride), sfb->vp_regs + 0x10); } -- cgit v0.10.2 From 9b1af46b3ae1880f7ab7b1f1598b4daf2ddec8e4 Mon Sep 17 00:00:00 2001 From: Bilel DRIRA Date: Tue, 3 Feb 2015 21:26:27 +0100 Subject: staging: ft1000: fix braces warning This patch fix checkpatch.pl WARNING: WARNING: braces {} are not necessary for single statement blocks Signed-off-by: Bilel DRIRA Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c index 5e0cdcf..017c3b9 100644 --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c @@ -204,11 +204,11 @@ static inline void ft1000_write_dpram_mag_16(struct net_device *dev, /* Provide mutual exclusive access while reading ASIC registers. */ spin_lock_irqsave(&info->dpram_lock, flags); ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, offset); - if (Index) { + if (Index) ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAL, value); - } else { + else ft1000_write_reg(dev, FT1000_REG_MAG_DPDATAH, value); - } + spin_unlock_irqrestore(&info->dpram_lock, flags); } @@ -440,9 +440,8 @@ static int ft1000_reset_card(struct net_device *dev) tempword = ft1000_read_dpram_mag_16(dev, FT1000_MAG_DPRAM_FEFE, FT1000_MAG_DPRAM_FEFE_INDX); - if (tempword == 0xfefe) { + if (tempword == 0xfefe) break; - } mdelay(20); } @@ -621,9 +620,9 @@ static void ft1000_hbchk(u_long data) tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); /* Let's check doorbell again if fail */ - if (tempword & FT1000_DB_HB) { + if (tempword & FT1000_DB_HB) tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); - } + if (tempword & FT1000_DB_HB) { pr_info("heartbeat doorbell not clear by firmware\n"); if (info->AsicID == ELECTRABUZZ_ID) { @@ -766,9 +765,8 @@ static void ft1000_send_cmd(struct net_device *dev, u16 *ptempbuffer, int size, size += sizeof(struct pseudo_hdr); /* check for odd byte and increment to 16-bit word align value */ - if ((size & 0x0001)) { + if ((size & 0x0001)) size++; - } pr_debug("total length = %d\n", size); pr_debug("length = %d\n", ntohs(*ptempbuffer)); /* @@ -911,9 +909,8 @@ static bool ft1000_receive_cmd(struct net_device *dev, u16 *pbuffer, * Calculate pseudo header checksum */ tempword = *ppseudohdr++; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) tempword ^= *ppseudohdr++; - } if ((tempword != *ppseudohdr)) { pr_debug("Pseudo header checksum mismatch\n"); /* Drop this message */ @@ -977,9 +974,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev) while (tempword & FT1000_DB_DPRAM_TX) { mdelay(5); i++; - if (i == 10) { + if (i == 10) break; - } } ptr = list_entry(info->prov_list.next, @@ -1099,9 +1095,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev) mdelay(10); tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); - if (tempword & FT1000_DB_DPRAM_TX) { + if (tempword & FT1000_DB_DPRAM_TX) mdelay(10); - } } if ((tempword & FT1000_DB_DPRAM_TX) == 0) { @@ -1128,9 +1123,9 @@ static void ft1000_proc_drvmsg(struct net_device *dev) ppseudo_hdr->portsrc = 0; /* Calculate new checksum */ ppseudo_hdr->checksum = *pmsg++; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) ppseudo_hdr->checksum ^= *pmsg++; - } + info->DSPInfoBlk[8] = 0x7200; info->DSPInfoBlk[9] = htons(info->DSPInfoBlklen); @@ -1150,9 +1145,8 @@ static void ft1000_proc_drvmsg(struct net_device *dev) mdelay(10); tempword = ft1000_read_reg(dev, FT1000_REG_DOORBELL); - if (tempword & FT1000_DB_DPRAM_TX) { + if (tempword & FT1000_DB_DPRAM_TX) mdelay(10); - } } if ((tempword & FT1000_DB_DPRAM_TX) == 0) { @@ -1178,9 +1172,9 @@ static void ft1000_proc_drvmsg(struct net_device *dev) ppseudo_hdr->portsrc = 0; /* Calculate new checksum */ ppseudo_hdr->checksum = *pmsg++; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) ppseudo_hdr->checksum ^= *pmsg++; - } + pmsg = (u16 *)&tempbuffer[16]; *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG); *pmsg++ = htons(0x000e); @@ -1502,9 +1496,8 @@ static void ft1000_flush_fifo(struct net_device *dev, u16 DrvErrNum) tempword = inw(dev->base_addr + FT1000_REG_MAG_DFSR); pr_debug("FT1000_REG_MAG_DFSR = 0x%x\n", tempword); } - if (DrvErrNum) { + if (DrvErrNum) pcmcia->PktIntfErr++; - } } } @@ -1561,9 +1554,9 @@ static int ft1000_copy_up_pkt(struct net_device *dev) if (skb == NULL) { pr_debug("No Network buffers available\n"); /* Read High word to complete 32 bit access */ - if (info->AsicID == MAGNEMITE_ID) { + if (info->AsicID == MAGNEMITE_ID) tempword = ft1000_read_reg(dev, FT1000_REG_MAG_DFRH); - } + ft1000_flush_fifo(dev, 0); info->stats.rx_errors++; return FAILURE; @@ -1667,9 +1660,8 @@ static int ft1000_copy_up_pkt(struct net_device *dev) } pr_debug("Data passed to Protocol layer:\n"); - for (i = 0; i < len + 12; i++) { + for (i = 0; i < len + 12; i++) pr_debug("Protocol Data: 0x%x\n", *ptemp++); - } skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); @@ -1723,21 +1715,16 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) /* Check if there is room on the FIFO */ if (len > ft1000_read_fifo_len(dev)) { udelay(10); - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } - if (len > ft1000_read_fifo_len(dev)) { + if (len > ft1000_read_fifo_len(dev)) udelay(20); - } if (len > ft1000_read_fifo_len(dev)) { pr_debug("Transmit FIFO is full - pkt drop\n"); info->stats.tx_errors++; @@ -1745,11 +1732,11 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) } } /* Create pseudo header and send pseudo/ip to hardware */ - if (info->AsicID == ELECTRABUZZ_ID) { + if (info->AsicID == ELECTRABUZZ_ID) pseudo.blk.length = len; - } else { + else pseudo.blk.length = ntohs(len); - } + pseudo.blk.source = DSPID; /* Need to swap to get in correct order */ pseudo.blk.destination = HOSTID; pseudo.blk.portdest = NETWORKID; /* Need to swap to get in correct order */ @@ -1762,9 +1749,8 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) pseudo.blk.qos_class = 0; /* Calculate pseudo header checksum */ pseudo.blk.checksum = pseudo.buff[0]; - for (i = 1; i < 7; i++) { + for (i = 1; i < 7; i++) pseudo.blk.checksum ^= pseudo.buff[i]; - } /* Production Mode */ if (info->AsicID == ELECTRABUZZ_ID) { @@ -1829,9 +1815,8 @@ static int ft1000_copy_down_pkt(struct net_device *dev, u16 *packet, u16 len) plong = (u32 *)packet; /* Write PPP type + IP Packet into Downlink FIFO */ - for (i = 0; i < (len >> 2); i++) { + for (i = 0; i < (len >> 2); i++) outl(*plong++, dev->base_addr + FT1000_REG_MAG_UFDR); - } /* Check for odd alignment */ if (len & 0x0003) { -- cgit v0.10.2 From 3d272700d73c6503138759c1de6021ee4466e4d8 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Wed, 4 Feb 2015 05:28:54 -0500 Subject: staging: rtl8188eu: odm: condition with no effect The if and the else branch code are identical - so the condition has no effect on the effective code - this patch removes the condition and the duplicated code. Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 9873998..878c460 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -534,13 +534,8 @@ void odm_DIGInit(struct odm_dm_struct *pDM_Odm) pDM_DigTable->RssiHighThresh = DM_DIG_THRESH_HIGH; pDM_DigTable->FALowThresh = DM_false_ALARM_THRESH_LOW; pDM_DigTable->FAHighThresh = DM_false_ALARM_THRESH_HIGH; - if (pDM_Odm->BoardType == ODM_BOARD_HIGHPWR) { - 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; pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT; pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX; pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN; -- cgit v0.10.2 From e914024d46e3de3c5c3ce9c5b77b564ad6a264c0 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Wed, 4 Feb 2015 05:28:55 -0500 Subject: staging: rtl8188eu: odm: conditional setting with no effect The if and the else branch code are identical - so the condition has no effect on the effective code - this patch removes the condition and the duplicated code. Due to this being a fall-through-if here - the first if condition has no effect either - so it also can be removed. struct mlme_priv is thus also no longer needed here. Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c index 878c460..06477e8 100644 --- a/drivers/staging/rtl8188eu/hal/odm.c +++ b/drivers/staging/rtl8188eu/hal/odm.c @@ -1133,16 +1133,9 @@ static void FindMinimumRSSI(struct adapter *pAdapter) { struct hal_data_8188e *pHalData = GET_HAL_DATA(pAdapter); struct dm_priv *pdmpriv = &pHalData->dmpriv; - struct mlme_priv *pmlmepriv = &pAdapter->mlmepriv; - - /* 1 1.Determine the minimum RSSI */ - if ((check_fwstate(pmlmepriv, _FW_LINKED) == false) && - (pdmpriv->EntryMinUndecoratedSmoothedPWDB == 0)) - pdmpriv->MinUndecoratedPWDBForDM = 0; - if (check_fwstate(pmlmepriv, _FW_LINKED) == true) /* Default port */ - pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; - else /* associated entry pwdb */ - pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; + + /* 1 1.Unconditionally set RSSI */ + pdmpriv->MinUndecoratedPWDBForDM = pdmpriv->EntryMinUndecoratedSmoothedPWDB; } void odm_RSSIMonitorCheckCE(struct odm_dm_struct *pDM_Odm) -- cgit v0.10.2 From e971e8de383f91c418c924afd349766f33b20501 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Wed, 4 Feb 2015 06:04:38 -0500 Subject: staging: rtl8188eu: core: switch with redundant cases A few redundant switch cases as well as a redundant if/else within one of the cases was consolidated to a single call. The cases are intentionally retained for documentation purposes. case WIFI_REASSOCREQ,WIFI_PROBEREQ,WIFI_BEACON,WIFI_ACTION all have the same effect - notably the also for WIFI_PROBEREQ where the if/else is executing the same function. These redundant cases could all be dropped and consolidated into the default but probably it is better for documentation/readability to leave them in the switch/case explicitly. Signed-off-by: Nicholas Mc Guire Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 28918201..cd12dd7 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -484,17 +484,8 @@ void mgt_dispatcher(struct adapter *padapter, struct recv_frame *precv_frame) /* fall through */ case WIFI_ASSOCREQ: case WIFI_REASSOCREQ: - _mgt_dispatcher(padapter, ptable, precv_frame); - break; case WIFI_PROBEREQ: - if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) - _mgt_dispatcher(padapter, ptable, precv_frame); - else - _mgt_dispatcher(padapter, ptable, precv_frame); - break; case WIFI_BEACON: - _mgt_dispatcher(padapter, ptable, precv_frame); - break; case WIFI_ACTION: _mgt_dispatcher(padapter, ptable, precv_frame); break; -- cgit v0.10.2 From 6acbd7523d93946844b79c3fe684491b0b06de6e Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 4 Feb 2015 19:44:34 +0100 Subject: staging: lustre: make obd_updatemax_lock static obd_updatemax_lock is only used in class_obd.c Signed-off-by: Fabian Frederick Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 89a3fb2..29456e1 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -61,7 +61,7 @@ __u64 obd_alloc; EXPORT_SYMBOL(obd_alloc); __u64 obd_pages; EXPORT_SYMBOL(obd_pages); -DEFINE_SPINLOCK(obd_updatemax_lock); +static DEFINE_SPINLOCK(obd_updatemax_lock); /* The following are visible and mutable through /proc/sys/lustre/. */ unsigned int obd_alloc_fail_rate = 0; -- cgit v0.10.2 From 21fa7be013a66a5521bd2f7c83c9e357cafb091f Mon Sep 17 00:00:00 2001 From: Michael Hornung Date: Wed, 4 Feb 2015 19:54:49 +0100 Subject: staging: rtl8712: Do coding style cleanup * Fix checkpatch.pl warnings "Fix missing space after return type warning". Signed-off-by: Michael Hornung Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h index 3d0a98b..e62543d 100644 --- a/drivers/staging/rtl8712/drv_types.h +++ b/drivers/staging/rtl8712/drv_types.h @@ -129,8 +129,8 @@ struct dvobj_priv { struct _adapter *padapter; u32 nr_endpoint; u8 ishighspeed; - uint(*inirp_init)(struct _adapter *adapter); - uint(*inirp_deinit)(struct _adapter *adapter); + uint (*inirp_init)(struct _adapter *adapter); + uint (*inirp_deinit)(struct _adapter *adapter); struct usb_device *pusbdev; }; @@ -166,7 +166,7 @@ struct _adapter { pid_t evtThread; struct task_struct *xmitThread; pid_t recvThread; - uint(*dvobj_init)(struct _adapter *adapter); + uint (*dvobj_init)(struct _adapter *adapter); void (*dvobj_deinit)(struct _adapter *adapter); struct net_device *pnetdev; int bup; -- cgit v0.10.2 From 533e80b1ea709577ec5cf73b8b566569bc711259 Mon Sep 17 00:00:00 2001 From: Chen Weixiang Date: Thu, 5 Feb 2015 21:24:41 +0800 Subject: staging: lustre: lustre: libcfs: define symbols as static This patch fixes the following warning using sparse - warning: symbol 'libcfs_debug_mb' was not declared. Should it be static? - warning: symbol 'portal_enter_debugger' was not declared. Should it be static? Signed-off-by: Chen Weixiang Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/lustre/lustre/libcfs/debug.c b/drivers/staging/lustre/lustre/libcfs/debug.c index 7170088..76c62e8 100644 --- a/drivers/staging/lustre/lustre/libcfs/debug.c +++ b/drivers/staging/lustre/lustre/libcfs/debug.c @@ -57,7 +57,7 @@ module_param(libcfs_debug, int, 0644); MODULE_PARM_DESC(libcfs_debug, "Lustre kernel debug mask"); EXPORT_SYMBOL(libcfs_debug); -unsigned int libcfs_debug_mb = 0; +static unsigned int libcfs_debug_mb; module_param(libcfs_debug_mb, uint, 0644); MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size."); EXPORT_SYMBOL(libcfs_debug_mb); @@ -93,7 +93,7 @@ EXPORT_SYMBOL(libcfs_debug_binary); unsigned int libcfs_stack = 3 * THREAD_SIZE / 4; EXPORT_SYMBOL(libcfs_stack); -unsigned int portal_enter_debugger; +static unsigned int portal_enter_debugger; EXPORT_SYMBOL(portal_enter_debugger); unsigned int libcfs_catastrophe; -- cgit v0.10.2