D: PCA9634 driver
D: Option GTM671WFS
D: Fintek F81216A
+D: AD5761 iio driver
D: Various kernel hacks
S: Qtechnology A/S
S: Valby Langgade 142
6kohm_to_gnd: connected to ground via a 6kOhm resistor,
20kohm_to_gnd: connected to ground via a 20kOhm resistor,
100kohm_to_gnd: connected to ground via an 100kOhm resistor,
+ 125kohm_to_gnd: connected to ground via an 125kOhm resistor,
500kohm_to_gnd: connected to ground via a 500kOhm resistor,
+ 640kohm_to_gnd: connected to ground via a 640kOhm resistor,
three_state: left floating.
For a list of available output power down options read
outX_powerdown_mode_available. If Y is not present the
This ABI is especially applicable for humidity sensors
to heatup the device and get rid of any condensation
in some humidity environment
+
+What: /sys/bus/iio/devices/iio:deviceX/in_ph_raw
+KernelVersion: 4.5
+Contact: linux-iio@vger.kernel.org
+Description:
+ Raw (unscaled no offset etc.) pH reading of a substance as a negative
+ base-10 logarithm of hydrodium ions in a litre of water.
-Freescale MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC triaxial accelerometer
+Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC
+triaxial accelerometer
Required properties:
- compatible: should contain one of
+ * "fsl,mma8451"
* "fsl,mma8452"
* "fsl,mma8453"
* "fsl,mma8652"
--- /dev/null
+* AT91 SAMA5D2 Analog to Digital Converter (ADC)
+
+Required properties:
+ - compatible: Should be "atmel,sama5d2-adc".
+ - reg: Should contain ADC registers location and length.
+ - interrupts: Should contain the IRQ line for the ADC.
+ - clocks: phandle to device clock.
+ - clock-names: Must be "adc_clk".
+ - vref-supply: Supply used as reference for conversions.
+ - vddana-supply: Supply for the adc device.
+ - atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC.
+ - atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC.
+ - atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC.
+
+Example:
+
+adc: adc@fc030000 {
+ compatible = "atmel,sama5d2-adc";
+ reg = <0xfc030000 0x100>;
+ interrupts = <40 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&adc_clk>;
+ clock-names = "adc_clk";
+ atmel,min-sample-rate-hz = <200000>;
+ atmel,max-sample-rate-hz = <20000000>;
+ atmel,startup-time-ms = <4>;
+ vddana-supply = <&vdd_3v3_lp_reg>;
+ vref-supply = <&vdd_3v3_lp_reg>;
+}
"microchip,mcp3422" or
"microchip,mcp3423" or
"microchip,mcp3424" or
+ "microchip,mcp3425" or
"microchip,mcp3426" or
"microchip,mcp3427" or
"microchip,mcp3428"
--- /dev/null
+* Atlas Scientific pH-SM OEM sensor
+
+http://www.atlas-scientific.com/_files/_datasheets/_oem/pH_oem_datasheet.pdf
+
+Required properties:
+
+ - compatible: must be "atlas,ph-sm"
+ - reg: the I2C address of the sensor
+ - interrupt-parent: should be the phandle for the interrupt controller
+ - interrupts: the sole interrupt generated by the device
+
+ Refer to interrupt-controller/interrupts.txt for generic interrupt client
+ node bindings.
+
+Example:
+
+atlas@65 {
+ compatible = "atlas,ph-sm";
+ reg = <0x65>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <16 2>;
+};
Refer to interrupt-controller/interrupts.txt for generic
interrupt client node bindings.
+Optional properties:
+ - maxim,led-current-microamp: configuration for LED current in microamperes
+ while the engine is running. First indexed value is the configuration for
+ the RED LED, and second value is for the IR LED.
+
+ Refer to the datasheet for the allowed current values.
+
Example:
max30100@057 {
compatible = "maxim,max30100";
reg = <57>;
+ maxim,led-current-microamp = <24000 50000>;
interrupt-parent = <&gpio1>;
interrupts = <16 2>;
};
--- /dev/null
+* Texas Instruments OPT3001 Ambient Light Sensor
+
+The driver supports interrupt-driven and interrupt-less operation, depending
+on whether an interrupt property has been populated into the DT. Note that
+the optional generation of IIO events on rising/falling light threshold changes
+requires the use of interrupts. Without interrupts, only the simple reading
+of the current light value is supported through the IIO API.
+
+http://www.ti.com/product/opt3001
+
+Required properties:
+ - compatible: should be "ti,opt3001"
+ - reg: the I2C address of the sensor
+
+Optional properties:
+ - interrupt-parent: should be the phandle for the interrupt controller
+ - interrupts: interrupt mapping for GPIO IRQ (configure for falling edge)
+
+Example:
+
+opt3001@44 {
+ compatible = "ti,opt3001";
+ reg = <0x44>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
+};
armadeus ARMadeus Systems SARL
artesyn Artesyn Embedded Technologies Inc.
asahi-kasei Asahi Kasei Corp.
+atlas Atlas Scientific LLC
atmel Atmel Corporation
auo AU Optronics Corporation
avago Avago Technologies
S: Supported
F: drivers/tty/serial/atmel_serial.c
+ATMEL SAMA5D2 ADC DRIVER
+M: Ludovic Desroches <ludovic.desroches@atmel.com>
+L: linux-iio@vger.kernel.org
+S: Supported
+F: drivers/iio/adc/at91-sama5d2_adc.c
+
ATMEL Audio ALSA driver
M: Nicolas Ferre <nicolas.ferre@atmel.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained
F: drivers/staging/dgnc/
-DIGI EPCA PCI PRODUCTS
-M: Lidza Louina <lidza.louina@gmail.com>
-M: Daeseok Youn <daeseok.youn@gmail.com>
-L: driverdev-devel@linuxdriverproject.org
-S: Maintained
-F: drivers/staging/dgap/
-
DIOLAN U2C-12 I2C DRIVER
M: Guenter Roeck <linux@roeck-us.net>
L: linux-i2c@vger.kernel.org
F: Documentation/mn10300/
F: arch/mn10300/
+PARALLEL LCD/KEYPAD PANEL DRIVER
+M: Willy Tarreau <willy@haproxy.com>
+M: Ksenija Stanojevic <ksenija.stanojevic@gmail.com>
+S: Odd Fixes
+F: Documentation/misc-devices/lcd-panel-cgram.txt
+F: drivers/misc/panel.c
+
PARALLEL PORT SUBSYSTEM
M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
M: Sudip Mukherjee <sudip@vectorindia.org>
S: Maintained
F: drivers/staging/nvec/
-STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
-M: Jens Frederich <jfrederich@gmail.com>
-M: Daniel Drake <dsd@laptop.org>
-M: Jon Nettleton <jon.nettleton@gmail.com>
-W: http://wiki.laptop.org/go/DCON
-S: Maintained
-F: drivers/staging/olpc_dcon/
-
-STAGING - PARALLEL LCD/KEYPAD PANEL DRIVER
-M: Willy Tarreau <willy@meta-x.org>
-S: Odd Fixes
-F: drivers/staging/panel/
-
STAGING - REALTEK RTL8712U DRIVERS
M: Larry Finger <Larry.Finger@lwfinger.net>
M: Florian Schilhabel <florian.c.schilhabel@googlemail.com>.
/*pr_info("binder_ioctl: %d:%d %x %lx\n",
proc->pid, current->pid, cmd, arg);*/
+ if (unlikely(current->mm != proc->vma_vm_mm)) {
+ pr_err("current mm mismatch proc mm\n");
+ return -EINVAL;
+ }
trace_binder_ioctl(cmd, arg);
ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
return -ENOMEM;
get_task_struct(current);
proc->tsk = current;
+ proc->vma_vm_mm = current->mm;
INIT_LIST_HEAD(&proc->todo);
init_waitqueue_head(&proc->wait);
proc->default_priority = task_nice(current);
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for the following Freescale 3-axis
- accelerometers: MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC.
+ accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC.
To compile this driver as a module, choose M here: the module
will be called mma8452.
/*
* mma8452.c - Support for following Freescale 3-axis accelerometers:
*
+ * MMA8451Q (14 bit)
* MMA8452Q (12 bit)
* MMA8453Q (10 bit)
* MMA8652FC (12 bit)
*
* 7-bit I2C slave address 0x1c/0x1d (pin selectable)
*
- * TODO: orientation / freefall events, autosleep
+ * TODO: orientation events, autosleep
*/
#include <linux/module.h>
#define MMA8452_INT_FF_MT BIT(2)
#define MMA8452_INT_TRANS BIT(5)
-#define MMA8452_DEVICE_ID 0x2a
-#define MMA8453_DEVICE_ID 0x3a
+#define MMA8451_DEVICE_ID 0x1a
+#define MMA8452_DEVICE_ID 0x2a
+#define MMA8453_DEVICE_ID 0x3a
#define MMA8652_DEVICE_ID 0x4a
#define MMA8653_DEVICE_ID 0x5a
return ret;
}
+/* returns >0 if in freefall mode, 0 if not or <0 if an error occured */
+static int mma8452_freefall_mode_enabled(struct mma8452_data *data)
+{
+ int val;
+ const struct mma_chip_info *chip = data->chip_info;
+
+ val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg);
+ if (val < 0)
+ return val;
+
+ return !(val & MMA8452_FF_MT_CFG_OAE);
+}
+
+static int mma8452_set_freefall_mode(struct mma8452_data *data, bool state)
+{
+ int val;
+ const struct mma_chip_info *chip = data->chip_info;
+
+ if ((state && mma8452_freefall_mode_enabled(data)) ||
+ (!state && !(mma8452_freefall_mode_enabled(data))))
+ return 0;
+
+ val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg);
+ if (val < 0)
+ return val;
+
+ if (state) {
+ val |= BIT(idx_x + chip->ev_cfg_chan_shift);
+ val |= BIT(idx_y + chip->ev_cfg_chan_shift);
+ val |= BIT(idx_z + chip->ev_cfg_chan_shift);
+ val &= ~MMA8452_FF_MT_CFG_OAE;
+ } else {
+ val &= ~BIT(idx_x + chip->ev_cfg_chan_shift);
+ val &= ~BIT(idx_y + chip->ev_cfg_chan_shift);
+ val &= ~BIT(idx_z + chip->ev_cfg_chan_shift);
+ val |= MMA8452_FF_MT_CFG_OAE;
+ }
+
+ val = mma8452_change_config(data, chip->ev_cfg, val);
+ if (val)
+ return val;
+
+ return 0;
+}
+
static int mma8452_set_hp_filter_frequency(struct mma8452_data *data,
int val, int val2)
{
const struct mma_chip_info *chip = data->chip_info;
int ret;
- ret = i2c_smbus_read_byte_data(data->client,
- data->chip_info->ev_cfg);
- if (ret < 0)
- return ret;
+ switch (dir) {
+ case IIO_EV_DIR_FALLING:
+ return mma8452_freefall_mode_enabled(data);
+ case IIO_EV_DIR_RISING:
+ if (mma8452_freefall_mode_enabled(data))
+ return 0;
+
+ ret = i2c_smbus_read_byte_data(data->client,
+ data->chip_info->ev_cfg);
+ if (ret < 0)
+ return ret;
- return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift));
+ return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift));
+ default:
+ return -EINVAL;
+ }
}
static int mma8452_write_event_config(struct iio_dev *indio_dev,
const struct mma_chip_info *chip = data->chip_info;
int val;
- val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg);
- if (val < 0)
- return val;
+ switch (dir) {
+ case IIO_EV_DIR_FALLING:
+ return mma8452_set_freefall_mode(data, state);
+ case IIO_EV_DIR_RISING:
+ val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg);
+ if (val < 0)
+ return val;
+
+ if (state) {
+ if (mma8452_freefall_mode_enabled(data)) {
+ val &= ~BIT(idx_x + chip->ev_cfg_chan_shift);
+ val &= ~BIT(idx_y + chip->ev_cfg_chan_shift);
+ val &= ~BIT(idx_z + chip->ev_cfg_chan_shift);
+ val |= MMA8452_FF_MT_CFG_OAE;
+ }
+ val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift);
+ } else {
+ if (mma8452_freefall_mode_enabled(data))
+ return 0;
- if (state)
- val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift);
- else
- val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift);
+ val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift);
+ }
- val |= chip->ev_cfg_ele;
- val |= MMA8452_FF_MT_CFG_OAE;
+ val |= chip->ev_cfg_ele;
- return mma8452_change_config(data, chip->ev_cfg, val);
+ return mma8452_change_config(data, chip->ev_cfg, val);
+ default:
+ return -EINVAL;
+ }
}
static void mma8452_transient_interrupt(struct iio_dev *indio_dev)
if (src < 0)
return;
+ if (mma8452_freefall_mode_enabled(data)) {
+ iio_push_event(indio_dev,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
+ IIO_MOD_X_AND_Y_AND_Z,
+ IIO_EV_TYPE_MAG,
+ IIO_EV_DIR_FALLING),
+ ts);
+ return;
+ }
+
if (src & data->chip_info->ev_src_xe)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X,
return 0;
}
+static const struct iio_event_spec mma8452_freefall_event[] = {
+ {
+ .type = IIO_EV_TYPE_MAG,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE),
+ .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_PERIOD) |
+ BIT(IIO_EV_INFO_HIGH_PASS_FILTER_3DB)
+ },
+};
+
+static const struct iio_event_spec mma8652_freefall_event[] = {
+ {
+ .type = IIO_EV_TYPE_MAG,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE),
+ .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_PERIOD)
+ },
+};
+
static const struct iio_event_spec mma8452_transient_event[] = {
{
.type = IIO_EV_TYPE_MAG,
.attrs = mma8452_event_attributes,
};
+#define MMA8452_FREEFALL_CHANNEL(modifier) { \
+ .type = IIO_ACCEL, \
+ .modified = 1, \
+ .channel2 = modifier, \
+ .scan_index = -1, \
+ .event_spec = mma8452_freefall_event, \
+ .num_event_specs = ARRAY_SIZE(mma8452_freefall_event), \
+}
+
+#define MMA8652_FREEFALL_CHANNEL(modifier) { \
+ .type = IIO_ACCEL, \
+ .modified = 1, \
+ .channel2 = modifier, \
+ .scan_index = -1, \
+ .event_spec = mma8652_freefall_event, \
+ .num_event_specs = ARRAY_SIZE(mma8652_freefall_event), \
+}
+
#define MMA8452_CHANNEL(axis, idx, bits) { \
.type = IIO_ACCEL, \
.modified = 1, \
.num_event_specs = ARRAY_SIZE(mma8452_motion_event), \
}
+static const struct iio_chan_spec mma8451_channels[] = {
+ MMA8452_CHANNEL(X, idx_x, 14),
+ MMA8452_CHANNEL(Y, idx_y, 14),
+ MMA8452_CHANNEL(Z, idx_z, 14),
+ IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
+ MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z),
+};
+
static const struct iio_chan_spec mma8452_channels[] = {
MMA8452_CHANNEL(X, idx_x, 12),
MMA8452_CHANNEL(Y, idx_y, 12),
MMA8452_CHANNEL(Z, idx_z, 12),
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
+ MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z),
};
static const struct iio_chan_spec mma8453_channels[] = {
MMA8452_CHANNEL(Y, idx_y, 10),
MMA8452_CHANNEL(Z, idx_z, 10),
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
+ MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z),
};
static const struct iio_chan_spec mma8652_channels[] = {
MMA8652_CHANNEL(Y, idx_y, 12),
MMA8652_CHANNEL(Z, idx_z, 12),
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
+ MMA8652_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z),
};
static const struct iio_chan_spec mma8653_channels[] = {
MMA8652_CHANNEL(Y, idx_y, 10),
MMA8652_CHANNEL(Z, idx_z, 10),
IIO_CHAN_SOFT_TIMESTAMP(idx_ts),
+ MMA8652_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z),
};
enum {
+ mma8451,
mma8452,
mma8453,
mma8652,
};
static const struct mma_chip_info mma_chip_info_table[] = {
- [mma8452] = {
- .chip_id = MMA8452_DEVICE_ID,
- .channels = mma8452_channels,
- .num_channels = ARRAY_SIZE(mma8452_channels),
+ [mma8451] = {
+ .chip_id = MMA8451_DEVICE_ID,
+ .channels = mma8451_channels,
+ .num_channels = ARRAY_SIZE(mma8451_channels),
/*
* Hardware has fullscale of -2G, -4G, -8G corresponding to
- * raw value -2048 for 12 bit or -512 for 10 bit.
+ * raw value -8192 for 14 bit, -2048 for 12 bit or -512 for 10
+ * bit.
* The userspace interface uses m/s^2 and we declare micro units
* So scale factor for 12 bit here is given by:
- * g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
+ * g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
*/
+ .mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
+ .ev_cfg = MMA8452_TRANSIENT_CFG,
+ .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
+ .ev_cfg_chan_shift = 1,
+ .ev_src = MMA8452_TRANSIENT_SRC,
+ .ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
+ .ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
+ .ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
+ .ev_ths = MMA8452_TRANSIENT_THS,
+ .ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
+ .ev_count = MMA8452_TRANSIENT_COUNT,
+ },
+ [mma8452] = {
+ .chip_id = MMA8452_DEVICE_ID,
+ .channels = mma8452_channels,
+ .num_channels = ARRAY_SIZE(mma8452_channels),
.mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} },
.ev_cfg = MMA8452_TRANSIENT_CFG,
.ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
}
static const struct of_device_id mma8452_dt_ids[] = {
+ { .compatible = "fsl,mma8451", .data = &mma_chip_info_table[mma8451] },
{ .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] },
{ .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] },
{ .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] },
return ret;
switch (ret) {
+ case MMA8451_DEVICE_ID:
case MMA8452_DEVICE_ID:
case MMA8453_DEVICE_ID:
case MMA8652_DEVICE_ID:
if (ret < 0)
goto buffer_cleanup;
+ ret = mma8452_set_freefall_mode(data, false);
+ if (ret)
+ return ret;
+
return 0;
buffer_cleanup:
#define ST_ACCEL_1_DRDY_IRQ_ADDR 0x22
#define ST_ACCEL_1_DRDY_IRQ_INT1_MASK 0x10
#define ST_ACCEL_1_DRDY_IRQ_INT2_MASK 0x08
+#define ST_ACCEL_1_IHL_IRQ_ADDR 0x25
+#define ST_ACCEL_1_IHL_IRQ_MASK 0x02
#define ST_ACCEL_1_MULTIREAD_BIT true
/* CUSTOM VALUES FOR SENSOR 2 */
#define ST_ACCEL_2_DRDY_IRQ_ADDR 0x22
#define ST_ACCEL_2_DRDY_IRQ_INT1_MASK 0x02
#define ST_ACCEL_2_DRDY_IRQ_INT2_MASK 0x10
+#define ST_ACCEL_2_IHL_IRQ_ADDR 0x22
+#define ST_ACCEL_2_IHL_IRQ_MASK 0x80
#define ST_ACCEL_2_MULTIREAD_BIT true
/* CUSTOM VALUES FOR SENSOR 3 */
#define ST_ACCEL_3_DRDY_IRQ_ADDR 0x23
#define ST_ACCEL_3_DRDY_IRQ_INT1_MASK 0x80
#define ST_ACCEL_3_DRDY_IRQ_INT2_MASK 0x00
+#define ST_ACCEL_3_IHL_IRQ_ADDR 0x23
+#define ST_ACCEL_3_IHL_IRQ_MASK 0x40
#define ST_ACCEL_3_IG1_EN_ADDR 0x23
#define ST_ACCEL_3_IG1_EN_MASK 0x08
#define ST_ACCEL_3_MULTIREAD_BIT false
#define ST_ACCEL_5_DRDY_IRQ_ADDR 0x22
#define ST_ACCEL_5_DRDY_IRQ_INT1_MASK 0x04
#define ST_ACCEL_5_DRDY_IRQ_INT2_MASK 0x20
+#define ST_ACCEL_5_IHL_IRQ_ADDR 0x22
+#define ST_ACCEL_5_IHL_IRQ_MASK 0x80
#define ST_ACCEL_5_IG1_EN_ADDR 0x21
#define ST_ACCEL_5_IG1_EN_MASK 0x08
#define ST_ACCEL_5_MULTIREAD_BIT false
.addr = ST_ACCEL_1_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_1_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK,
+ .addr_ihl = ST_ACCEL_1_IHL_IRQ_ADDR,
+ .mask_ihl = ST_ACCEL_1_IHL_IRQ_MASK,
},
.multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT,
.bootime = 2,
.addr = ST_ACCEL_2_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_2_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK,
+ .addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR,
+ .mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK,
},
.multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
.bootime = 2,
.addr = ST_ACCEL_3_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_3_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK,
+ .addr_ihl = ST_ACCEL_3_IHL_IRQ_ADDR,
+ .mask_ihl = ST_ACCEL_3_IHL_IRQ_MASK,
.ig1 = {
.en_addr = ST_ACCEL_3_IG1_EN_ADDR,
.en_mask = ST_ACCEL_3_IG1_EN_MASK,
.addr = ST_ACCEL_5_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_5_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK,
+ .addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR,
+ .mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK,
},
.multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT,
.bootime = 2, /* guess */
To compile this driver as a module, choose M here: the module will be
called at91_adc.
+config AT91_SAMA5D2_ADC
+ tristate "Atmel AT91 SAMA5D2 ADC"
+ depends on ARCH_AT91 || COMPILE_TEST
+ help
+ Say yes here to build support for Atmel SAMA5D2 ADC which is
+ available on SAMA5D2 SoC family.
+
+ To compile this driver as a module, choose M here: the module will be
+ called at91-sama5d2_adc.
+
config AXP288_ADC
tristate "X-Powers AXP288 ADC driver"
depends on MFD_AXP20X
called mcp320x.
config MCP3422
- tristate "Microchip Technology MCP3422/3/4/6/7/8 driver"
+ tristate "Microchip Technology MCP3421/2/3/4/5/6/7/8 driver"
depends on I2C
help
- Say yes here to build support for Microchip Technology's
- MCP3422, MCP3423, MCP3424, MCP3426, MCP3427 or MCP3428
+ Say yes here to build support for Microchip Technology's MCP3421
+ MCP3422, MCP3423, MCP3424, MCP3425, MCP3426, MCP3427 or MCP3428
analog to digital converters.
This driver can also be built as a module. If so, the module will be
obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
+obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o
obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o
obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
--- /dev/null
+/*
+ * Atmel ADC driver for SAMA5D2 devices and compatible.
+ *
+ * Copyright (C) 2015 Atmel,
+ * 2015 Ludovic Desroches <ludovic.desroches@atmel.com>
+ *
+ * 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 <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/regulator/consumer.h>
+
+/* Control Register */
+#define AT91_SAMA5D2_CR 0x00
+/* Software Reset */
+#define AT91_SAMA5D2_CR_SWRST BIT(0)
+/* Start Conversion */
+#define AT91_SAMA5D2_CR_START BIT(1)
+/* Touchscreen Calibration */
+#define AT91_SAMA5D2_CR_TSCALIB BIT(2)
+/* Comparison Restart */
+#define AT91_SAMA5D2_CR_CMPRST BIT(4)
+
+/* Mode Register */
+#define AT91_SAMA5D2_MR 0x04
+/* Trigger Selection */
+#define AT91_SAMA5D2_MR_TRGSEL(v) ((v) << 1)
+/* ADTRG */
+#define AT91_SAMA5D2_MR_TRGSEL_TRIG0 0
+/* TIOA0 */
+#define AT91_SAMA5D2_MR_TRGSEL_TRIG1 1
+/* TIOA1 */
+#define AT91_SAMA5D2_MR_TRGSEL_TRIG2 2
+/* TIOA2 */
+#define AT91_SAMA5D2_MR_TRGSEL_TRIG3 3
+/* PWM event line 0 */
+#define AT91_SAMA5D2_MR_TRGSEL_TRIG4 4
+/* PWM event line 1 */
+#define AT91_SAMA5D2_MR_TRGSEL_TRIG5 5
+/* TIOA3 */
+#define AT91_SAMA5D2_MR_TRGSEL_TRIG6 6
+/* RTCOUT0 */
+#define AT91_SAMA5D2_MR_TRGSEL_TRIG7 7
+/* Sleep Mode */
+#define AT91_SAMA5D2_MR_SLEEP BIT(5)
+/* Fast Wake Up */
+#define AT91_SAMA5D2_MR_FWUP BIT(6)
+/* Prescaler Rate Selection */
+#define AT91_SAMA5D2_MR_PRESCAL(v) ((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET)
+#define AT91_SAMA5D2_MR_PRESCAL_OFFSET 8
+#define AT91_SAMA5D2_MR_PRESCAL_MAX 0xff
+/* Startup Time */
+#define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16)
+/* Analog Change */
+#define AT91_SAMA5D2_MR_ANACH BIT(23)
+/* Tracking Time */
+#define AT91_SAMA5D2_MR_TRACKTIM(v) ((v) << 24)
+#define AT91_SAMA5D2_MR_TRACKTIM_MAX 0xff
+/* Transfer Time */
+#define AT91_SAMA5D2_MR_TRANSFER(v) ((v) << 28)
+#define AT91_SAMA5D2_MR_TRANSFER_MAX 0x3
+/* Use Sequence Enable */
+#define AT91_SAMA5D2_MR_USEQ BIT(31)
+
+/* Channel Sequence Register 1 */
+#define AT91_SAMA5D2_SEQR1 0x08
+/* Channel Sequence Register 2 */
+#define AT91_SAMA5D2_SEQR2 0x0c
+/* Channel Enable Register */
+#define AT91_SAMA5D2_CHER 0x10
+/* Channel Disable Register */
+#define AT91_SAMA5D2_CHDR 0x14
+/* Channel Status Register */
+#define AT91_SAMA5D2_CHSR 0x18
+/* Last Converted Data Register */
+#define AT91_SAMA5D2_LCDR 0x20
+/* Interrupt Enable Register */
+#define AT91_SAMA5D2_IER 0x24
+/* Interrupt Disable Register */
+#define AT91_SAMA5D2_IDR 0x28
+/* Interrupt Mask Register */
+#define AT91_SAMA5D2_IMR 0x2c
+/* Interrupt Status Register */
+#define AT91_SAMA5D2_ISR 0x30
+/* Last Channel Trigger Mode Register */
+#define AT91_SAMA5D2_LCTMR 0x34
+/* Last Channel Compare Window Register */
+#define AT91_SAMA5D2_LCCWR 0x38
+/* Overrun Status Register */
+#define AT91_SAMA5D2_OVER 0x3c
+/* Extended Mode Register */
+#define AT91_SAMA5D2_EMR 0x40
+/* Compare Window Register */
+#define AT91_SAMA5D2_CWR 0x44
+/* Channel Gain Register */
+#define AT91_SAMA5D2_CGR 0x48
+/* Channel Offset Register */
+#define AT91_SAMA5D2_COR 0x4c
+/* Channel Data Register 0 */
+#define AT91_SAMA5D2_CDR0 0x50
+/* Analog Control Register */
+#define AT91_SAMA5D2_ACR 0x94
+/* Touchscreen Mode Register */
+#define AT91_SAMA5D2_TSMR 0xb0
+/* Touchscreen X Position Register */
+#define AT91_SAMA5D2_XPOSR 0xb4
+/* Touchscreen Y Position Register */
+#define AT91_SAMA5D2_YPOSR 0xb8
+/* Touchscreen Pressure Register */
+#define AT91_SAMA5D2_PRESSR 0xbc
+/* Trigger Register */
+#define AT91_SAMA5D2_TRGR 0xc0
+/* Correction Select Register */
+#define AT91_SAMA5D2_COSR 0xd0
+/* Correction Value Register */
+#define AT91_SAMA5D2_CVR 0xd4
+/* Channel Error Correction Register */
+#define AT91_SAMA5D2_CECR 0xd8
+/* Write Protection Mode Register */
+#define AT91_SAMA5D2_WPMR 0xe4
+/* Write Protection Status Register */
+#define AT91_SAMA5D2_WPSR 0xe8
+/* Version Register */
+#define AT91_SAMA5D2_VERSION 0xfc
+
+#define AT91_AT91_SAMA5D2_CHAN(num, addr) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .channel = num, \
+ .address = addr, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 12, \
+ }, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+ .datasheet_name = "CH"#num, \
+ .indexed = 1, \
+ }
+
+#define at91_adc_readl(st, reg) readl_relaxed(st->base + reg)
+#define at91_adc_writel(st, reg, val) writel_relaxed(val, st->base + reg)
+
+struct at91_adc_soc_info {
+ unsigned startup_time;
+ unsigned min_sample_rate;
+ unsigned max_sample_rate;
+};
+
+struct at91_adc_state {
+ void __iomem *base;
+ int irq;
+ struct clk *per_clk;
+ struct regulator *reg;
+ struct regulator *vref;
+ int vref_uv;
+ const struct iio_chan_spec *chan;
+ bool conversion_done;
+ u32 conversion_value;
+ struct at91_adc_soc_info soc_info;
+ wait_queue_head_t wq_data_available;
+ /*
+ * lock to prevent concurrent 'single conversion' requests through
+ * sysfs.
+ */
+ struct mutex lock;
+};
+
+static const struct iio_chan_spec at91_adc_channels[] = {
+ AT91_AT91_SAMA5D2_CHAN(0, 0x50),
+ AT91_AT91_SAMA5D2_CHAN(1, 0x54),
+ AT91_AT91_SAMA5D2_CHAN(2, 0x58),
+ AT91_AT91_SAMA5D2_CHAN(3, 0x5c),
+ AT91_AT91_SAMA5D2_CHAN(4, 0x60),
+ AT91_AT91_SAMA5D2_CHAN(5, 0x64),
+ AT91_AT91_SAMA5D2_CHAN(6, 0x68),
+ AT91_AT91_SAMA5D2_CHAN(7, 0x6c),
+ AT91_AT91_SAMA5D2_CHAN(8, 0x70),
+ AT91_AT91_SAMA5D2_CHAN(9, 0x74),
+ AT91_AT91_SAMA5D2_CHAN(10, 0x78),
+ AT91_AT91_SAMA5D2_CHAN(11, 0x7c),
+};
+
+static unsigned at91_adc_startup_time(unsigned startup_time_min,
+ unsigned adc_clk_khz)
+{
+ const unsigned startup_lookup[] = {
+ 0, 8, 16, 24,
+ 64, 80, 96, 112,
+ 512, 576, 640, 704,
+ 768, 832, 896, 960
+ };
+ unsigned ticks_min, i;
+
+ /*
+ * Since the adc frequency is checked before, there is no reason
+ * to not meet the startup time constraint.
+ */
+
+ ticks_min = startup_time_min * adc_clk_khz / 1000;
+ for (i = 0; i < ARRAY_SIZE(startup_lookup); i++)
+ if (startup_lookup[i] > ticks_min)
+ break;
+
+ return i;
+}
+
+static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
+{
+ struct iio_dev *indio_dev = iio_priv_to_dev(st);
+ unsigned f_per, prescal, startup;
+
+ f_per = clk_get_rate(st->per_clk);
+ prescal = (f_per / (2 * freq)) - 1;
+
+ startup = at91_adc_startup_time(st->soc_info.startup_time,
+ freq / 1000);
+
+ at91_adc_writel(st, AT91_SAMA5D2_MR,
+ AT91_SAMA5D2_MR_TRANSFER(2)
+ | AT91_SAMA5D2_MR_STARTUP(startup)
+ | AT91_SAMA5D2_MR_PRESCAL(prescal));
+
+ dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n",
+ freq, startup, prescal);
+}
+
+static unsigned at91_adc_get_sample_freq(struct at91_adc_state *st)
+{
+ unsigned f_adc, f_per = clk_get_rate(st->per_clk);
+ unsigned mr, prescal;
+
+ mr = at91_adc_readl(st, AT91_SAMA5D2_MR);
+ prescal = (mr >> AT91_SAMA5D2_MR_PRESCAL_OFFSET)
+ & AT91_SAMA5D2_MR_PRESCAL_MAX;
+ f_adc = f_per / (2 * (prescal + 1));
+
+ return f_adc;
+}
+
+static irqreturn_t at91_adc_interrupt(int irq, void *private)
+{
+ struct iio_dev *indio = private;
+ struct at91_adc_state *st = iio_priv(indio);
+ u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
+ u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
+
+ if (status & imr) {
+ st->conversion_value = at91_adc_readl(st, st->chan->address);
+ st->conversion_done = true;
+ wake_up_interruptible(&st->wq_data_available);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int at91_adc_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct at91_adc_state *st = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ mutex_lock(&st->lock);
+
+ st->chan = chan;
+
+ at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
+ at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel));
+ at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
+
+ ret = wait_event_interruptible_timeout(st->wq_data_available,
+ st->conversion_done,
+ msecs_to_jiffies(1000));
+ if (ret == 0)
+ ret = -ETIMEDOUT;
+
+ if (ret > 0) {
+ *val = st->conversion_value;
+ ret = IIO_VAL_INT;
+ st->conversion_done = false;
+ }
+
+ at91_adc_writel(st, AT91_SAMA5D2_IDR, BIT(chan->channel));
+ at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
+
+ mutex_unlock(&st->lock);
+ return ret;
+
+ case IIO_CHAN_INFO_SCALE:
+ *val = st->vref_uv / 1000;
+ *val2 = chan->scan_type.realbits;
+ return IIO_VAL_FRACTIONAL_LOG2;
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = at91_adc_get_sample_freq(st);
+ return IIO_VAL_INT;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int at91_adc_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct at91_adc_state *st = iio_priv(indio_dev);
+
+ if (mask != IIO_CHAN_INFO_SAMP_FREQ)
+ return -EINVAL;
+
+ if (val < st->soc_info.min_sample_rate ||
+ val > st->soc_info.max_sample_rate)
+ return -EINVAL;
+
+ at91_adc_setup_samp_freq(st, val);
+
+ return 0;
+}
+
+static const struct iio_info at91_adc_info = {
+ .read_raw = &at91_adc_read_raw,
+ .write_raw = &at91_adc_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
+static int at91_adc_probe(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev;
+ struct at91_adc_state *st;
+ struct resource *res;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ indio_dev->dev.parent = &pdev->dev;
+ indio_dev->name = dev_name(&pdev->dev);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &at91_adc_info;
+ indio_dev->channels = at91_adc_channels;
+ indio_dev->num_channels = ARRAY_SIZE(at91_adc_channels);
+
+ st = iio_priv(indio_dev);
+
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "atmel,min-sample-rate-hz",
+ &st->soc_info.min_sample_rate);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "invalid or missing value for atmel,min-sample-rate-hz\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "atmel,max-sample-rate-hz",
+ &st->soc_info.max_sample_rate);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "invalid or missing value for atmel,max-sample-rate-hz\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(pdev->dev.of_node, "atmel,startup-time-ms",
+ &st->soc_info.startup_time);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "invalid or missing value for atmel,startup-time-ms\n");
+ return ret;
+ }
+
+ init_waitqueue_head(&st->wq_data_available);
+ mutex_init(&st->lock);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ st->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(st->base))
+ return PTR_ERR(st->base);
+
+ st->irq = platform_get_irq(pdev, 0);
+ if (st->irq <= 0) {
+ if (!st->irq)
+ st->irq = -ENXIO;
+
+ return st->irq;
+ }
+
+ st->per_clk = devm_clk_get(&pdev->dev, "adc_clk");
+ if (IS_ERR(st->per_clk))
+ return PTR_ERR(st->per_clk);
+
+ st->reg = devm_regulator_get(&pdev->dev, "vddana");
+ if (IS_ERR(st->reg))
+ return PTR_ERR(st->reg);
+
+ st->vref = devm_regulator_get(&pdev->dev, "vref");
+ if (IS_ERR(st->vref))
+ return PTR_ERR(st->vref);
+
+ ret = devm_request_irq(&pdev->dev, st->irq, at91_adc_interrupt, 0,
+ pdev->dev.driver->name, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = regulator_enable(st->reg);
+ if (ret)
+ return ret;
+
+ ret = regulator_enable(st->vref);
+ if (ret)
+ goto reg_disable;
+
+ st->vref_uv = regulator_get_voltage(st->vref);
+ if (st->vref_uv <= 0) {
+ ret = -EINVAL;
+ goto vref_disable;
+ }
+
+ at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
+ at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
+
+ at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
+
+ ret = clk_prepare_enable(st->per_clk);
+ if (ret)
+ goto vref_disable;
+
+ ret = iio_device_register(indio_dev);
+ if (ret < 0)
+ goto per_clk_disable_unprepare;
+
+ dev_info(&pdev->dev, "version: %x\n",
+ readl_relaxed(st->base + AT91_SAMA5D2_VERSION));
+
+ return 0;
+
+per_clk_disable_unprepare:
+ clk_disable_unprepare(st->per_clk);
+vref_disable:
+ regulator_disable(st->vref);
+reg_disable:
+ regulator_disable(st->reg);
+ return ret;
+}
+
+static int at91_adc_remove(struct platform_device *pdev)
+{
+ struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+ struct at91_adc_state *st = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+
+ clk_disable_unprepare(st->per_clk);
+
+ regulator_disable(st->vref);
+ regulator_disable(st->reg);
+
+ return 0;
+}
+
+static const struct of_device_id at91_adc_dt_match[] = {
+ {
+ .compatible = "atmel,sama5d2-adc",
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, at91_adc_dt_match);
+
+static struct platform_driver at91_adc_driver = {
+ .probe = at91_adc_probe,
+ .remove = at91_adc_remove,
+ .driver = {
+ .name = "at91-sama5d2_adc",
+ .of_match_table = at91_adc_dt_match,
+ },
+};
+module_platform_driver(at91_adc_driver)
+
+MODULE_AUTHOR("Ludovic Desroches <ludovic.desroches@atmel.com>");
+MODULE_DESCRIPTION("Atmel AT91 SAMA5D2 ADC");
+MODULE_LICENSE("GPL v2");
struct regmap *regmap;
};
-static const struct iio_chan_spec const axp288_adc_channels[] = {
+static const struct iio_chan_spec axp288_adc_channels[] = {
{
.indexed = 1,
.type = IIO_TEMP,
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
-#define MCP320X_VOLTAGE_CHANNEL_DIFF(num) \
+#define MCP320X_VOLTAGE_CHANNEL_DIFF(chan1, chan2) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
- .channel = (num * 2), \
- .channel2 = (num * 2 + 1), \
- .address = (num * 2), \
+ .channel = (chan1), \
+ .channel2 = (chan2), \
+ .address = (chan1), \
.differential = 1, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
static const struct iio_chan_spec mcp3201_channels[] = {
- MCP320X_VOLTAGE_CHANNEL_DIFF(0),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
};
static const struct iio_chan_spec mcp3202_channels[] = {
MCP320X_VOLTAGE_CHANNEL(0),
MCP320X_VOLTAGE_CHANNEL(1),
- MCP320X_VOLTAGE_CHANNEL_DIFF(0),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
};
static const struct iio_chan_spec mcp3204_channels[] = {
MCP320X_VOLTAGE_CHANNEL(1),
MCP320X_VOLTAGE_CHANNEL(2),
MCP320X_VOLTAGE_CHANNEL(3),
- MCP320X_VOLTAGE_CHANNEL_DIFF(0),
- MCP320X_VOLTAGE_CHANNEL_DIFF(1),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2),
};
static const struct iio_chan_spec mcp3208_channels[] = {
MCP320X_VOLTAGE_CHANNEL(5),
MCP320X_VOLTAGE_CHANNEL(6),
MCP320X_VOLTAGE_CHANNEL(7),
- MCP320X_VOLTAGE_CHANNEL_DIFF(0),
- MCP320X_VOLTAGE_CHANNEL_DIFF(1),
- MCP320X_VOLTAGE_CHANNEL_DIFF(2),
- MCP320X_VOLTAGE_CHANNEL_DIFF(3),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(4, 5),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(5, 4),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(6, 7),
+ MCP320X_VOLTAGE_CHANNEL_DIFF(7, 6),
};
static const struct iio_info mcp320x_info = {
/*
- * mcp3422.c - driver for the Microchip mcp3422/3/4/6/7/8 chip family
+ * mcp3422.c - driver for the Microchip mcp3421/2/3/4/5/6/7/8 chip family
*
* Copyright (C) 2013, Angelo Compagnucci
* Author: Angelo Compagnucci <angelo.compagnucci@gmail.com>
*
* Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf
* http://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf
+ * http://ww1.microchip.com/downloads/en/DeviceDoc/22072b.pdf
*
* This driver exports the value of analog input voltage to sysfs, the
* voltage unit is nV.
switch (adc->id) {
case 1:
+ case 5:
indio_dev->channels = mcp3421_channels;
indio_dev->num_channels = ARRAY_SIZE(mcp3421_channels);
break;
{ "mcp3422", 2 },
{ "mcp3423", 3 },
{ "mcp3424", 4 },
+ { "mcp3425", 5 },
{ "mcp3426", 6 },
{ "mcp3427", 7 },
{ "mcp3428", 8 },
module_i2c_driver(mcp3422_driver);
MODULE_AUTHOR("Angelo Compagnucci <angelo.compagnucci@gmail.com>");
-MODULE_DESCRIPTION("Microchip mcp3422/3/4/6/7/8 driver");
+MODULE_DESCRIPTION("Microchip mcp3421/2/3/4/5/6/7/8 driver");
MODULE_LICENSE("GPL v2");
menu "Chemical Sensors"
+config ATLAS_PH_SENSOR
+ tristate "Atlas Scientific OEM pH-SM sensor"
+ depends on I2C
+ select REGMAP_I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say Y here to build I2C interface support for the Atlas
+ Scientific OEM pH-SM sensor.
+
+ To compile this driver as module, choose M here: the
+ module will be called atlas-ph-sensor.
+
config IAQCORE
tristate "AMS iAQ-Core VOC sensors"
depends on I2C
#
# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-ph-sensor.o
obj-$(CONFIG_IAQCORE) += ams-iaq-core.o
obj-$(CONFIG_VZ89X) += vz89x.o
--- /dev/null
+/*
+ * atlas-ph-sensor.c - Support for Atlas Scientific OEM pH-SM sensor
+ *
+ * Copyright (C) 2015 Matt Ranostay <mranostay@gmail.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 <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/irq_work.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/pm_runtime.h>
+
+#define ATLAS_REGMAP_NAME "atlas_ph_regmap"
+#define ATLAS_DRV_NAME "atlas_ph"
+
+#define ATLAS_REG_DEV_TYPE 0x00
+#define ATLAS_REG_DEV_VERSION 0x01
+
+#define ATLAS_REG_INT_CONTROL 0x04
+#define ATLAS_REG_INT_CONTROL_EN BIT(3)
+
+#define ATLAS_REG_PWR_CONTROL 0x06
+
+#define ATLAS_REG_CALIB_STATUS 0x0d
+#define ATLAS_REG_CALIB_STATUS_MASK 0x07
+#define ATLAS_REG_CALIB_STATUS_LOW BIT(0)
+#define ATLAS_REG_CALIB_STATUS_MID BIT(1)
+#define ATLAS_REG_CALIB_STATUS_HIGH BIT(2)
+
+#define ATLAS_REG_TEMP_DATA 0x0e
+#define ATLAS_REG_PH_DATA 0x16
+
+#define ATLAS_PH_INT_TIME_IN_US 450000
+
+struct atlas_data {
+ struct i2c_client *client;
+ struct iio_trigger *trig;
+ struct regmap *regmap;
+ struct irq_work work;
+
+ __be32 buffer[4]; /* 32-bit pH data + 32-bit pad + 64-bit timestamp */
+};
+
+static const struct regmap_range atlas_volatile_ranges[] = {
+ regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL),
+ regmap_reg_range(ATLAS_REG_CALIB_STATUS, ATLAS_REG_CALIB_STATUS),
+ regmap_reg_range(ATLAS_REG_TEMP_DATA, ATLAS_REG_TEMP_DATA + 4),
+ regmap_reg_range(ATLAS_REG_PH_DATA, ATLAS_REG_PH_DATA + 4),
+};
+
+static const struct regmap_access_table atlas_volatile_table = {
+ .yes_ranges = atlas_volatile_ranges,
+ .n_yes_ranges = ARRAY_SIZE(atlas_volatile_ranges),
+};
+
+static const struct regmap_config atlas_regmap_config = {
+ .name = ATLAS_REGMAP_NAME,
+
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .volatile_table = &atlas_volatile_table,
+ .max_register = ATLAS_REG_PH_DATA + 4,
+ .cache_type = REGCACHE_FLAT,
+};
+
+static const struct iio_chan_spec atlas_channels[] = {
+ {
+ .type = IIO_PH,
+ .info_mask_separate =
+ BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_BE,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+ {
+ .type = IIO_TEMP,
+ .address = ATLAS_REG_TEMP_DATA,
+ .info_mask_separate =
+ BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+ .output = 1,
+ .scan_index = -1
+ },
+};
+
+static int atlas_set_powermode(struct atlas_data *data, int on)
+{
+ return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on);
+}
+
+static int atlas_set_interrupt(struct atlas_data *data, bool state)
+{
+ return regmap_update_bits(data->regmap, ATLAS_REG_INT_CONTROL,
+ ATLAS_REG_INT_CONTROL_EN,
+ state ? ATLAS_REG_INT_CONTROL_EN : 0);
+}
+
+static int atlas_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct atlas_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = iio_triggered_buffer_postenable(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = pm_runtime_get_sync(&data->client->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(&data->client->dev);
+ return ret;
+ }
+
+ return atlas_set_interrupt(data, true);
+}
+
+static int atlas_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct atlas_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = iio_triggered_buffer_predisable(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = atlas_set_interrupt(data, false);
+ if (ret)
+ return ret;
+
+ pm_runtime_mark_last_busy(&data->client->dev);
+ return pm_runtime_put_autosuspend(&data->client->dev);
+}
+
+static const struct iio_trigger_ops atlas_interrupt_trigger_ops = {
+ .owner = THIS_MODULE,
+};
+
+static const struct iio_buffer_setup_ops atlas_buffer_setup_ops = {
+ .postenable = atlas_buffer_postenable,
+ .predisable = atlas_buffer_predisable,
+};
+
+static void atlas_work_handler(struct irq_work *work)
+{
+ struct atlas_data *data = container_of(work, struct atlas_data, work);
+
+ iio_trigger_poll(data->trig);
+}
+
+static irqreturn_t atlas_trigger_handler(int irq, void *private)
+{
+ struct iio_poll_func *pf = private;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct atlas_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(data->client, ATLAS_REG_PH_DATA,
+ sizeof(data->buffer[0]), (u8 *) &data->buffer);
+
+ if (ret > 0)
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+ iio_get_time_ns());
+
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t atlas_interrupt_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct atlas_data *data = iio_priv(indio_dev);
+
+ irq_work_queue(&data->work);
+
+ return IRQ_HANDLED;
+}
+
+static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val)
+{
+ struct device *dev = &data->client->dev;
+ int suspended = pm_runtime_suspended(dev);
+ int ret;
+
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ if (suspended)
+ usleep_range(ATLAS_PH_INT_TIME_IN_US,
+ ATLAS_PH_INT_TIME_IN_US + 100000);
+
+ ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA,
+ (u8 *) val, sizeof(*val));
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ return ret;
+}
+
+static int atlas_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct atlas_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW: {
+ int ret;
+ __be32 reg;
+
+ switch (chan->type) {
+ case IIO_TEMP:
+ ret = regmap_bulk_read(data->regmap, chan->address,
+ (u8 *) ®, sizeof(reg));
+ break;
+ case IIO_PH:
+ mutex_lock(&indio_dev->mlock);
+
+ if (iio_buffer_enabled(indio_dev))
+ ret = -EBUSY;
+ else
+ ret = atlas_read_ph_measurement(data, ®);
+
+ mutex_unlock(&indio_dev->mlock);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ if (!ret) {
+ *val = be32_to_cpu(reg);
+ ret = IIO_VAL_INT;
+ }
+ return ret;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = 1; /* 0.01 */
+ *val2 = 100;
+ break;
+ case IIO_PH:
+ *val = 1; /* 0.001 */
+ *val2 = 1000;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return IIO_VAL_FRACTIONAL;
+ }
+
+ return -EINVAL;
+}
+
+static int atlas_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct atlas_data *data = iio_priv(indio_dev);
+ __be32 reg = cpu_to_be32(val);
+
+ if (val2 != 0 || val < 0 || val > 20000)
+ return -EINVAL;
+
+ if (mask != IIO_CHAN_INFO_RAW || chan->type != IIO_TEMP)
+ return -EINVAL;
+
+ return regmap_bulk_write(data->regmap, chan->address,
+ ®, sizeof(reg));
+}
+
+static const struct iio_info atlas_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = atlas_read_raw,
+ .write_raw = atlas_write_raw,
+};
+
+static int atlas_check_calibration(struct atlas_data *data)
+{
+ struct device *dev = &data->client->dev;
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(data->regmap, ATLAS_REG_CALIB_STATUS, &val);
+ if (ret)
+ return ret;
+
+ if (!(val & ATLAS_REG_CALIB_STATUS_MASK)) {
+ dev_warn(dev, "device has not been calibrated\n");
+ return 0;
+ }
+
+ if (!(val & ATLAS_REG_CALIB_STATUS_LOW))
+ dev_warn(dev, "device missing low point calibration\n");
+
+ if (!(val & ATLAS_REG_CALIB_STATUS_MID))
+ dev_warn(dev, "device missing mid point calibration\n");
+
+ if (!(val & ATLAS_REG_CALIB_STATUS_HIGH))
+ dev_warn(dev, "device missing high point calibration\n");
+
+ return 0;
+};
+
+static int atlas_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct atlas_data *data;
+ struct iio_trigger *trig;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ indio_dev->info = &atlas_info;
+ indio_dev->name = ATLAS_DRV_NAME;
+ indio_dev->channels = atlas_channels;
+ indio_dev->num_channels = ARRAY_SIZE(atlas_channels);
+ indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE;
+ indio_dev->dev.parent = &client->dev;
+
+ trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
+ indio_dev->name, indio_dev->id);
+
+ if (!trig)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ data->client = client;
+ data->trig = trig;
+ trig->dev.parent = indio_dev->dev.parent;
+ trig->ops = &atlas_interrupt_trigger_ops;
+ iio_trigger_set_drvdata(trig, indio_dev);
+
+ i2c_set_clientdata(client, indio_dev);
+
+ data->regmap = devm_regmap_init_i2c(client, &atlas_regmap_config);
+ if (IS_ERR(data->regmap)) {
+ dev_err(&client->dev, "regmap initialization failed\n");
+ return PTR_ERR(data->regmap);
+ }
+
+ ret = pm_runtime_set_active(&client->dev);
+ if (ret)
+ return ret;
+
+ if (client->irq <= 0) {
+ dev_err(&client->dev, "no valid irq defined\n");
+ return -EINVAL;
+ }
+
+ ret = atlas_check_calibration(data);
+ if (ret)
+ return ret;
+
+ ret = iio_trigger_register(trig);
+ if (ret) {
+ dev_err(&client->dev, "failed to register trigger\n");
+ return ret;
+ }
+
+ ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+ &atlas_trigger_handler, &atlas_buffer_setup_ops);
+ if (ret) {
+ dev_err(&client->dev, "cannot setup iio trigger\n");
+ goto unregister_trigger;
+ }
+
+ init_irq_work(&data->work, atlas_work_handler);
+
+ /* interrupt pin toggles on new conversion */
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, atlas_interrupt_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "atlas_irq",
+ indio_dev);
+ if (ret) {
+ dev_err(&client->dev, "request irq (%d) failed\n", client->irq);
+ goto unregister_buffer;
+ }
+
+ ret = atlas_set_powermode(data, 1);
+ if (ret) {
+ dev_err(&client->dev, "cannot power device on");
+ goto unregister_buffer;
+ }
+
+ pm_runtime_enable(&client->dev);
+ pm_runtime_set_autosuspend_delay(&client->dev, 2500);
+ pm_runtime_use_autosuspend(&client->dev);
+
+ ret = iio_device_register(indio_dev);
+ if (ret) {
+ dev_err(&client->dev, "unable to register device\n");
+ goto unregister_pm;
+ }
+
+ return 0;
+
+unregister_pm:
+ pm_runtime_disable(&client->dev);
+ atlas_set_powermode(data, 0);
+
+unregister_buffer:
+ iio_triggered_buffer_cleanup(indio_dev);
+
+unregister_trigger:
+ iio_trigger_unregister(data->trig);
+
+ return ret;
+}
+
+static int atlas_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct atlas_data *data = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
+ iio_trigger_unregister(data->trig);
+
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+ pm_runtime_put_noidle(&client->dev);
+
+ return atlas_set_powermode(data, 0);
+}
+
+#ifdef CONFIG_PM
+static int atlas_runtime_suspend(struct device *dev)
+{
+ struct atlas_data *data =
+ iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
+
+ return atlas_set_powermode(data, 0);
+}
+
+static int atlas_runtime_resume(struct device *dev)
+{
+ struct atlas_data *data =
+ iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
+
+ return atlas_set_powermode(data, 1);
+}
+#endif
+
+static const struct dev_pm_ops atlas_pm_ops = {
+ SET_RUNTIME_PM_OPS(atlas_runtime_suspend,
+ atlas_runtime_resume, NULL)
+};
+
+static const struct i2c_device_id atlas_id[] = {
+ { "atlas-ph-sm", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, atlas_id);
+
+static const struct of_device_id atlas_dt_ids[] = {
+ { .compatible = "atlas,ph-sm" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, atlas_dt_ids);
+
+static struct i2c_driver atlas_driver = {
+ .driver = {
+ .name = ATLAS_DRV_NAME,
+ .of_match_table = of_match_ptr(atlas_dt_ids),
+ .pm = &atlas_pm_ops,
+ },
+ .probe = atlas_probe,
+ .remove = atlas_remove,
+ .id_table = atlas_id,
+};
+module_i2c_driver(atlas_driver);
+
+MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>");
+MODULE_DESCRIPTION("Atlas Scientific pH-SM sensor");
+MODULE_LICENSE("GPL");
#include <asm/unaligned.h>
#include <linux/iio/common/st_sensors.h>
+#include "st_sensors_core.h"
+
static inline u32 st_sensors_get_unaligned_le24(const u8 *p)
{
return (s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8;
}
-static int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
- u8 reg_addr, u8 mask, u8 data)
+int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
+ u8 reg_addr, u8 mask, u8 data)
{
int err;
u8 new_data;
--- /dev/null
+/*
+ * Local functions in the ST Sensors core
+ */
+#ifndef __ST_SENSORS_CORE_H
+#define __ST_SENSORS_CORE_H
+int st_sensors_write_data_with_mask(struct iio_dev *indio_dev,
+ u8 reg_addr, u8 mask, u8 data);
+#endif
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include <linux/interrupt.h>
-
#include <linux/iio/common/st_sensors.h>
-
+#include "st_sensors_core.h"
int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
const struct iio_trigger_ops *trigger_ops)
{
- int err;
+ int err, irq;
struct st_sensor_data *sdata = iio_priv(indio_dev);
+ unsigned long irq_trig;
sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name);
if (sdata->trig == NULL) {
- err = -ENOMEM;
dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n");
- goto iio_trigger_alloc_error;
+ return -ENOMEM;
}
- err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev),
+ irq = sdata->get_irq_data_ready(indio_dev);
+ irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
+ /*
+ * If the IRQ is triggered on falling edge, we need to mark the
+ * interrupt as active low, if the hardware supports this.
+ */
+ if (irq_trig == IRQF_TRIGGER_FALLING) {
+ if (!sdata->sensor_settings->drdy_irq.addr_ihl) {
+ dev_err(&indio_dev->dev,
+ "falling edge specified for IRQ but hardware "
+ "only support rising edge, will request "
+ "rising edge\n");
+ irq_trig = IRQF_TRIGGER_RISING;
+ } else {
+ /* Set up INT active low i.e. falling edge */
+ err = st_sensors_write_data_with_mask(indio_dev,
+ sdata->sensor_settings->drdy_irq.addr_ihl,
+ sdata->sensor_settings->drdy_irq.mask_ihl, 1);
+ if (err < 0)
+ goto iio_trigger_free;
+ dev_info(&indio_dev->dev,
+ "interrupts on the falling edge\n");
+ }
+ } else if (irq_trig == IRQF_TRIGGER_RISING) {
+ dev_info(&indio_dev->dev,
+ "interrupts on the rising edge\n");
+
+ } else {
+ dev_err(&indio_dev->dev,
+ "unsupported IRQ trigger specified (%lx), only "
+ "rising and falling edges supported, enforce "
+ "rising edge\n", irq_trig);
+ irq_trig = IRQF_TRIGGER_RISING;
+ }
+ err = request_threaded_irq(irq,
iio_trigger_generic_data_rdy_poll,
NULL,
- IRQF_TRIGGER_RISING,
+ irq_trig,
sdata->trig->name,
sdata->trig);
if (err) {
dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n");
- goto request_irq_error;
+ goto iio_trigger_free;
}
iio_trigger_set_drvdata(sdata->trig, indio_dev);
iio_trigger_register_error:
free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig);
-request_irq_error:
+iio_trigger_free:
iio_trigger_free(sdata->trig);
-iio_trigger_alloc_error:
return err;
}
EXPORT_SYMBOL(st_sensors_allocate_trigger);
To compile this driver as a module, choose M here: the
module will be called ad5755.
+config AD5761
+ tristate "Analog Devices AD5761/61R/21/21R DAC driver"
+ depends on SPI_MASTER
+ help
+ Say yes here to build support for Analog Devices AD5761, AD5761R, AD5721,
+ AD5721R Digital to Analog Converter.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad5761.
+
config AD5764
tristate "Analog Devices AD5764/64R/44/44R DAC driver"
depends on SPI_MASTER
10 bits DAC.
config MCP4725
- tristate "MCP4725 DAC driver"
+ tristate "MCP4725/6 DAC driver"
depends on I2C
---help---
Say Y here if you want to build a driver for the Microchip
- MCP 4725 12-bit digital-to-analog converter (DAC) with I2C
+ MCP 4725/6 12-bit digital-to-analog converter (DAC) with I2C
interface.
To compile this driver as a module, choose M here: the module
obj-$(CONFIG_AD5446) += ad5446.o
obj-$(CONFIG_AD5449) += ad5449.o
obj-$(CONFIG_AD5755) += ad5755.o
+obj-$(CONFIG_AD5761) += ad5761.o
obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
--- /dev/null
+/*
+ * AD5721, AD5721R, AD5761, AD5761R, Voltage Output Digital to Analog Converter
+ *
+ * Copyright 2016 Qtechnology A/S
+ * 2016 Ricardo Ribalda <ricardo.ribalda@gmail.com>
+ *
+ * Licensed under the GPL-2.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/bitops.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/regulator/consumer.h>
+#include <linux/platform_data/ad5761.h>
+
+#define AD5761_ADDR(addr) ((addr & 0xf) << 16)
+#define AD5761_ADDR_NOOP 0x0
+#define AD5761_ADDR_DAC_WRITE 0x3
+#define AD5761_ADDR_CTRL_WRITE_REG 0x4
+#define AD5761_ADDR_SW_DATA_RESET 0x7
+#define AD5761_ADDR_DAC_READ 0xb
+#define AD5761_ADDR_CTRL_READ_REG 0xc
+#define AD5761_ADDR_SW_FULL_RESET 0xf
+
+#define AD5761_CTRL_USE_INTVREF BIT(5)
+#define AD5761_CTRL_ETS BIT(6)
+
+/**
+ * struct ad5761_chip_info - chip specific information
+ * @int_vref: Value of the internal reference voltage in mV - 0 if external
+ * reference voltage is used
+ * @channel: channel specification
+*/
+
+struct ad5761_chip_info {
+ unsigned long int_vref;
+ const struct iio_chan_spec channel;
+};
+
+struct ad5761_range_params {
+ int m;
+ int c;
+};
+
+enum ad5761_supported_device_ids {
+ ID_AD5721,
+ ID_AD5721R,
+ ID_AD5761,
+ ID_AD5761R,
+};
+
+/**
+ * struct ad5761_state - driver instance specific data
+ * @spi: spi_device
+ * @vref_reg: reference voltage regulator
+ * @use_intref: true when the internal voltage reference is used
+ * @vref: actual voltage reference in mVolts
+ * @range: output range mode used
+ * @data: cache aligned spi buffer
+ */
+struct ad5761_state {
+ struct spi_device *spi;
+ struct regulator *vref_reg;
+
+ bool use_intref;
+ int vref;
+ enum ad5761_voltage_range range;
+
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ union {
+ __be32 d32;
+ u8 d8[4];
+ } data[3] ____cacheline_aligned;
+};
+
+static const struct ad5761_range_params ad5761_range_params[] = {
+ [AD5761_VOLTAGE_RANGE_M10V_10V] = {
+ .m = 80,
+ .c = 40,
+ },
+ [AD5761_VOLTAGE_RANGE_0V_10V] = {
+ .m = 40,
+ .c = 0,
+ },
+ [AD5761_VOLTAGE_RANGE_M5V_5V] = {
+ .m = 40,
+ .c = 20,
+ },
+ [AD5761_VOLTAGE_RANGE_0V_5V] = {
+ .m = 20,
+ .c = 0,
+ },
+ [AD5761_VOLTAGE_RANGE_M2V5_7V5] = {
+ .m = 40,
+ .c = 10,
+ },
+ [AD5761_VOLTAGE_RANGE_M3V_3V] = {
+ .m = 24,
+ .c = 12,
+ },
+ [AD5761_VOLTAGE_RANGE_0V_16V] = {
+ .m = 64,
+ .c = 0,
+ },
+ [AD5761_VOLTAGE_RANGE_0V_20V] = {
+ .m = 80,
+ .c = 0,
+ },
+};
+
+static int _ad5761_spi_write(struct ad5761_state *st, u8 addr, u16 val)
+{
+ st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr) | val);
+
+ return spi_write(st->spi, &st->data[0].d8[1], 3);
+}
+
+static int ad5761_spi_write(struct iio_dev *indio_dev, u8 addr, u16 val)
+{
+ struct ad5761_state *st = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&indio_dev->mlock);
+ ret = _ad5761_spi_write(st, addr, val);
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
+static int _ad5761_spi_read(struct ad5761_state *st, u8 addr, u16 *val)
+{
+ int ret;
+ struct spi_transfer xfers[] = {
+ {
+ .tx_buf = &st->data[0].d8[1],
+ .bits_per_word = 8,
+ .len = 3,
+ .cs_change = true,
+ }, {
+ .tx_buf = &st->data[1].d8[1],
+ .rx_buf = &st->data[2].d8[1],
+ .bits_per_word = 8,
+ .len = 3,
+ },
+ };
+
+ st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr));
+ st->data[1].d32 = cpu_to_be32(AD5761_ADDR(AD5761_ADDR_NOOP));
+
+ ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
+
+ *val = be32_to_cpu(st->data[2].d32);
+
+ return ret;
+}
+
+static int ad5761_spi_read(struct iio_dev *indio_dev, u8 addr, u16 *val)
+{
+ struct ad5761_state *st = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&indio_dev->mlock);
+ ret = _ad5761_spi_read(st, addr, val);
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
+static int ad5761_spi_set_range(struct ad5761_state *st,
+ enum ad5761_voltage_range range)
+{
+ u16 aux;
+ int ret;
+
+ aux = (range & 0x7) | AD5761_CTRL_ETS;
+
+ if (st->use_intref)
+ aux |= AD5761_CTRL_USE_INTVREF;
+
+ ret = _ad5761_spi_write(st, AD5761_ADDR_SW_FULL_RESET, 0);
+ if (ret)
+ return ret;
+
+ ret = _ad5761_spi_write(st, AD5761_ADDR_CTRL_WRITE_REG, aux);
+ if (ret)
+ return ret;
+
+ st->range = range;
+
+ return 0;
+}
+
+static int ad5761_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask)
+{
+ struct ad5761_state *st;
+ int ret;
+ u16 aux;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = ad5761_spi_read(indio_dev, AD5761_ADDR_DAC_READ, &aux);
+ if (ret)
+ return ret;
+ *val = aux >> chan->scan_type.shift;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ st = iio_priv(indio_dev);
+ *val = st->vref * ad5761_range_params[st->range].m;
+ *val /= 10;
+ *val2 = chan->scan_type.realbits;
+ return IIO_VAL_FRACTIONAL_LOG2;
+ case IIO_CHAN_INFO_OFFSET:
+ st = iio_priv(indio_dev);
+ *val = -(1 << chan->scan_type.realbits);
+ *val *= ad5761_range_params[st->range].c;
+ *val /= ad5761_range_params[st->range].m;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad5761_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask)
+{
+ u16 aux;
+
+ if (mask != IIO_CHAN_INFO_RAW)
+ return -EINVAL;
+
+ if (val2 || (val << chan->scan_type.shift) > 0xffff || val < 0)
+ return -EINVAL;
+
+ aux = val << chan->scan_type.shift;
+
+ return ad5761_spi_write(indio_dev, AD5761_ADDR_DAC_WRITE, aux);
+}
+
+static const struct iio_info ad5761_info = {
+ .read_raw = &ad5761_read_raw,
+ .write_raw = &ad5761_write_raw,
+ .driver_module = THIS_MODULE,
+};
+
+#define AD5761_CHAN(_bits) { \
+ .type = IIO_VOLTAGE, \
+ .output = 1, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = (_bits), \
+ .storagebits = 16, \
+ .shift = 16 - (_bits), \
+ }, \
+}
+
+static const struct ad5761_chip_info ad5761_chip_infos[] = {
+ [ID_AD5721] = {
+ .int_vref = 0,
+ .channel = AD5761_CHAN(12),
+ },
+ [ID_AD5721R] = {
+ .int_vref = 2500,
+ .channel = AD5761_CHAN(12),
+ },
+ [ID_AD5761] = {
+ .int_vref = 0,
+ .channel = AD5761_CHAN(16),
+ },
+ [ID_AD5761R] = {
+ .int_vref = 2500,
+ .channel = AD5761_CHAN(16),
+ },
+};
+
+static int ad5761_get_vref(struct ad5761_state *st,
+ const struct ad5761_chip_info *chip_info)
+{
+ int ret;
+
+ st->vref_reg = devm_regulator_get_optional(&st->spi->dev, "vref");
+ if (PTR_ERR(st->vref_reg) == -ENODEV) {
+ /* Use Internal regulator */
+ if (!chip_info->int_vref) {
+ dev_err(&st->spi->dev,
+ "Voltage reference not found\n");
+ return -EIO;
+ }
+
+ st->use_intref = true;
+ st->vref = chip_info->int_vref;
+ return 0;
+ }
+
+ if (IS_ERR(st->vref_reg)) {
+ dev_err(&st->spi->dev,
+ "Error getting voltage reference regulator\n");
+ return PTR_ERR(st->vref_reg);
+ }
+
+ ret = regulator_enable(st->vref_reg);
+ if (ret) {
+ dev_err(&st->spi->dev,
+ "Failed to enable voltage reference\n");
+ return ret;
+ }
+
+ ret = regulator_get_voltage(st->vref_reg);
+ if (ret < 0) {
+ dev_err(&st->spi->dev,
+ "Failed to get voltage reference value\n");
+ goto disable_regulator_vref;
+ }
+
+ if (ret < 2000000 || ret > 3000000) {
+ dev_warn(&st->spi->dev,
+ "Invalid external voltage ref. value %d uV\n", ret);
+ ret = -EIO;
+ goto disable_regulator_vref;
+ }
+
+ st->vref = ret / 1000;
+ st->use_intref = false;
+
+ return 0;
+
+disable_regulator_vref:
+ regulator_disable(st->vref_reg);
+ st->vref_reg = NULL;
+ return ret;
+}
+
+static int ad5761_probe(struct spi_device *spi)
+{
+ struct iio_dev *iio_dev;
+ struct ad5761_state *st;
+ int ret;
+ const struct ad5761_chip_info *chip_info =
+ &ad5761_chip_infos[spi_get_device_id(spi)->driver_data];
+ enum ad5761_voltage_range voltage_range = AD5761_VOLTAGE_RANGE_0V_5V;
+ struct ad5761_platform_data *pdata = dev_get_platdata(&spi->dev);
+
+ iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ if (!iio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(iio_dev);
+
+ st->spi = spi;
+ spi_set_drvdata(spi, iio_dev);
+
+ ret = ad5761_get_vref(st, chip_info);
+ if (ret)
+ return ret;
+
+ if (pdata)
+ voltage_range = pdata->voltage_range;
+
+ ret = ad5761_spi_set_range(st, voltage_range);
+ if (ret)
+ goto disable_regulator_err;
+
+ iio_dev->dev.parent = &spi->dev;
+ iio_dev->info = &ad5761_info;
+ iio_dev->modes = INDIO_DIRECT_MODE;
+ iio_dev->channels = &chip_info->channel;
+ iio_dev->num_channels = 1;
+ iio_dev->name = spi_get_device_id(st->spi)->name;
+ ret = iio_device_register(iio_dev);
+ if (ret)
+ goto disable_regulator_err;
+
+ return 0;
+
+disable_regulator_err:
+ if (!IS_ERR_OR_NULL(st->vref_reg))
+ regulator_disable(st->vref_reg);
+
+ return ret;
+}
+
+static int ad5761_remove(struct spi_device *spi)
+{
+ struct iio_dev *iio_dev = spi_get_drvdata(spi);
+ struct ad5761_state *st = iio_priv(iio_dev);
+
+ iio_device_unregister(iio_dev);
+
+ if (!IS_ERR_OR_NULL(st->vref_reg))
+ regulator_disable(st->vref_reg);
+
+ return 0;
+}
+
+static const struct spi_device_id ad5761_id[] = {
+ {"ad5721", ID_AD5721},
+ {"ad5721r", ID_AD5721R},
+ {"ad5761", ID_AD5761},
+ {"ad5761r", ID_AD5761R},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, ad5761_id);
+
+static struct spi_driver ad5761_driver = {
+ .driver = {
+ .name = "ad5761",
+ },
+ .probe = ad5761_probe,
+ .remove = ad5761_remove,
+ .id_table = ad5761_id,
+};
+module_spi_driver(ad5761_driver);
+
+MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
+MODULE_DESCRIPTION("Analog Devices AD5721, AD5721R, AD5761, AD5761R driver");
+MODULE_LICENSE("GPL v2");
/*
- * mcp4725.c - Support for Microchip MCP4725
+ * mcp4725.c - Support for Microchip MCP4725/6
*
* Copyright (C) 2012 Peter Meerwald <pmeerw@pmeerw.net>
*
"500kohm_to_gnd"
};
+static const char * const mcp4726_powerdown_modes[] = {
+ "1kohm_to_gnd",
+ "125kohm_to_gnd",
+ "640kohm_to_gnd"
+};
+
static int mcp4725_get_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
return len;
}
-static const struct iio_enum mcp4725_powerdown_mode_enum = {
- .items = mcp4725_powerdown_modes,
- .num_items = ARRAY_SIZE(mcp4725_powerdown_modes),
- .get = mcp4725_get_powerdown_mode,
- .set = mcp4725_set_powerdown_mode,
+enum {
+ MCP4725,
+ MCP4726,
+};
+
+static const struct iio_enum mcp472x_powerdown_mode_enum[] = {
+ [MCP4725] = {
+ .items = mcp4725_powerdown_modes,
+ .num_items = ARRAY_SIZE(mcp4725_powerdown_modes),
+ .get = mcp4725_get_powerdown_mode,
+ .set = mcp4725_set_powerdown_mode,
+ },
+ [MCP4726] = {
+ .items = mcp4726_powerdown_modes,
+ .num_items = ARRAY_SIZE(mcp4726_powerdown_modes),
+ .get = mcp4725_get_powerdown_mode,
+ .set = mcp4725_set_powerdown_mode,
+ },
};
static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = {
.write = mcp4725_write_powerdown,
.shared = IIO_SEPARATE,
},
- IIO_ENUM("powerdown_mode", IIO_SEPARATE, &mcp4725_powerdown_mode_enum),
- IIO_ENUM_AVAILABLE("powerdown_mode", &mcp4725_powerdown_mode_enum),
+ IIO_ENUM("powerdown_mode", IIO_SEPARATE,
+ &mcp472x_powerdown_mode_enum[MCP4725]),
+ IIO_ENUM_AVAILABLE("powerdown_mode",
+ &mcp472x_powerdown_mode_enum[MCP4725]),
+ { },
+};
+
+static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = {
+ {
+ .name = "powerdown",
+ .read = mcp4725_read_powerdown,
+ .write = mcp4725_write_powerdown,
+ .shared = IIO_SEPARATE,
+ },
+ IIO_ENUM("powerdown_mode", IIO_SEPARATE,
+ &mcp472x_powerdown_mode_enum[MCP4726]),
+ IIO_ENUM_AVAILABLE("powerdown_mode",
+ &mcp472x_powerdown_mode_enum[MCP4726]),
{ },
};
-static const struct iio_chan_spec mcp4725_channel = {
- .type = IIO_VOLTAGE,
- .indexed = 1,
- .output = 1,
- .channel = 0,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
- .ext_info = mcp4725_ext_info,
+static const struct iio_chan_spec mcp472x_channel[] = {
+ [MCP4725] = {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .output = 1,
+ .channel = 0,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+ .ext_info = mcp4725_ext_info,
+ },
+ [MCP4726] = {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .output = 1,
+ .channel = 0,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+ .ext_info = mcp4726_ext_info,
+ },
};
static int mcp4725_set_value(struct iio_dev *indio_dev, int val)
indio_dev->dev.parent = &client->dev;
indio_dev->name = id->name;
indio_dev->info = &mcp4725_info;
- indio_dev->channels = &mcp4725_channel;
+ indio_dev->channels = &mcp472x_channel[id->driver_data];
indio_dev->num_channels = 1;
indio_dev->modes = INDIO_DIRECT_MODE;
}
pd = (inbuf[0] >> 1) & 0x3;
data->powerdown = pd > 0 ? true : false;
- data->powerdown_mode = pd ? pd-1 : 2; /* 500kohm_to_gnd */
+ data->powerdown_mode = pd ? pd - 1 : 2; /* largest register to gnd */
data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
return iio_device_register(indio_dev);
}
static const struct i2c_device_id mcp4725_id[] = {
- { "mcp4725", 0 },
+ { "mcp4725", MCP4725 },
+ { "mcp4726", MCP4726 },
{ }
};
MODULE_DEVICE_TABLE(i2c, mcp4725_id);
module_i2c_driver(mcp4725_driver);
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
-MODULE_DESCRIPTION("MCP4725 12-bit DAC");
+MODULE_DESCRIPTION("MCP4725/6 12-bit DAC");
MODULE_LICENSE("GPL");
.drdy_irq = {
.addr = ST_GYRO_1_DRDY_IRQ_ADDR,
.mask_int2 = ST_GYRO_1_DRDY_IRQ_INT2_MASK,
+ /*
+ * The sensor has IHL (active low) and open
+ * drain settings, but only for INT1 and not
+ * for the DRDY line on INT2.
+ */
},
.multi_read_bit = ST_GYRO_1_MULTIREAD_BIT,
.bootime = 2,
.drdy_irq = {
.addr = ST_GYRO_2_DRDY_IRQ_ADDR,
.mask_int2 = ST_GYRO_2_DRDY_IRQ_INT2_MASK,
+ /*
+ * The sensor has IHL (active low) and open
+ * drain settings, but only for INT1 and not
+ * for the DRDY line on INT2.
+ */
},
.multi_read_bit = ST_GYRO_2_MULTIREAD_BIT,
.bootime = 2,
.drdy_irq = {
.addr = ST_GYRO_3_DRDY_IRQ_ADDR,
.mask_int2 = ST_GYRO_3_DRDY_IRQ_INT2_MASK,
+ /*
+ * The sensor has IHL (active low) and open
+ * drain settings, but only for INT1 and not
+ * for the DRDY line on INT2.
+ */
},
.multi_read_bit = ST_GYRO_3_MULTIREAD_BIT,
.bootime = 2,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * TODO: allow LED current and pulse length controls via device tree properties
+ * TODO: enable pulse length controls via device tree properties
*/
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
+#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#define MAX30100_REG_SPO2_CONFIG_1600US 0x3
#define MAX30100_REG_LED_CONFIG 0x09
+#define MAX30100_REG_LED_CONFIG_LED_MASK 0x0f
#define MAX30100_REG_LED_CONFIG_RED_LED_SHIFT 4
#define MAX30100_REG_LED_CONFIG_24MA 0x07
.volatile_reg = max30100_is_volatile_reg,
};
+static const unsigned int max30100_led_current_mapping[] = {
+ 4400, 7600, 11000, 14200, 17400,
+ 20800, 24000, 27100, 30600, 33800,
+ 37000, 40200, 43600, 46800, 50000
+};
+
static const unsigned long max30100_scan_masks[] = {0x3, 0};
static const struct iio_chan_spec max30100_channels[] = {
return IRQ_HANDLED;
}
+static int max30100_get_current_idx(unsigned int val, int *reg)
+{
+ int idx;
+
+ /* LED turned off */
+ if (val == 0) {
+ *reg = 0;
+ return 0;
+ }
+
+ for (idx = 0; idx < ARRAY_SIZE(max30100_led_current_mapping); idx++) {
+ if (max30100_led_current_mapping[idx] == val) {
+ *reg = idx + 1;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int max30100_led_init(struct max30100_data *data)
+{
+ struct device *dev = &data->client->dev;
+ struct device_node *np = dev->of_node;
+ unsigned int val[2];
+ int reg, ret;
+
+ ret = of_property_read_u32_array(np, "maxim,led-current-microamp",
+ (unsigned int *) &val, 2);
+ if (ret) {
+ /* Default to 24 mA RED LED, 50 mA IR LED */
+ reg = (MAX30100_REG_LED_CONFIG_24MA <<
+ MAX30100_REG_LED_CONFIG_RED_LED_SHIFT) |
+ MAX30100_REG_LED_CONFIG_50MA;
+ dev_warn(dev, "no led-current-microamp set");
+
+ return regmap_write(data->regmap, MAX30100_REG_LED_CONFIG, reg);
+ }
+
+ /* RED LED current */
+ ret = max30100_get_current_idx(val[0], ®);
+ if (ret) {
+ dev_err(dev, "invalid RED current setting %d", val[0]);
+ return ret;
+ }
+
+ ret = regmap_update_bits(data->regmap, MAX30100_REG_LED_CONFIG,
+ MAX30100_REG_LED_CONFIG_LED_MASK <<
+ MAX30100_REG_LED_CONFIG_RED_LED_SHIFT,
+ reg << MAX30100_REG_LED_CONFIG_RED_LED_SHIFT);
+ if (ret)
+ return ret;
+
+ /* IR LED current */
+ ret = max30100_get_current_idx(val[1], ®);
+ if (ret) {
+ dev_err(dev, "invalid IR current setting %d", val[1]);
+ return ret;
+ }
+
+ return regmap_update_bits(data->regmap, MAX30100_REG_LED_CONFIG,
+ MAX30100_REG_LED_CONFIG_LED_MASK, reg);
+}
+
static int max30100_chip_init(struct max30100_data *data)
{
int ret;
- /* RED IR LED = 24mA, IR LED = 50mA */
- ret = regmap_write(data->regmap, MAX30100_REG_LED_CONFIG,
- (MAX30100_REG_LED_CONFIG_24MA <<
- MAX30100_REG_LED_CONFIG_RED_LED_SHIFT) |
- MAX30100_REG_LED_CONFIG_50MA);
+ /* setup LED current settings */
+ ret = max30100_led_init(data);
if (ret)
return ret;
humidity and temperature sensor.
To compile this driver as a module, choose M here: the module
- will be called si7005.
+ will be called si7005. This driver also
+ supports Hoperf TH02 Humidity and Temperature Sensor.
config SI7020
tristate "Si7013/20/21 Relative Humidity and Temperature Sensors"
depends on I2C
help
Say yes here to build support for the Silicon Labs Si7013/20/21
- Relative Humidity and Temperature Sensors.
+ Relative Humidity and Temperature Sensors. This driver also
+ supports Hoperf TH06 Humidity and Temperature Sensor.
To compile this driver as a module, choose M here: the module
will be called si7020.
#define DHT11_EDGES_PER_READ (2 * DHT11_BITS_PER_READ + \
DHT11_EDGES_PREAMBLE + 1)
-/* Data transmission timing (nano seconds) */
+/*
+ * Data transmission timing:
+ * Data bits are encoded as pulse length (high time) on the data line.
+ * 0-bit: 22-30uS -- typically 26uS (AM2302)
+ * 1-bit: 68-75uS -- typically 70uS (AM2302)
+ * The acutal timings also depend on the properties of the cable, with
+ * longer cables typically making pulses shorter.
+ *
+ * Our decoding depends on the time resolution of the system:
+ * timeres > 34uS ... don't know what a 1-tick pulse is
+ * 34uS > timeres > 30uS ... no problem (30kHz and 32kHz clocks)
+ * 30uS > timeres > 23uS ... don't know what a 2-tick pulse is
+ * timeres < 23uS ... no problem
+ *
+ * Luckily clocks in the 33-44kHz range are quite uncommon, so we can
+ * support most systems if the threshold for decoding a pulse as 1-bit
+ * is chosen carefully. If somebody really wants to support clocks around
+ * 40kHz, where this driver is most unreliable, there are two options.
+ * a) select an implementation using busy loop polling on those systems
+ * b) use the checksum to do some probabilistic decoding
+ */
#define DHT11_START_TRANSMISSION 18 /* ms */
-#define DHT11_SENSOR_RESPONSE 80000
-#define DHT11_START_BIT 50000
-#define DHT11_DATA_BIT_LOW 27000
-#define DHT11_DATA_BIT_HIGH 70000
+#define DHT11_MIN_TIMERES 34000 /* ns */
+#define DHT11_THRESHOLD 49000 /* ns */
+#define DHT11_AMBIG_LOW 23000 /* ns */
+#define DHT11_AMBIG_HIGH 30000 /* ns */
struct dht11 {
struct device *dev;
struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ];
};
-static unsigned char dht11_decode_byte(int *timing, int threshold)
+static unsigned char dht11_decode_byte(char *bits)
{
unsigned char ret = 0;
int i;
for (i = 0; i < 8; ++i) {
ret <<= 1;
- if (timing[i] >= threshold)
+ if (bits[i])
++ret;
}
return ret;
}
-static int dht11_decode(struct dht11 *dht11, int offset, int timeres)
+static int dht11_decode(struct dht11 *dht11, int offset)
{
- int i, t, timing[DHT11_BITS_PER_READ], threshold;
+ int i, t;
+ char bits[DHT11_BITS_PER_READ];
unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
- threshold = DHT11_DATA_BIT_HIGH / timeres;
- if (DHT11_DATA_BIT_LOW / timeres + 1 >= threshold)
- pr_err("dht11: WARNING: decoding ambiguous\n");
-
- /* scale down with timeres and check validity */
for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
t = dht11->edges[offset + 2 * i + 2].ts -
dht11->edges[offset + 2 * i + 1].ts;
if (!dht11->edges[offset + 2 * i + 1].value)
return -EIO; /* lost synchronisation */
- timing[i] = t / timeres;
+ bits[i] = t > DHT11_THRESHOLD;
}
- hum_int = dht11_decode_byte(timing, threshold);
- hum_dec = dht11_decode_byte(&timing[8], threshold);
- temp_int = dht11_decode_byte(&timing[16], threshold);
- temp_dec = dht11_decode_byte(&timing[24], threshold);
- checksum = dht11_decode_byte(&timing[32], threshold);
+ hum_int = dht11_decode_byte(bits);
+ hum_dec = dht11_decode_byte(&bits[8]);
+ temp_int = dht11_decode_byte(&bits[16]);
+ temp_dec = dht11_decode_byte(&bits[24]);
+ checksum = dht11_decode_byte(&bits[32]);
if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum)
return -EIO;
int *val, int *val2, long m)
{
struct dht11 *dht11 = iio_priv(iio_dev);
- int ret, timeres;
+ int ret, timeres, offset;
mutex_lock(&dht11->lock);
if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_boot_ns()) {
timeres = ktime_get_resolution_ns();
- if (DHT11_DATA_BIT_HIGH < 2 * timeres) {
+ if (timeres > DHT11_MIN_TIMERES) {
dev_err(dht11->dev, "timeresolution %dns too low\n",
timeres);
/* In theory a better clock could become available
ret = -EAGAIN;
goto err;
}
+ if (timeres > DHT11_AMBIG_LOW && timeres < DHT11_AMBIG_HIGH)
+ dev_warn(dht11->dev,
+ "timeresolution: %dns - decoding ambiguous\n",
+ timeres);
reinit_completion(&dht11->completion);
if (ret < 0)
goto err;
- ret = dht11_decode(dht11,
- dht11->num_edges == DHT11_EDGES_PER_READ ?
- DHT11_EDGES_PREAMBLE :
- DHT11_EDGES_PREAMBLE - 2,
- timeres);
+ offset = DHT11_EDGES_PREAMBLE +
+ dht11->num_edges - DHT11_EDGES_PER_READ;
+ for (; offset >= 0; --offset) {
+ ret = dht11_decode(dht11, offset);
+ if (!ret)
+ break;
+ }
+
if (ret)
goto err;
}
static const struct i2c_device_id si7005_id[] = {
{ "si7005", 0 },
+ { "th02", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, si7005_id);
static const struct i2c_device_id si7020_id[] = {
{ "si7020", 0 },
+ { "th06", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, si7020_id);
/**
* inv_check_and_setup_chip() - check and setup chip.
*/
-static int inv_check_and_setup_chip(struct inv_mpu6050_state *st,
- const struct i2c_device_id *id)
+static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
{
int result;
if (pdata)
st->plat_data = *pdata;
/* power is turned on inside check chip type*/
- result = inv_check_and_setup_chip(st, id);
+ result = inv_check_and_setup_chip(st);
if (result)
return result;
[IIO_VELOCITY] = "velocity",
[IIO_CONCENTRATION] = "concentration",
[IIO_RESISTANCE] = "resistance",
+ [IIO_PH] = "ph",
};
static const char * const iio_modifier_names[] = {
#define OPT3001_REG_EXPONENT(n) ((n) >> 12)
#define OPT3001_REG_MANTISSA(n) ((n) & 0xfff)
+#define OPT3001_INT_TIME_LONG 800000
+#define OPT3001_INT_TIME_SHORT 100000
+
/*
* Time to wait for conversion result to be ready. The device datasheet
- * worst-case max value is 880ms. Add some slack to be on the safe side.
+ * sect. 6.5 states results are ready after total integration time plus 3ms.
+ * This results in worst-case max values of 113ms or 883ms, respectively.
+ * Add some slack to be on the safe side.
*/
-#define OPT3001_RESULT_READY_TIMEOUT msecs_to_jiffies(1000)
+#define OPT3001_RESULT_READY_SHORT 150
+#define OPT3001_RESULT_READY_LONG 1000
struct opt3001 {
struct i2c_client *client;
struct device *dev;
struct mutex lock;
- u16 ok_to_ignore_lock:1;
- u16 result_ready:1;
+ bool ok_to_ignore_lock;
+ bool result_ready;
wait_queue_head_t result_ready_queue;
u16 result;
u8 high_thresh_exp;
u8 low_thresh_exp;
+
+ bool use_irq;
};
struct opt3001_scale {
u16 reg;
u8 exponent;
u16 value;
+ long timeout;
- /*
- * Enable the end-of-conversion interrupt mechanism. Note that doing
- * so will overwrite the low-level limit value however we will restore
- * this value later on.
- */
- ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT,
- OPT3001_LOW_LIMIT_EOC_ENABLE);
- if (ret < 0) {
- dev_err(opt->dev, "failed to write register %02x\n",
- OPT3001_LOW_LIMIT);
- return ret;
+ if (opt->use_irq) {
+ /*
+ * Enable the end-of-conversion interrupt mechanism. Note that
+ * doing so will overwrite the low-level limit value however we
+ * will restore this value later on.
+ */
+ ret = i2c_smbus_write_word_swapped(opt->client,
+ OPT3001_LOW_LIMIT,
+ OPT3001_LOW_LIMIT_EOC_ENABLE);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to write register %02x\n",
+ OPT3001_LOW_LIMIT);
+ return ret;
+ }
+
+ /* Allow IRQ to access the device despite lock being set */
+ opt->ok_to_ignore_lock = true;
}
- /* Reset data-ready indicator flag (will be set in the IRQ routine) */
+ /* Reset data-ready indicator flag */
opt->result_ready = false;
- /* Allow IRQ to access the device despite lock being set */
- opt->ok_to_ignore_lock = true;
-
/* Configure for single-conversion mode and start a new conversion */
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
if (ret < 0) {
goto err;
}
- /* Wait for the IRQ to indicate the conversion is complete */
- ret = wait_event_timeout(opt->result_ready_queue, opt->result_ready,
- OPT3001_RESULT_READY_TIMEOUT);
+ if (opt->use_irq) {
+ /* Wait for the IRQ to indicate the conversion is complete */
+ ret = wait_event_timeout(opt->result_ready_queue,
+ opt->result_ready,
+ msecs_to_jiffies(OPT3001_RESULT_READY_LONG));
+ } else {
+ /* Sleep for result ready time */
+ timeout = (opt->int_time == OPT3001_INT_TIME_SHORT) ?
+ OPT3001_RESULT_READY_SHORT : OPT3001_RESULT_READY_LONG;
+ msleep(timeout);
+
+ /* Check result ready flag */
+ ret = i2c_smbus_read_word_swapped(opt->client,
+ OPT3001_CONFIGURATION);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to read register %02x\n",
+ OPT3001_CONFIGURATION);
+ goto err;
+ }
+
+ if (!(ret & OPT3001_CONFIGURATION_CRF)) {
+ ret = -ETIMEDOUT;
+ goto err;
+ }
+
+ /* Obtain value */
+ ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to read register %02x\n",
+ OPT3001_RESULT);
+ goto err;
+ }
+ opt->result = ret;
+ opt->result_ready = true;
+ }
err:
- /* Disallow IRQ to access the device while lock is active */
- opt->ok_to_ignore_lock = false;
+ if (opt->use_irq)
+ /* Disallow IRQ to access the device while lock is active */
+ opt->ok_to_ignore_lock = false;
if (ret == 0)
return -ETIMEDOUT;
else if (ret < 0)
return ret;
- /*
- * Disable the end-of-conversion interrupt mechanism by restoring the
- * low-level limit value (clearing OPT3001_LOW_LIMIT_EOC_ENABLE). Note
- * that selectively clearing those enable bits would affect the actual
- * limit value due to bit-overlap and therefore can't be done.
- */
- value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa;
- ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT,
- value);
- if (ret < 0) {
- dev_err(opt->dev, "failed to write register %02x\n",
- OPT3001_LOW_LIMIT);
- return ret;
+ if (opt->use_irq) {
+ /*
+ * Disable the end-of-conversion interrupt mechanism by
+ * restoring the low-level limit value (clearing
+ * OPT3001_LOW_LIMIT_EOC_ENABLE). Note that selectively clearing
+ * those enable bits would affect the actual limit value due to
+ * bit-overlap and therefore can't be done.
+ */
+ value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa;
+ ret = i2c_smbus_write_word_swapped(opt->client,
+ OPT3001_LOW_LIMIT,
+ value);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to write register %02x\n",
+ OPT3001_LOW_LIMIT);
+ return ret;
+ }
}
exponent = OPT3001_REG_EXPONENT(opt->result);
reg = ret;
switch (time) {
- case 100000:
+ case OPT3001_INT_TIME_SHORT:
reg &= ~OPT3001_CONFIGURATION_CT;
- opt->int_time = 100000;
+ opt->int_time = OPT3001_INT_TIME_SHORT;
break;
- case 800000:
+ case OPT3001_INT_TIME_LONG:
reg |= OPT3001_CONFIGURATION_CT;
- opt->int_time = 800000;
+ opt->int_time = OPT3001_INT_TIME_LONG;
break;
default:
return -EINVAL;
/* Reflect status of the device's integration time setting */
if (reg & OPT3001_CONFIGURATION_CT)
- opt->int_time = 800000;
+ opt->int_time = OPT3001_INT_TIME_LONG;
else
- opt->int_time = 100000;
+ opt->int_time = OPT3001_INT_TIME_SHORT;
/* Ensure device is in shutdown initially */
opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SHUTDOWN);
return ret;
}
- ret = request_threaded_irq(irq, NULL, opt3001_irq,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- "opt3001", iio);
- if (ret) {
- dev_err(dev, "failed to request IRQ #%d\n", irq);
- return ret;
+ /* Make use of INT pin only if valid IRQ no. is given */
+ if (irq > 0) {
+ ret = request_threaded_irq(irq, NULL, opt3001_irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ "opt3001", iio);
+ if (ret) {
+ dev_err(dev, "failed to request IRQ #%d\n", irq);
+ return ret;
+ }
+ opt->use_irq = true;
+ } else {
+ dev_dbg(opt->dev, "enabling interrupt-less operation\n");
}
return 0;
int ret;
u16 reg;
- free_irq(client->irq, iio);
+ if (opt->use_irq)
+ free_irq(client->irq, iio);
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
if (ret < 0) {
u8 data_regs[3];
};
-static struct ak_def ak_def_array[AK_MAX_TYPE] = {
+static const struct ak_def ak_def_array[AK_MAX_TYPE] = {
{
.type = AK8975,
.raw_to_gauss = ak8975_raw_to_gauss,
*/
struct ak8975_data {
struct i2c_client *client;
- struct ak_def *def;
+ const struct ak_def *def;
struct attribute_group attrs;
struct mutex lock;
u8 asa[3];
#define ST_MAGN_3_BDU_MASK 0x10
#define ST_MAGN_3_DRDY_IRQ_ADDR 0x62
#define ST_MAGN_3_DRDY_INT_MASK 0x01
+#define ST_MAGN_3_IHL_IRQ_ADDR 0x63
+#define ST_MAGN_3_IHL_IRQ_MASK 0x04
#define ST_MAGN_3_FS_AVL_15000_GAIN 1500
#define ST_MAGN_3_MULTIREAD_BIT false
#define ST_MAGN_3_OUT_X_L_ADDR 0x68
.drdy_irq = {
.addr = ST_MAGN_3_DRDY_IRQ_ADDR,
.mask_int1 = ST_MAGN_3_DRDY_INT_MASK,
+ .addr_ihl = ST_MAGN_3_IHL_IRQ_ADDR,
+ .mask_ihl = ST_MAGN_3_IHL_IRQ_MASK,
},
.multi_read_bit = ST_MAGN_3_MULTIREAD_BIT,
.bootime = 2,
depends on I2C
select REGMAP_I2C
help
- Say yes here to build support for Bosch Sensortec BMP280
- pressure and temperature sensor.
+ Say yes here to build support for Bosch Sensortec BMP280
+ pressure and temperature sensor.
- To compile this driver as a module, choose M here: the module
- will be called bmp280.
+ To compile this driver as a module, choose M here: the module
+ will be called bmp280.
config HID_SENSOR_PRESS
depends on HID_SENSOR_HUB
Say yes here to build support for the HID SENSOR
Pressure driver
- To compile this driver as a module, choose M here: the module
- will be called hid-sensor-press.
+ To compile this driver as a module, choose M here: the module
+ will be called hid-sensor-press.
config MPL115
+ tristate
+
+config MPL115_I2C
tristate "Freescale MPL115A2 pressure sensor driver"
depends on I2C
+ select MPL115
help
Say yes here to build support for the Freescale MPL115A2
pressure sensor connected via I2C.
- To compile this driver as a module, choose M here: the module
- will be called mpl115.
+ To compile this driver as a module, choose M here: the module
+ will be called mpl115_i2c.
+
+config MPL115_SPI
+ tristate "Freescale MPL115A1 pressure sensor driver"
+ depends on SPI_MASTER
+ select MPL115
+ help
+ Say yes here to build support for the Freescale MPL115A1
+ pressure sensor connected via SPI.
+
+ To compile this driver as a module, choose M here: the module
+ will be called mpl115_spi.
config MPL3115
tristate "Freescale MPL3115A2 pressure sensor driver"
Say yes here to build support for the Freescale MPL3115A2
pressure sensor / altimeter.
- To compile this driver as a module, choose M here: the module
- will be called mpl3115.
+ To compile this driver as a module, choose M here: the module
+ will be called mpl3115.
config MS5611
tristate "Measurement Specialties MS5611 pressure sensor driver"
config MS5637
tristate "Measurement Specialties MS5637 pressure & temperature sensor"
depends on I2C
- select IIO_MS_SENSORS_I2C
+ select IIO_MS_SENSORS_I2C
help
If you say yes here you get support for the Measurement Specialties
MS5637 pressure and temperature sensor.
Say yes here to build support for the EPCOS T5403 pressure sensor
connected via I2C.
- To compile this driver as a module, choose M here: the module
- will be called t5403.
+ To compile this driver as a module, choose M here: the module
+ will be called t5403.
endmenu
obj-$(CONFIG_BMP280) += bmp280.o
obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o
obj-$(CONFIG_MPL115) += mpl115.o
+obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o
+obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o
obj-$(CONFIG_MPL3115) += mpl3115.o
obj-$(CONFIG_MS5611) += ms5611_core.o
obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o
/*
- * mpl115.c - Support for Freescale MPL115A2 pressure/temperature sensor
+ * mpl115.c - Support for Freescale MPL115A pressure/temperature sensor
*
* Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
*
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
- * (7-bit I2C slave address 0x60)
- *
* TODO: shutdown pin
*
*/
#include <linux/module.h>
-#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/delay.h>
+#include "mpl115.h"
+
#define MPL115_PADC 0x00 /* pressure ADC output value, MSB first, 10 bit */
#define MPL115_TADC 0x02 /* temperature ADC output value, MSB first, 10 bit */
#define MPL115_A0 0x04 /* 12 bit integer, 3 bit fraction */
#define MPL115_CONVERT 0x12 /* convert temperature and pressure */
struct mpl115_data {
- struct i2c_client *client;
+ struct device *dev;
struct mutex lock;
s16 a0;
s16 b1, b2;
s16 c12;
+ const struct mpl115_ops *ops;
};
static int mpl115_request(struct mpl115_data *data)
{
- int ret = i2c_smbus_write_byte_data(data->client, MPL115_CONVERT, 0);
+ int ret = data->ops->write(data->dev, MPL115_CONVERT, 0);
+
if (ret < 0)
return ret;
if (ret < 0)
goto done;
- ret = i2c_smbus_read_word_swapped(data->client, MPL115_PADC);
+ ret = data->ops->read(data->dev, MPL115_PADC);
if (ret < 0)
goto done;
padc = ret >> 6;
- ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC);
+ ret = data->ops->read(data->dev, MPL115_TADC);
if (ret < 0)
goto done;
tadc = ret >> 6;
ret = mpl115_request(data);
if (ret < 0)
goto done;
- ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC);
+ ret = data->ops->read(data->dev, MPL115_TADC);
done:
mutex_unlock(&data->lock);
return ret;
.driver_module = THIS_MODULE,
};
-static int mpl115_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+int mpl115_probe(struct device *dev, const char *name,
+ const struct mpl115_ops *ops)
{
struct mpl115_data *data;
struct iio_dev *indio_dev;
int ret;
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
- return -ENODEV;
-
- indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
- data->client = client;
+ data->dev = dev;
+ data->ops = ops;
mutex_init(&data->lock);
- i2c_set_clientdata(client, indio_dev);
indio_dev->info = &mpl115_info;
- indio_dev->name = id->name;
- indio_dev->dev.parent = &client->dev;
+ indio_dev->name = name;
+ indio_dev->dev.parent = dev;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = mpl115_channels;
indio_dev->num_channels = ARRAY_SIZE(mpl115_channels);
- ret = i2c_smbus_read_word_swapped(data->client, MPL115_A0);
+ ret = data->ops->init(data->dev);
+ if (ret)
+ return ret;
+
+ ret = data->ops->read(data->dev, MPL115_A0);
if (ret < 0)
return ret;
data->a0 = ret;
- ret = i2c_smbus_read_word_swapped(data->client, MPL115_B1);
+ ret = data->ops->read(data->dev, MPL115_B1);
if (ret < 0)
return ret;
data->b1 = ret;
- ret = i2c_smbus_read_word_swapped(data->client, MPL115_B2);
+ ret = data->ops->read(data->dev, MPL115_B2);
if (ret < 0)
return ret;
data->b2 = ret;
- ret = i2c_smbus_read_word_swapped(data->client, MPL115_C12);
+ ret = data->ops->read(data->dev, MPL115_C12);
if (ret < 0)
return ret;
data->c12 = ret;
- return devm_iio_device_register(&client->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
-
-static const struct i2c_device_id mpl115_id[] = {
- { "mpl115", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, mpl115_id);
-
-static struct i2c_driver mpl115_driver = {
- .driver = {
- .name = "mpl115",
- },
- .probe = mpl115_probe,
- .id_table = mpl115_id,
-};
-module_i2c_driver(mpl115_driver);
+EXPORT_SYMBOL_GPL(mpl115_probe);
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
MODULE_DESCRIPTION("Freescale MPL115 pressure/temperature driver");
--- /dev/null
+/*
+ * Freescale MPL115A pressure/temperature sensor
+ *
+ * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
+ * Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ */
+
+#ifndef _MPL115_H_
+#define _MPL115_H_
+
+struct mpl115_ops {
+ int (*init)(struct device *);
+ int (*read)(struct device *, u8);
+ int (*write)(struct device *, u8, u8);
+};
+
+int mpl115_probe(struct device *dev, const char *name,
+ const struct mpl115_ops *ops);
+
+#endif
--- /dev/null
+/*
+ * Freescale MPL115A2 pressure/temperature sensor
+ *
+ * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * (7-bit I2C slave address 0x60)
+ *
+ * Datasheet: http://www.nxp.com/files/sensors/doc/data_sheet/MPL115A2.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+
+#include "mpl115.h"
+
+static int mpl115_i2c_init(struct device *dev)
+{
+ return 0;
+}
+
+static int mpl115_i2c_read(struct device *dev, u8 address)
+{
+ return i2c_smbus_read_word_swapped(to_i2c_client(dev), address);
+}
+
+static int mpl115_i2c_write(struct device *dev, u8 address, u8 value)
+{
+ return i2c_smbus_write_byte_data(to_i2c_client(dev), address, value);
+}
+
+static const struct mpl115_ops mpl115_i2c_ops = {
+ .init = mpl115_i2c_init,
+ .read = mpl115_i2c_read,
+ .write = mpl115_i2c_write,
+};
+
+static int mpl115_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
+ return -ENODEV;
+
+ return mpl115_probe(&client->dev, id->name, &mpl115_i2c_ops);
+}
+
+static const struct i2c_device_id mpl115_i2c_id[] = {
+ { "mpl115", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mpl115_i2c_id);
+
+static struct i2c_driver mpl115_i2c_driver = {
+ .driver = {
+ .name = "mpl115",
+ },
+ .probe = mpl115_i2c_probe,
+ .id_table = mpl115_i2c_id,
+};
+module_i2c_driver(mpl115_i2c_driver);
+
+MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("Freescale MPL115A2 pressure/temperature driver");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * Freescale MPL115A1 pressure/temperature sensor
+ *
+ * Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Datasheet: http://www.nxp.com/files/sensors/doc/data_sheet/MPL115A1.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#include "mpl115.h"
+
+#define MPL115_SPI_WRITE(address) ((address) << 1)
+#define MPL115_SPI_READ(address) (0x80 | (address) << 1)
+
+struct mpl115_spi_buf {
+ u8 tx[4];
+ u8 rx[4];
+};
+
+static int mpl115_spi_init(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct mpl115_spi_buf *buf;
+
+ buf = devm_kzalloc(dev, sizeof(*buf), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ spi_set_drvdata(spi, buf);
+
+ return 0;
+}
+
+static int mpl115_spi_read(struct device *dev, u8 address)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct mpl115_spi_buf *buf = spi_get_drvdata(spi);
+ struct spi_transfer xfer = {
+ .tx_buf = buf->tx,
+ .rx_buf = buf->rx,
+ .len = 4,
+ };
+ int ret;
+
+ buf->tx[0] = MPL115_SPI_READ(address);
+ buf->tx[2] = MPL115_SPI_READ(address + 1);
+
+ ret = spi_sync_transfer(spi, &xfer, 1);
+ if (ret)
+ return ret;
+
+ return (buf->rx[1] << 8) | buf->rx[3];
+}
+
+static int mpl115_spi_write(struct device *dev, u8 address, u8 value)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct mpl115_spi_buf *buf = spi_get_drvdata(spi);
+ struct spi_transfer xfer = {
+ .tx_buf = buf->tx,
+ .len = 2,
+ };
+
+ buf->tx[0] = MPL115_SPI_WRITE(address);
+ buf->tx[1] = value;
+
+ return spi_sync_transfer(spi, &xfer, 1);
+}
+
+static const struct mpl115_ops mpl115_spi_ops = {
+ .init = mpl115_spi_init,
+ .read = mpl115_spi_read,
+ .write = mpl115_spi_write,
+};
+
+static int mpl115_spi_probe(struct spi_device *spi)
+{
+ const struct spi_device_id *id = spi_get_device_id(spi);
+
+ return mpl115_probe(&spi->dev, id->name, &mpl115_spi_ops);
+}
+
+static const struct spi_device_id mpl115_spi_ids[] = {
+ { "mpl115", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(spi, mpl115_spi_ids);
+
+static struct spi_driver mpl115_spi_driver = {
+ .driver = {
+ .name = "mpl115",
+ },
+ .probe = mpl115_spi_probe,
+ .id_table = mpl115_spi_ids,
+};
+module_spi_driver(mpl115_spi_driver);
+
+MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
+MODULE_DESCRIPTION("Freescale MPL115A1 pressure/temperature driver");
+MODULE_LICENSE("GPL");
#define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR 0x22
#define ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK 0x04
#define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK 0x20
+#define ST_PRESS_LPS331AP_IHL_IRQ_ADDR 0x22
+#define ST_PRESS_LPS331AP_IHL_IRQ_MASK 0x80
#define ST_PRESS_LPS331AP_MULTIREAD_BIT true
#define ST_PRESS_LPS331AP_TEMP_OFFSET 42500
#define ST_PRESS_LPS25H_DRDY_IRQ_ADDR 0x23
#define ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK 0x01
#define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK 0x10
+#define ST_PRESS_LPS25H_IHL_IRQ_ADDR 0x22
+#define ST_PRESS_LPS25H_IHL_IRQ_MASK 0x80
#define ST_PRESS_LPS25H_MULTIREAD_BIT true
#define ST_PRESS_LPS25H_TEMP_OFFSET 42500
#define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28
.addr = ST_PRESS_LPS331AP_DRDY_IRQ_ADDR,
.mask_int1 = ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK,
+ .addr_ihl = ST_PRESS_LPS331AP_IHL_IRQ_ADDR,
+ .mask_ihl = ST_PRESS_LPS331AP_IHL_IRQ_MASK,
},
.multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT,
.bootime = 2,
.addr = ST_PRESS_LPS25H_DRDY_IRQ_ADDR,
.mask_int1 = ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK,
+ .addr_ihl = ST_PRESS_LPS25H_IHL_IRQ_ADDR,
+ .mask_ihl = ST_PRESS_LPS25H_IHL_IRQ_MASK,
},
.multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT,
.bootime = 2,
ARM Ltd. Versatile Express uses specialised platform configuration
bus. System Configuration interface is one of the possible means
of generating transactions on this bus.
+config PANEL
+ tristate "Parallel port LCD/Keypad Panel support"
+ depends on PARPORT
+ ---help---
+ Say Y here if you have an HD44780 or KS-0074 LCD connected to your
+ parallel port. This driver also features 4 and 6-key keypads. The LCD
+ is accessible through the /dev/lcd char device (10, 156), and the
+ keypad through /dev/keypad (10, 185). Both require misc device to be
+ enabled. This code can either be compiled as a module, or linked into
+ the kernel and started at boot. If you don't understand what all this
+ is about, say N.
+
+config PANEL_PARPORT
+ int "Default parallel port number (0=LPT1)"
+ depends on PANEL
+ range 0 255
+ default "0"
+ ---help---
+ This is the index of the parallel port the panel is connected to. One
+ driver instance only supports one parallel port, so if your keypad
+ and LCD are connected to two separate ports, you have to start two
+ modules with different arguments. Numbering starts with '0' for LPT1,
+ and so on.
+
+config PANEL_PROFILE
+ int "Default panel profile (0-5, 0=custom)"
+ depends on PANEL
+ range 0 5
+ default "5"
+ ---help---
+ To ease configuration, the driver supports different configuration
+ profiles for past and recent wirings. These profiles can also be
+ used to define an approximative configuration, completed by a few
+ other options. Here are the profiles :
+
+ 0 = custom (see further)
+ 1 = 2x16 parallel LCD, old keypad
+ 2 = 2x16 serial LCD (KS-0074), new keypad
+ 3 = 2x16 parallel LCD (Hantronix), no keypad
+ 4 = 2x16 parallel LCD (Nexcom NSA1045) with Nexcom's keypad
+ 5 = 2x40 parallel LCD (old one), with old keypad
+
+ Custom configurations allow you to define how your display is
+ wired to the parallel port, and how it works. This is only intended
+ for experts.
+
+config PANEL_KEYPAD
+ depends on PANEL && PANEL_PROFILE="0"
+ int "Keypad type (0=none, 1=old 6 keys, 2=new 6 keys, 3=Nexcom 4 keys)"
+ range 0 3
+ default 0
+ ---help---
+ This enables and configures a keypad connected to the parallel port.
+ The keys will be read from character device 10,185. Valid values are :
+
+ 0 : do not enable this driver
+ 1 : old 6 keys keypad
+ 2 : new 6 keys keypad, as used on the server at www.ant-computing.com
+ 3 : Nexcom NSA1045's 4 keys keypad
+
+ New profiles can be described in the driver source. The driver also
+ supports simultaneous keys pressed when the keypad supports them.
+
+config PANEL_LCD
+ depends on PANEL && PANEL_PROFILE="0"
+ int "LCD type (0=none, 1=custom, 2=old //, 3=ks0074, 4=hantronix, 5=Nexcom)"
+ range 0 5
+ default 0
+ ---help---
+ This enables and configures an LCD connected to the parallel port.
+ The driver includes an interpreter for escape codes starting with
+ '\e[L' which are specific to the LCD, and a few ANSI codes. The
+ driver will be registered as character device 10,156, usually
+ under the name '/dev/lcd'. There are a total of 6 supported types :
+
+ 0 : do not enable the driver
+ 1 : custom configuration and wiring (see further)
+ 2 : 2x16 & 2x40 parallel LCD (old wiring)
+ 3 : 2x16 serial LCD (KS-0074 based)
+ 4 : 2x16 parallel LCD (Hantronix wiring)
+ 5 : 2x16 parallel LCD (Nexcom wiring)
+
+ When type '1' is specified, other options will appear to configure
+ more precise aspects (wiring, dimensions, protocol, ...). Please note
+ that those values changed from the 2.4 driver for better consistency.
+
+config PANEL_LCD_HEIGHT
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "Number of lines on the LCD (1-2)"
+ range 1 2
+ default 2
+ ---help---
+ This is the number of visible character lines on the LCD in custom profile.
+ It can either be 1 or 2.
+
+config PANEL_LCD_WIDTH
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "Number of characters per line on the LCD (1-40)"
+ range 1 40
+ default 40
+ ---help---
+ This is the number of characters per line on the LCD in custom profile.
+ Common values are 16,20,24,40.
+
+config PANEL_LCD_BWIDTH
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "Internal LCD line width (1-40, 40 by default)"
+ range 1 40
+ default 40
+ ---help---
+ Most LCDs use a standard controller which supports hardware lines of 40
+ characters, although sometimes only 16, 20 or 24 of them are really wired
+ to the terminal. This results in some non-visible but addressable characters,
+ and is the case for most parallel LCDs. Other LCDs, and some serial ones,
+ however, use the same line width internally as what is visible. The KS0074
+ for example, uses 16 characters per line for 16 visible characters per line.
+
+ This option lets you configure the value used by your LCD in 'custom' profile.
+ If you don't know, put '40' here.
+
+config PANEL_LCD_HWIDTH
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "Hardware LCD line width (1-64, 64 by default)"
+ range 1 64
+ default 64
+ ---help---
+ Most LCDs use a single address bit to differentiate line 0 and line 1. Since
+ some of them need to be able to address 40 chars with the lower bits, they
+ often use the immediately superior power of 2, which is 64, to address the
+ next line.
+
+ If you don't know what your LCD uses, in doubt let 16 here for a 2x16, and
+ 64 here for a 2x40.
+
+config PANEL_LCD_CHARSET
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "LCD character set (0=normal, 1=KS0074)"
+ range 0 1
+ default 0
+ ---help---
+ Some controllers such as the KS0074 use a somewhat strange character set
+ where many symbols are at unusual places. The driver knows how to map
+ 'standard' ASCII characters to the character sets used by these controllers.
+ Valid values are :
+
+ 0 : normal (untranslated) character set
+ 1 : KS0074 character set
+
+ If you don't know, use the normal one (0).
+
+config PANEL_LCD_PROTO
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "LCD communication mode (0=parallel 8 bits, 1=serial)"
+ range 0 1
+ default 0
+ ---help---
+ This driver now supports any serial or parallel LCD wired to a parallel
+ port. But before assigning signals, the driver needs to know if it will
+ be driving a serial LCD or a parallel one. Serial LCDs only use 2 wires
+ (SDA/SCL), while parallel ones use 2 or 3 wires for the control signals
+ (E, RS, sometimes RW), and 4 or 8 for the data. Use 0 here for a 8 bits
+ parallel LCD, and 1 for a serial LCD.
+
+config PANEL_LCD_PIN_E
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
+ int "Parallel port pin number & polarity connected to the LCD E signal (-17...17) "
+ range -17 17
+ default 14
+ ---help---
+ This describes the number of the parallel port pin to which the LCD 'E'
+ signal has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'E' pin in custom profile is '14' (AUTOFEED).
+
+config PANEL_LCD_PIN_RS
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
+ int "Parallel port pin number & polarity connected to the LCD RS signal (-17...17) "
+ range -17 17
+ default 17
+ ---help---
+ This describes the number of the parallel port pin to which the LCD 'RS'
+ signal has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'RS' pin in custom profile is '17' (SELECT IN).
+
+config PANEL_LCD_PIN_RW
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
+ int "Parallel port pin number & polarity connected to the LCD RW signal (-17...17) "
+ range -17 17
+ default 16
+ ---help---
+ This describes the number of the parallel port pin to which the LCD 'RW'
+ signal has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'RW' pin in custom profile is '16' (INIT).
+
+config PANEL_LCD_PIN_SCL
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0"
+ int "Parallel port pin number & polarity connected to the LCD SCL signal (-17...17) "
+ range -17 17
+ default 1
+ ---help---
+ This describes the number of the parallel port pin to which the serial
+ LCD 'SCL' signal has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'SCL' pin in custom profile is '1' (STROBE).
+
+config PANEL_LCD_PIN_SDA
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0"
+ int "Parallel port pin number & polarity connected to the LCD SDA signal (-17...17) "
+ range -17 17
+ default 2
+ ---help---
+ This describes the number of the parallel port pin to which the serial
+ LCD 'SDA' signal has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'SDA' pin in custom profile is '2' (D0).
+
+config PANEL_LCD_PIN_BL
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "Parallel port pin number & polarity connected to the LCD backlight signal (-17...17) "
+ range -17 17
+ default 0
+ ---help---
+ This describes the number of the parallel port pin to which the LCD 'BL' signal
+ has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'BL' pin in custom profile is '0' (uncontrolled).
+
+config PANEL_CHANGE_MESSAGE
+ depends on PANEL
+ bool "Change LCD initialization message ?"
+ default "n"
+ ---help---
+ This allows you to replace the boot message indicating the kernel version
+ and the driver version with a custom message. This is useful on appliances
+ where a simple 'Starting system' message can be enough to stop a customer
+ from worrying.
+
+ If you say 'Y' here, you'll be able to choose a message yourself. Otherwise,
+ say 'N' and keep the default message with the version.
+
+config PANEL_BOOT_MESSAGE
+ depends on PANEL && PANEL_CHANGE_MESSAGE="y"
+ string "New initialization message"
+ default ""
+ ---help---
+ This allows you to replace the boot message indicating the kernel version
+ and the driver version with a custom message. This is useful on appliances
+ where a simple 'Starting system' message can be enough to stop a customer
+ from worrying.
+
+ An empty message will only clear the display at driver init time. Any other
+ printf()-formatted message is valid with newline and escape codes.
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
obj-$(CONFIG_CXL_BASE) += cxl/
+obj-$(CONFIG_PANEL) += panel.o
/* logical or of the input bits involved in the scan matrix */
static __u8 scan_mask_i;
-typedef __u64 pmask_t;
-
enum input_type {
INPUT_TYPE_STD,
INPUT_TYPE_KBD,
struct logical_input {
struct list_head list;
- pmask_t mask;
- pmask_t value;
+ __u64 mask;
+ __u64 value;
enum input_type type;
enum input_state state;
__u8 rise_time, fall_time;
* corresponds to the ground.
* Within each group, bits are stored in the same order as read on the port :
* BAPSE (busy=4, ack=3, paper empty=2, select=1, error=0).
- * So, each __u64 (or pmask_t) is represented like this :
+ * So, each __u64 is represented like this :
* 0000000000000000000BAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSE
* <-----unused------><gnd><d07><d06><d05><d04><d03><d02><d01><d00>
*/
/* what has just been read from the I/O ports */
-static pmask_t phys_read;
+static __u64 phys_read;
/* previous phys_read */
-static pmask_t phys_read_prev;
+static __u64 phys_read_prev;
/* stabilized phys_read (phys_read|phys_read_prev) */
-static pmask_t phys_curr;
+static __u64 phys_curr;
/* previous phys_curr */
-static pmask_t phys_prev;
+static __u64 phys_prev;
/* 0 means that at least one logical signal needs be computed */
static char inputs_stable;
lcd_send_serial(0x5F); /* R/W=W, RS=1 */
lcd_send_serial(' ' & 0x0F);
lcd_send_serial((' ' >> 4) & 0x0F);
- udelay(40); /* the shortest data takes at least 40 us */
+ /* the shortest data takes at least 40 us */
+ udelay(40);
}
spin_unlock_irq(&pprt_lock);
gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i;
/* grounded inputs are signals 40-44 */
- phys_read |= (pmask_t) gndmask << 40;
+ phys_read |= (__u64)gndmask << 40;
if (bitmask != gndmask) {
/*
w_dtr(pprt, oldval & ~bitval); /* enable this output */
bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask;
- phys_read |= (pmask_t) bitmask << (5 * bit);
+ phys_read |= (__u64)bitmask << (5 * bit);
}
w_dtr(pprt, oldval); /* disable all outputs */
}
* corresponding to out and in bits respectively.
* returns 1 if ok, 0 if error (in which case, nothing is written).
*/
-static int input_name2mask(const char *name, pmask_t *mask, pmask_t *value,
- char *imask, char *omask)
+static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value,
+ u8 *imask, u8 *omask)
{
- static char sigtab[10] = "EeSsPpAaBb";
- char im, om;
- pmask_t m, v;
+ const char sigtab[] = "EeSsPpAaBb";
+ u8 im, om;
+ __u64 m, v;
- om = 0ULL;
- im = 0ULL;
+ om = 0;
+ im = 0;
m = 0ULL;
v = 0ULL;
while (*name) {
int in, out, bit, neg;
+ const char *idx;
- for (in = 0; (in < sizeof(sigtab)) && (sigtab[in] != *name);
- in++)
- ;
-
- if (in >= sizeof(sigtab))
+ idx = strchr(sigtab, *name);
+ if (!idx)
return 0; /* input name not found */
+
+ in = idx - sigtab;
neg = (in & 1); /* odd (lower) names are negated */
in >>= 1;
im |= BIT(in);
name++;
- if (isdigit(*name)) {
+ if (*name >= '0' && *name <= '7') {
out = *name - '0';
om |= BIT(out);
} else if (*name == '-') {
source "drivers/staging/comedi/Kconfig"
-source "drivers/staging/olpc_dcon/Kconfig"
-
-source "drivers/staging/panel/Kconfig"
-
source "drivers/staging/rtl8192u/Kconfig"
source "drivers/staging/rtl8192e/Kconfig"
source "drivers/staging/dgnc/Kconfig"
-source "drivers/staging/dgap/Kconfig"
-
source "drivers/staging/gs_fpgaboot/Kconfig"
source "drivers/staging/skein/Kconfig"
# Makefile for staging directory
-# fix for build system bug...
-obj-$(CONFIG_STAGING) += staging.o
-
obj-y += media/
obj-$(CONFIG_SLICOSS) += slicoss/
obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_COMEDI) += comedi/
-obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
-obj-$(CONFIG_PANEL) += panel/
obj-$(CONFIG_RTL8192U) += rtl8192u/
obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_R8712U) += rtl8712/
obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_LUSTRE_FS) += lustre/
obj-$(CONFIG_DGNC) += dgnc/
-obj-$(CONFIG_DGAP) += dgap/
obj-$(CONFIG_MTD_SPINAND_MT29F) += mt29f_spinand/
obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/
obj-$(CONFIG_CRYPTO_SKEIN) += skein/
synchronization. Useful when there is no hardware primitive backing
the synchronization.
-config SW_SYNC_USER
- bool "Userspace API for SW_SYNC"
- default n
- depends on SW_SYNC
- ---help---
- Provides a user space API to the sw sync object.
- *WARNING* improper use of this can result in deadlocking kernel
- drivers from userspace.
-
source "drivers/staging/android/ion/Kconfig"
endif # if ANDROID
if (!(sc->gfp_mask & __GFP_FS))
return SHRINK_STOP;
- mutex_lock(&ashmem_mutex);
+ if (!mutex_trylock(&ashmem_mutex))
+ return -1;
+
list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) {
loff_t start = range->pgstart * PAGE_SIZE;
loff_t end = (range->pgend + 1) * PAGE_SIZE;
* memory coming from the heaps is ready for dma, ie if it has a
* cached mapping that mapping has been invalidated
*/
- for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i)
+ for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) {
sg_dma_address(sg) = sg_phys(sg);
+ sg_dma_len(sg) = sg->length;
+ }
mutex_lock(&dev->buffer_lock);
ion_buffer_add(dev, buffer);
mutex_unlock(&dev->buffer_lock);
}
EXPORT_SYMBOL(ion_unmap_kernel);
+static struct mutex debugfs_mutex;
+static struct rb_root *ion_root_client;
+static int is_client_alive(struct ion_client *client)
+{
+ struct rb_node *node;
+ struct ion_client *tmp;
+ struct ion_device *dev;
+
+ node = ion_root_client->rb_node;
+ dev = container_of(ion_root_client, struct ion_device, clients);
+
+ down_read(&dev->lock);
+ while (node) {
+ tmp = rb_entry(node, struct ion_client, node);
+ if (client < tmp) {
+ node = node->rb_left;
+ } else if (client > tmp) {
+ node = node->rb_right;
+ } else {
+ up_read(&dev->lock);
+ return 1;
+ }
+ }
+
+ up_read(&dev->lock);
+ return 0;
+}
+
static int ion_debug_client_show(struct seq_file *s, void *unused)
{
struct ion_client *client = s->private;
const char *names[ION_NUM_HEAP_IDS] = {NULL};
int i;
+ mutex_lock(&debugfs_mutex);
+ if (!is_client_alive(client)) {
+ seq_printf(s, "ion_client 0x%p dead, can't dump its buffers\n",
+ client);
+ mutex_unlock(&debugfs_mutex);
+ return 0;
+ }
+
mutex_lock(&client->lock);
for (n = rb_first(&client->handles); n; n = rb_next(n)) {
struct ion_handle *handle = rb_entry(n, struct ion_handle,
sizes[id] += handle->buffer->size;
}
mutex_unlock(&client->lock);
+ mutex_unlock(&debugfs_mutex);
seq_printf(s, "%16.16s: %16.16s\n", "heap_name", "size_in_bytes");
for (i = 0; i < ION_NUM_HEAP_IDS; i++) {
struct rb_node *n;
pr_debug("%s: %d\n", __func__, __LINE__);
+ mutex_lock(&debugfs_mutex);
while ((n = rb_first(&client->handles))) {
struct ion_handle *handle = rb_entry(n, struct ion_handle,
node);
kfree(client->display_name);
kfree(client->name);
kfree(client);
+ mutex_unlock(&debugfs_mutex);
}
EXPORT_SYMBOL(ion_client_destroy);
}
EXPORT_SYMBOL(ion_share_dma_buf_fd);
-struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd)
+struct ion_handle *ion_import_dma_buf(struct ion_client *client,
+ struct dma_buf *dmabuf)
{
- struct dma_buf *dmabuf;
struct ion_buffer *buffer;
struct ion_handle *handle;
int ret;
- dmabuf = dma_buf_get(fd);
- if (IS_ERR(dmabuf))
- return ERR_CAST(dmabuf);
/* if this memory came from ion */
if (dmabuf->ops != &dma_buf_ops) {
pr_err("%s: can not import dmabuf from another exporter\n",
__func__);
- dma_buf_put(dmabuf);
return ERR_PTR(-EINVAL);
}
buffer = dmabuf->priv;
}
end:
- dma_buf_put(dmabuf);
return handle;
}
EXPORT_SYMBOL(ion_import_dma_buf);
+struct ion_handle *ion_import_dma_buf_fd(struct ion_client *client, int fd)
+{
+ struct dma_buf *dmabuf;
+ struct ion_handle *handle;
+
+ dmabuf = dma_buf_get(fd);
+ if (IS_ERR(dmabuf))
+ return ERR_CAST(dmabuf);
+
+ handle = ion_import_dma_buf(client, dmabuf);
+ dma_buf_put(dmabuf);
+ return handle;
+}
+EXPORT_SYMBOL(ion_import_dma_buf_fd);
+
static int ion_sync_for_device(struct ion_client *client, int fd)
{
struct dma_buf *dmabuf;
{
struct ion_handle *handle;
- handle = ion_import_dma_buf(client, data.fd.fd);
+ handle = ion_import_dma_buf_fd(client, data.fd.fd);
if (IS_ERR(handle))
ret = PTR_ERR(handle);
else
seq_printf(s, "%16s %16s %16s\n", "client", "pid", "size");
seq_puts(s, "----------------------------------------------------\n");
+ mutex_lock(&debugfs_mutex);
for (n = rb_first(&dev->clients); n; n = rb_next(n)) {
struct ion_client *client = rb_entry(n, struct ion_client,
node);
client->pid, size);
}
}
+ mutex_unlock(&debugfs_mutex);
+
seq_puts(s, "----------------------------------------------------\n");
seq_puts(s, "orphaned allocations (info is from last known client):\n");
mutex_lock(&dev->buffer_lock);
init_rwsem(&idev->lock);
plist_head_init(&idev->heaps);
idev->clients = RB_ROOT;
+ ion_root_client = &idev->clients;
+ mutex_init(&debugfs_mutex);
return idev;
}
EXPORT_SYMBOL(ion_device_create);
int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle);
/**
- * ion_import_dma_buf() - given an dma-buf fd from the ion exporter get handle
+ * ion_import_dma_buf() - get ion_handle from dma-buf
+ * @client: the client
+ * @dmabuf: the dma-buf
+ *
+ * Get the ion_buffer associated with the dma-buf and return the ion_handle.
+ * If no ion_handle exists for this buffer, return newly created ion_handle.
+ * If dma-buf from another exporter is passed, return ERR_PTR(-EINVAL)
+ */
+struct ion_handle *ion_import_dma_buf(struct ion_client *client,
+ struct dma_buf *dmabuf);
+
+/**
+ * ion_import_dma_buf_fd() - given a dma-buf fd from the ion exporter get handle
* @client: the client
* @fd: the dma-buf fd
*
- * Given an dma-buf fd that was allocated through ion via ion_share_dma_buf,
- * import that fd and return a handle representing it. If a dma-buf from
+ * Given an dma-buf fd that was allocated through ion via ion_share_dma_buf_fd,
+ * import that fd and return a handle representing it. If a dma-buf from
* another exporter is passed in this function will return ERR_PTR(-EINVAL)
*/
-struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd);
+struct ion_handle *ion_import_dma_buf_fd(struct ion_client *client, int fd);
#endif /* _LINUX_ION_H */
if (!carveout_heap)
return ERR_PTR(-ENOMEM);
- carveout_heap->pool = gen_pool_create(12, -1);
+ carveout_heap->pool = gen_pool_create(PAGE_SHIFT, -1);
if (!carveout_heap->pool) {
kfree(carveout_heap);
return ERR_PTR(-ENOMEM);
struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order)
{
- struct ion_page_pool *pool = kmalloc(sizeof(struct ion_page_pool),
- GFP_KERNEL);
+ struct ion_page_pool *pool = kmalloc(sizeof(*pool), GFP_KERNEL);
+
if (!pool)
return NULL;
pool->high_count = 0;
#include "ion_priv.h"
static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN |
- __GFP_NORETRY) & ~__GFP_DIRECT_RECLAIM;
+ __GFP_NORETRY) & ~__GFP_RECLAIM;
static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN);
static const unsigned int orders[] = {8, 4, 0};
static const int num_orders = ARRAY_SIZE(orders);
int tasksize;
int i;
short min_score_adj = OOM_SCORE_ADJ_MAX + 1;
+ int minfree = 0;
int selected_tasksize = 0;
short selected_oom_score_adj;
int array_size = ARRAY_SIZE(lowmem_adj);
if (lowmem_minfree_size < array_size)
array_size = lowmem_minfree_size;
for (i = 0; i < array_size; i++) {
- if (other_free < lowmem_minfree[i] &&
- other_file < lowmem_minfree[i]) {
+ minfree = lowmem_minfree[i];
+ if (other_free < minfree && other_file < minfree) {
min_score_adj = lowmem_adj[i];
break;
}
selected = p;
selected_tasksize = tasksize;
selected_oom_score_adj = oom_score_adj;
- lowmem_print(2, "select %d (%s), adj %hd, size %d, to kill\n",
- p->pid, p->comm, oom_score_adj, tasksize);
+ lowmem_print(2, "select '%s' (%d), adj %hd, size %d, to kill\n",
+ p->comm, p->pid, oom_score_adj, tasksize);
}
if (selected) {
task_lock(selected);
if (selected->mm)
mark_oom_victim(selected);
task_unlock(selected);
- lowmem_print(1, "send sigkill to %d (%s), adj %hd, size %d\n",
- selected->pid, selected->comm,
- selected_oom_score_adj, selected_tasksize);
+ lowmem_print(1, "Killing '%s' (%d), adj %hd,\n"
+ " to free %ldkB on behalf of '%s' (%d) because\n"
+ " cache %ldkB is below limit %ldkB for oom_score_adj %hd\n"
+ " Free memory is %ldkB above reserved\n",
+ selected->comm, selected->pid,
+ selected_oom_score_adj,
+ selected_tasksize * (long)(PAGE_SIZE / 1024),
+ current->comm, current->pid,
+ other_file * (long)(PAGE_SIZE / 1024),
+ minfree * (long)(PAGE_SIZE / 1024),
+ min_score_adj,
+ other_free * (long)(PAGE_SIZE / 1024));
lowmem_deathpending_timeout = jiffies + HZ;
rem += selected_tasksize;
}
#include "sw_sync.h"
-static int sw_sync_cmp(u32 a, u32 b)
-{
- if (a == b)
- return 0;
-
- return ((s32)a - (s32)b) < 0 ? -1 : 1;
-}
-
-struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value)
+struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value)
{
struct sw_sync_pt *pt;
pt->value = value;
- return (struct sync_pt *)pt;
+ return (struct fence *)pt;
}
EXPORT_SYMBOL(sw_sync_pt_create);
-static struct sync_pt *sw_sync_pt_dup(struct sync_pt *sync_pt)
-{
- struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
- struct sw_sync_timeline *obj =
- (struct sw_sync_timeline *)sync_pt_parent(sync_pt);
-
- return (struct sync_pt *)sw_sync_pt_create(obj, pt->value);
-}
-
-static int sw_sync_pt_has_signaled(struct sync_pt *sync_pt)
+static int sw_sync_fence_has_signaled(struct fence *fence)
{
- struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+ struct sw_sync_pt *pt = (struct sw_sync_pt *)fence;
struct sw_sync_timeline *obj =
- (struct sw_sync_timeline *)sync_pt_parent(sync_pt);
-
- return sw_sync_cmp(obj->value, pt->value) >= 0;
-}
-
-static int sw_sync_pt_compare(struct sync_pt *a, struct sync_pt *b)
-{
- struct sw_sync_pt *pt_a = (struct sw_sync_pt *)a;
- struct sw_sync_pt *pt_b = (struct sw_sync_pt *)b;
-
- return sw_sync_cmp(pt_a->value, pt_b->value);
-}
-
-static int sw_sync_fill_driver_data(struct sync_pt *sync_pt,
- void *data, int size)
-{
- struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
-
- if (size < sizeof(pt->value))
- return -ENOMEM;
+ (struct sw_sync_timeline *)fence_parent(fence);
- memcpy(data, &pt->value, sizeof(pt->value));
-
- return sizeof(pt->value);
+ return (pt->value > obj->value) ? 0 : 1;
}
static void sw_sync_timeline_value_str(struct sync_timeline *sync_timeline,
snprintf(str, size, "%d", timeline->value);
}
-static void sw_sync_pt_value_str(struct sync_pt *sync_pt,
- char *str, int size)
+static void sw_sync_fence_value_str(struct fence *fence, char *str, int size)
{
- struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+ struct sw_sync_pt *pt = (struct sw_sync_pt *)fence;
snprintf(str, size, "%d", pt->value);
}
static struct sync_timeline_ops sw_sync_timeline_ops = {
.driver_name = "sw_sync",
- .dup = sw_sync_pt_dup,
- .has_signaled = sw_sync_pt_has_signaled,
- .compare = sw_sync_pt_compare,
- .fill_driver_data = sw_sync_fill_driver_data,
+ .has_signaled = sw_sync_fence_has_signaled,
.timeline_value_str = sw_sync_timeline_value_str,
- .pt_value_str = sw_sync_pt_value_str,
+ .fence_value_str = sw_sync_fence_value_str,
};
struct sw_sync_timeline *sw_sync_timeline_create(const char *name)
sync_timeline_signal(&obj->obj);
}
EXPORT_SYMBOL(sw_sync_timeline_inc);
-
-#ifdef CONFIG_SW_SYNC_USER
-/* *WARNING*
- *
- * improper use of this can result in deadlocking kernel drivers from userspace.
- */
-
-/* opening sw_sync create a new sync obj */
-static int sw_sync_open(struct inode *inode, struct file *file)
-{
- struct sw_sync_timeline *obj;
- char task_comm[TASK_COMM_LEN];
-
- get_task_comm(task_comm, current);
-
- obj = sw_sync_timeline_create(task_comm);
- if (!obj)
- return -ENOMEM;
-
- file->private_data = obj;
-
- return 0;
-}
-
-static int sw_sync_release(struct inode *inode, struct file *file)
-{
- struct sw_sync_timeline *obj = file->private_data;
-
- sync_timeline_destroy(&obj->obj);
- return 0;
-}
-
-static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj,
- unsigned long arg)
-{
- int fd = get_unused_fd_flags(O_CLOEXEC);
- int err;
- struct sync_pt *pt;
- struct sync_fence *fence;
- struct sw_sync_create_fence_data data;
-
- if (fd < 0)
- return fd;
-
- if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
- err = -EFAULT;
- goto err;
- }
-
- pt = sw_sync_pt_create(obj, data.value);
- if (!pt) {
- err = -ENOMEM;
- goto err;
- }
-
- data.name[sizeof(data.name) - 1] = '\0';
- fence = sync_fence_create(data.name, pt);
- if (!fence) {
- sync_pt_free(pt);
- err = -ENOMEM;
- goto err;
- }
-
- data.fence = fd;
- if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
- sync_fence_put(fence);
- err = -EFAULT;
- goto err;
- }
-
- sync_fence_install(fence, fd);
-
- return 0;
-
-err:
- put_unused_fd(fd);
- return err;
-}
-
-static long sw_sync_ioctl_inc(struct sw_sync_timeline *obj, unsigned long arg)
-{
- u32 value;
-
- if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
- return -EFAULT;
-
- sw_sync_timeline_inc(obj, value);
-
- return 0;
-}
-
-static long sw_sync_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct sw_sync_timeline *obj = file->private_data;
-
- switch (cmd) {
- case SW_SYNC_IOC_CREATE_FENCE:
- return sw_sync_ioctl_create_fence(obj, arg);
-
- case SW_SYNC_IOC_INC:
- return sw_sync_ioctl_inc(obj, arg);
-
- default:
- return -ENOTTY;
- }
-}
-
-static const struct file_operations sw_sync_fops = {
- .owner = THIS_MODULE,
- .open = sw_sync_open,
- .release = sw_sync_release,
- .unlocked_ioctl = sw_sync_ioctl,
- .compat_ioctl = sw_sync_ioctl,
-};
-
-static struct miscdevice sw_sync_dev = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "sw_sync",
- .fops = &sw_sync_fops,
-};
-
-static int __init sw_sync_device_init(void)
-{
- return misc_register(&sw_sync_dev);
-}
-device_initcall(sw_sync_device_init);
-
-#endif /* CONFIG_SW_SYNC_USER */
};
struct sw_sync_pt {
- struct sync_pt pt;
+ struct fence pt;
u32 value;
};
struct sw_sync_timeline *sw_sync_timeline_create(const char *name);
void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc);
-struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value);
+struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value);
#else
static inline struct sw_sync_timeline *sw_sync_timeline_create(const char *name)
{
{
}
-static inline struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj,
- u32 value)
+static inline struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj,
+ u32 value)
{
return NULL;
}
#include "trace/sync.h"
static const struct fence_ops android_fence_ops;
-static const struct file_operations sync_fence_fops;
+static const struct file_operations sync_file_fops;
struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
int size, const char *name)
sync_timeline_debug_remove(obj);
- if (obj->ops->release_obj)
- obj->ops->release_obj(obj);
-
kfree(obj);
}
*/
smp_wmb();
- /*
- * signal any children that their parent is going away.
- */
- sync_timeline_signal(obj);
sync_timeline_put(obj);
}
EXPORT_SYMBOL(sync_timeline_destroy);
void sync_timeline_signal(struct sync_timeline *obj)
{
unsigned long flags;
- LIST_HEAD(signaled_pts);
- struct sync_pt *pt, *next;
+ struct fence *fence, *next;
trace_sync_timeline(obj);
spin_lock_irqsave(&obj->child_list_lock, flags);
- list_for_each_entry_safe(pt, next, &obj->active_list_head,
+ list_for_each_entry_safe(fence, next, &obj->active_list_head,
active_list) {
- if (fence_is_signaled_locked(&pt->base))
- list_del_init(&pt->active_list);
+ if (fence_is_signaled_locked(fence))
+ list_del_init(&fence->active_list);
}
spin_unlock_irqrestore(&obj->child_list_lock, flags);
}
EXPORT_SYMBOL(sync_timeline_signal);
-struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size)
+struct fence *sync_pt_create(struct sync_timeline *obj, int size)
{
unsigned long flags;
- struct sync_pt *pt;
+ struct fence *fence;
- if (size < sizeof(struct sync_pt))
+ if (size < sizeof(*fence))
return NULL;
- pt = kzalloc(size, GFP_KERNEL);
- if (!pt)
+ fence = kzalloc(size, GFP_KERNEL);
+ if (!fence)
return NULL;
spin_lock_irqsave(&obj->child_list_lock, flags);
sync_timeline_get(obj);
- fence_init(&pt->base, &android_fence_ops, &obj->child_list_lock,
+ fence_init(fence, &android_fence_ops, &obj->child_list_lock,
obj->context, ++obj->value);
- list_add_tail(&pt->child_list, &obj->child_list_head);
- INIT_LIST_HEAD(&pt->active_list);
+ list_add_tail(&fence->child_list, &obj->child_list_head);
+ INIT_LIST_HEAD(&fence->active_list);
spin_unlock_irqrestore(&obj->child_list_lock, flags);
- return pt;
+ return fence;
}
EXPORT_SYMBOL(sync_pt_create);
-void sync_pt_free(struct sync_pt *pt)
-{
- fence_put(&pt->base);
-}
-EXPORT_SYMBOL(sync_pt_free);
-
-static struct sync_fence *sync_fence_alloc(int size, const char *name)
+static struct sync_file *sync_file_alloc(int size, const char *name)
{
- struct sync_fence *fence;
+ struct sync_file *sync_file;
- fence = kzalloc(size, GFP_KERNEL);
- if (!fence)
+ sync_file = kzalloc(size, GFP_KERNEL);
+ if (!sync_file)
return NULL;
- fence->file = anon_inode_getfile("sync_fence", &sync_fence_fops,
- fence, 0);
- if (IS_ERR(fence->file))
+ sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops,
+ sync_file, 0);
+ if (IS_ERR(sync_file->file))
goto err;
- kref_init(&fence->kref);
- strlcpy(fence->name, name, sizeof(fence->name));
+ kref_init(&sync_file->kref);
+ strlcpy(sync_file->name, name, sizeof(sync_file->name));
- init_waitqueue_head(&fence->wq);
+ init_waitqueue_head(&sync_file->wq);
- return fence;
+ return sync_file;
err:
- kfree(fence);
+ kfree(sync_file);
return NULL;
}
static void fence_check_cb_func(struct fence *f, struct fence_cb *cb)
{
- struct sync_fence_cb *check;
- struct sync_fence *fence;
+ struct sync_file_cb *check;
+ struct sync_file *sync_file;
- check = container_of(cb, struct sync_fence_cb, cb);
- fence = check->fence;
+ check = container_of(cb, struct sync_file_cb, cb);
+ sync_file = check->sync_file;
- if (atomic_dec_and_test(&fence->status))
- wake_up_all(&fence->wq);
+ if (atomic_dec_and_test(&sync_file->status))
+ wake_up_all(&sync_file->wq);
}
-/* TODO: implement a create which takes more that one sync_pt */
-struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt)
+/* TODO: implement a create which takes more that one fence */
+struct sync_file *sync_file_create(const char *name, struct fence *fence)
{
- struct sync_fence *fence;
+ struct sync_file *sync_file;
- fence = sync_fence_alloc(offsetof(struct sync_fence, cbs[1]), name);
- if (!fence)
+ sync_file = sync_file_alloc(offsetof(struct sync_file, cbs[1]),
+ name);
+ if (!sync_file)
return NULL;
- fence->num_fences = 1;
- atomic_set(&fence->status, 1);
+ sync_file->num_fences = 1;
+ atomic_set(&sync_file->status, 1);
- fence->cbs[0].sync_pt = pt;
- fence->cbs[0].fence = fence;
- if (fence_add_callback(pt, &fence->cbs[0].cb, fence_check_cb_func))
- atomic_dec(&fence->status);
+ sync_file->cbs[0].fence = fence;
+ sync_file->cbs[0].sync_file = sync_file;
+ if (fence_add_callback(fence, &sync_file->cbs[0].cb,
+ fence_check_cb_func))
+ atomic_dec(&sync_file->status);
- sync_fence_debug_add(fence);
+ sync_file_debug_add(sync_file);
- return fence;
+ return sync_file;
}
-EXPORT_SYMBOL(sync_fence_create_dma);
+EXPORT_SYMBOL(sync_file_create);
-struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
-{
- return sync_fence_create_dma(name, &pt->base);
-}
-EXPORT_SYMBOL(sync_fence_create);
-
-struct sync_fence *sync_fence_fdget(int fd)
+struct sync_file *sync_file_fdget(int fd)
{
struct file *file = fget(fd);
if (!file)
return NULL;
- if (file->f_op != &sync_fence_fops)
+ if (file->f_op != &sync_file_fops)
goto err;
return file->private_data;
fput(file);
return NULL;
}
-EXPORT_SYMBOL(sync_fence_fdget);
+EXPORT_SYMBOL(sync_file_fdget);
-void sync_fence_put(struct sync_fence *fence)
+void sync_file_put(struct sync_file *sync_file)
{
- fput(fence->file);
+ fput(sync_file->file);
}
-EXPORT_SYMBOL(sync_fence_put);
+EXPORT_SYMBOL(sync_file_put);
-void sync_fence_install(struct sync_fence *fence, int fd)
+void sync_file_install(struct sync_file *sync_file, int fd)
{
- fd_install(fd, fence->file);
+ fd_install(fd, sync_file->file);
}
-EXPORT_SYMBOL(sync_fence_install);
+EXPORT_SYMBOL(sync_file_install);
-static void sync_fence_add_pt(struct sync_fence *fence,
- int *i, struct fence *pt)
+static void sync_file_add_pt(struct sync_file *sync_file, int *i,
+ struct fence *fence)
{
- fence->cbs[*i].sync_pt = pt;
- fence->cbs[*i].fence = fence;
+ sync_file->cbs[*i].fence = fence;
+ sync_file->cbs[*i].sync_file = sync_file;
- if (!fence_add_callback(pt, &fence->cbs[*i].cb, fence_check_cb_func)) {
- fence_get(pt);
+ if (!fence_add_callback(fence, &sync_file->cbs[*i].cb,
+ fence_check_cb_func)) {
+ fence_get(fence);
(*i)++;
}
}
-struct sync_fence *sync_fence_merge(const char *name,
- struct sync_fence *a, struct sync_fence *b)
+struct sync_file *sync_file_merge(const char *name,
+ struct sync_file *a, struct sync_file *b)
{
int num_fences = a->num_fences + b->num_fences;
- struct sync_fence *fence;
+ struct sync_file *sync_file;
int i, i_a, i_b;
- unsigned long size = offsetof(struct sync_fence, cbs[num_fences]);
+ unsigned long size = offsetof(struct sync_file, cbs[num_fences]);
- fence = sync_fence_alloc(size, name);
- if (!fence)
+ sync_file = sync_file_alloc(size, name);
+ if (!sync_file)
return NULL;
- atomic_set(&fence->status, num_fences);
+ atomic_set(&sync_file->status, num_fences);
/*
- * Assume sync_fence a and b are both ordered and have no
+ * Assume sync_file a and b are both ordered and have no
* duplicates with the same context.
*
- * If a sync_fence can only be created with sync_fence_merge
- * and sync_fence_create, this is a reasonable assumption.
+ * If a sync_file can only be created with sync_file_merge
+ * and sync_file_create, this is a reasonable assumption.
*/
for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) {
- struct fence *pt_a = a->cbs[i_a].sync_pt;
- struct fence *pt_b = b->cbs[i_b].sync_pt;
+ struct fence *pt_a = a->cbs[i_a].fence;
+ struct fence *pt_b = b->cbs[i_b].fence;
if (pt_a->context < pt_b->context) {
- sync_fence_add_pt(fence, &i, pt_a);
+ sync_file_add_pt(sync_file, &i, pt_a);
i_a++;
} else if (pt_a->context > pt_b->context) {
- sync_fence_add_pt(fence, &i, pt_b);
+ sync_file_add_pt(sync_file, &i, pt_b);
i_b++;
} else {
if (pt_a->seqno - pt_b->seqno <= INT_MAX)
- sync_fence_add_pt(fence, &i, pt_a);
+ sync_file_add_pt(sync_file, &i, pt_a);
else
- sync_fence_add_pt(fence, &i, pt_b);
+ sync_file_add_pt(sync_file, &i, pt_b);
i_a++;
i_b++;
}
for (; i_a < a->num_fences; i_a++)
- sync_fence_add_pt(fence, &i, a->cbs[i_a].sync_pt);
+ sync_file_add_pt(sync_file, &i, a->cbs[i_a].fence);
for (; i_b < b->num_fences; i_b++)
- sync_fence_add_pt(fence, &i, b->cbs[i_b].sync_pt);
+ sync_file_add_pt(sync_file, &i, b->cbs[i_b].fence);
if (num_fences > i)
- atomic_sub(num_fences - i, &fence->status);
- fence->num_fences = i;
-
- sync_fence_debug_add(fence);
- return fence;
-}
-EXPORT_SYMBOL(sync_fence_merge);
-
-int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode,
- int wake_flags, void *key)
-{
- struct sync_fence_waiter *wait;
-
- wait = container_of(curr, struct sync_fence_waiter, work);
- list_del_init(&wait->work.task_list);
-
- wait->callback(wait->work.private, wait);
- return 1;
-}
-
-int sync_fence_wait_async(struct sync_fence *fence,
- struct sync_fence_waiter *waiter)
-{
- int err = atomic_read(&fence->status);
- unsigned long flags;
-
- if (err < 0)
- return err;
-
- if (!err)
- return 1;
-
- init_waitqueue_func_entry(&waiter->work, sync_fence_wake_up_wq);
- waiter->work.private = fence;
-
- spin_lock_irqsave(&fence->wq.lock, flags);
- err = atomic_read(&fence->status);
- if (err > 0)
- __add_wait_queue_tail(&fence->wq, &waiter->work);
- spin_unlock_irqrestore(&fence->wq.lock, flags);
-
- if (err < 0)
- return err;
-
- return !err;
-}
-EXPORT_SYMBOL(sync_fence_wait_async);
-
-int sync_fence_cancel_async(struct sync_fence *fence,
- struct sync_fence_waiter *waiter)
-{
- unsigned long flags;
- int ret = 0;
-
- spin_lock_irqsave(&fence->wq.lock, flags);
- if (!list_empty(&waiter->work.task_list))
- list_del_init(&waiter->work.task_list);
- else
- ret = -ENOENT;
- spin_unlock_irqrestore(&fence->wq.lock, flags);
- return ret;
-}
-EXPORT_SYMBOL(sync_fence_cancel_async);
-
-int sync_fence_wait(struct sync_fence *fence, long timeout)
-{
- long ret;
- int i;
+ atomic_sub(num_fences - i, &sync_file->status);
+ sync_file->num_fences = i;
- if (timeout < 0)
- timeout = MAX_SCHEDULE_TIMEOUT;
- else
- timeout = msecs_to_jiffies(timeout);
-
- trace_sync_wait(fence, 1);
- for (i = 0; i < fence->num_fences; ++i)
- trace_sync_pt(fence->cbs[i].sync_pt);
- ret = wait_event_interruptible_timeout(fence->wq,
- atomic_read(&fence->status) <= 0,
- timeout);
- trace_sync_wait(fence, 0);
-
- if (ret < 0) {
- return ret;
- } else if (ret == 0) {
- if (timeout) {
- pr_info("fence timeout on [%p] after %dms\n", fence,
- jiffies_to_msecs(timeout));
- sync_dump();
- }
- return -ETIME;
- }
-
- ret = atomic_read(&fence->status);
- if (ret) {
- pr_info("fence error %ld on [%p]\n", ret, fence);
- sync_dump();
- }
- return ret;
+ sync_file_debug_add(sync_file);
+ return sync_file;
}
-EXPORT_SYMBOL(sync_fence_wait);
+EXPORT_SYMBOL(sync_file_merge);
static const char *android_fence_get_driver_name(struct fence *fence)
{
- struct sync_pt *pt = container_of(fence, struct sync_pt, base);
- struct sync_timeline *parent = sync_pt_parent(pt);
+ struct sync_timeline *parent = fence_parent(fence);
return parent->ops->driver_name;
}
static const char *android_fence_get_timeline_name(struct fence *fence)
{
- struct sync_pt *pt = container_of(fence, struct sync_pt, base);
- struct sync_timeline *parent = sync_pt_parent(pt);
+ struct sync_timeline *parent = fence_parent(fence);
return parent->name;
}
static void android_fence_release(struct fence *fence)
{
- struct sync_pt *pt = container_of(fence, struct sync_pt, base);
- struct sync_timeline *parent = sync_pt_parent(pt);
+ struct sync_timeline *parent = fence_parent(fence);
unsigned long flags;
spin_lock_irqsave(fence->lock, flags);
- list_del(&pt->child_list);
- if (WARN_ON_ONCE(!list_empty(&pt->active_list)))
- list_del(&pt->active_list);
+ list_del(&fence->child_list);
+ if (WARN_ON_ONCE(!list_empty(&fence->active_list)))
+ list_del(&fence->active_list);
spin_unlock_irqrestore(fence->lock, flags);
- if (parent->ops->free_pt)
- parent->ops->free_pt(pt);
-
sync_timeline_put(parent);
- fence_free(&pt->base);
+ fence_free(fence);
}
static bool android_fence_signaled(struct fence *fence)
{
- struct sync_pt *pt = container_of(fence, struct sync_pt, base);
- struct sync_timeline *parent = sync_pt_parent(pt);
+ struct sync_timeline *parent = fence_parent(fence);
int ret;
- ret = parent->ops->has_signaled(pt);
+ ret = parent->ops->has_signaled(fence);
if (ret < 0)
fence->status = ret;
return ret;
static bool android_fence_enable_signaling(struct fence *fence)
{
- struct sync_pt *pt = container_of(fence, struct sync_pt, base);
- struct sync_timeline *parent = sync_pt_parent(pt);
+ struct sync_timeline *parent = fence_parent(fence);
if (android_fence_signaled(fence))
return false;
- list_add_tail(&pt->active_list, &parent->active_list_head);
+ list_add_tail(&fence->active_list, &parent->active_list_head);
return true;
}
-static int android_fence_fill_driver_data(struct fence *fence,
- void *data, int size)
-{
- struct sync_pt *pt = container_of(fence, struct sync_pt, base);
- struct sync_timeline *parent = sync_pt_parent(pt);
-
- if (!parent->ops->fill_driver_data)
- return 0;
- return parent->ops->fill_driver_data(pt, data, size);
-}
-
static void android_fence_value_str(struct fence *fence,
char *str, int size)
{
- struct sync_pt *pt = container_of(fence, struct sync_pt, base);
- struct sync_timeline *parent = sync_pt_parent(pt);
+ struct sync_timeline *parent = fence_parent(fence);
- if (!parent->ops->pt_value_str) {
+ if (!parent->ops->fence_value_str) {
if (size)
*str = 0;
return;
}
- parent->ops->pt_value_str(pt, str, size);
+ parent->ops->fence_value_str(fence, str, size);
}
static void android_fence_timeline_value_str(struct fence *fence,
char *str, int size)
{
- struct sync_pt *pt = container_of(fence, struct sync_pt, base);
- struct sync_timeline *parent = sync_pt_parent(pt);
+ struct sync_timeline *parent = fence_parent(fence);
if (!parent->ops->timeline_value_str) {
if (size)
.signaled = android_fence_signaled,
.wait = fence_default_wait,
.release = android_fence_release,
- .fill_driver_data = android_fence_fill_driver_data,
.fence_value_str = android_fence_value_str,
.timeline_value_str = android_fence_timeline_value_str,
};
-static void sync_fence_free(struct kref *kref)
+static void sync_file_free(struct kref *kref)
{
- struct sync_fence *fence = container_of(kref, struct sync_fence, kref);
+ struct sync_file *sync_file = container_of(kref, struct sync_file,
+ kref);
int i;
- for (i = 0; i < fence->num_fences; ++i) {
- fence_remove_callback(fence->cbs[i].sync_pt, &fence->cbs[i].cb);
- fence_put(fence->cbs[i].sync_pt);
+ for (i = 0; i < sync_file->num_fences; ++i) {
+ fence_remove_callback(sync_file->cbs[i].fence,
+ &sync_file->cbs[i].cb);
+ fence_put(sync_file->cbs[i].fence);
}
- kfree(fence);
+ kfree(sync_file);
}
-static int sync_fence_release(struct inode *inode, struct file *file)
+static int sync_file_release(struct inode *inode, struct file *file)
{
- struct sync_fence *fence = file->private_data;
+ struct sync_file *sync_file = file->private_data;
- sync_fence_debug_remove(fence);
+ sync_file_debug_remove(sync_file);
- kref_put(&fence->kref, sync_fence_free);
+ kref_put(&sync_file->kref, sync_file_free);
return 0;
}
-static unsigned int sync_fence_poll(struct file *file, poll_table *wait)
+static unsigned int sync_file_poll(struct file *file, poll_table *wait)
{
- struct sync_fence *fence = file->private_data;
+ struct sync_file *sync_file = file->private_data;
int status;
- poll_wait(file, &fence->wq, wait);
+ poll_wait(file, &sync_file->wq, wait);
- status = atomic_read(&fence->status);
+ status = atomic_read(&sync_file->status);
if (!status)
return POLLIN;
return 0;
}
-static long sync_fence_ioctl_wait(struct sync_fence *fence, unsigned long arg)
-{
- __s32 value;
-
- if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
- return -EFAULT;
-
- return sync_fence_wait(fence, value);
-}
-
-static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg)
+static long sync_file_ioctl_merge(struct sync_file *sync_file,
+ unsigned long arg)
{
int fd = get_unused_fd_flags(O_CLOEXEC);
int err;
- struct sync_fence *fence2, *fence3;
+ struct sync_file *fence2, *fence3;
struct sync_merge_data data;
if (fd < 0)
goto err_put_fd;
}
- fence2 = sync_fence_fdget(data.fd2);
+ fence2 = sync_file_fdget(data.fd2);
if (!fence2) {
err = -ENOENT;
goto err_put_fd;
}
data.name[sizeof(data.name) - 1] = '\0';
- fence3 = sync_fence_merge(data.name, fence, fence2);
+ fence3 = sync_file_merge(data.name, sync_file, fence2);
if (!fence3) {
err = -ENOMEM;
goto err_put_fence2;
goto err_put_fence3;
}
- sync_fence_install(fence3, fd);
- sync_fence_put(fence2);
+ sync_file_install(fence3, fd);
+ sync_file_put(fence2);
return 0;
err_put_fence3:
- sync_fence_put(fence3);
+ sync_file_put(fence3);
err_put_fence2:
- sync_fence_put(fence2);
+ sync_file_put(fence2);
err_put_fd:
put_unused_fd(fd);
return err;
}
-static int sync_fill_pt_info(struct fence *fence, void *data, int size)
+static int sync_fill_fence_info(struct fence *fence, void *data, int size)
{
- struct sync_pt_info *info = data;
- int ret;
+ struct sync_fence_info *info = data;
- if (size < sizeof(struct sync_pt_info))
+ if (size < sizeof(*info))
return -ENOMEM;
- info->len = sizeof(struct sync_pt_info);
-
- if (fence->ops->fill_driver_data) {
- ret = fence->ops->fill_driver_data(fence, info->driver_data,
- size - sizeof(*info));
- if (ret < 0)
- return ret;
-
- info->len += ret;
- }
-
strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
sizeof(info->obj_name));
strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
info->status = 0;
info->timestamp_ns = ktime_to_ns(fence->timestamp);
- return info->len;
+ return sizeof(*info);
}
-static long sync_fence_ioctl_fence_info(struct sync_fence *fence,
+static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
unsigned long arg)
{
- struct sync_fence_info_data *data;
+ struct sync_file_info *info;
__u32 size;
__u32 len = 0;
int ret, i;
if (copy_from_user(&size, (void __user *)arg, sizeof(size)))
return -EFAULT;
- if (size < sizeof(struct sync_fence_info_data))
+ if (size < sizeof(struct sync_file_info))
return -EINVAL;
if (size > 4096)
size = 4096;
- data = kzalloc(size, GFP_KERNEL);
- if (!data)
+ info = kzalloc(size, GFP_KERNEL);
+ if (!info)
return -ENOMEM;
- strlcpy(data->name, fence->name, sizeof(data->name));
- data->status = atomic_read(&fence->status);
- if (data->status >= 0)
- data->status = !data->status;
+ strlcpy(info->name, sync_file->name, sizeof(info->name));
+ info->status = atomic_read(&sync_file->status);
+ if (info->status >= 0)
+ info->status = !info->status;
- len = sizeof(struct sync_fence_info_data);
+ len = sizeof(struct sync_file_info);
- for (i = 0; i < fence->num_fences; ++i) {
- struct fence *pt = fence->cbs[i].sync_pt;
+ for (i = 0; i < sync_file->num_fences; ++i) {
+ struct fence *fence = sync_file->cbs[i].fence;
- ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len);
+ ret = sync_fill_fence_info(fence, (u8 *)info + len, size - len);
if (ret < 0)
goto out;
len += ret;
}
- data->len = len;
+ info->len = len;
- if (copy_to_user((void __user *)arg, data, len))
+ if (copy_to_user((void __user *)arg, info, len))
ret = -EFAULT;
else
ret = 0;
out:
- kfree(data);
+ kfree(info);
return ret;
}
-static long sync_fence_ioctl(struct file *file, unsigned int cmd,
+static long sync_file_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
- struct sync_fence *fence = file->private_data;
+ struct sync_file *sync_file = file->private_data;
switch (cmd) {
- case SYNC_IOC_WAIT:
- return sync_fence_ioctl_wait(fence, arg);
-
case SYNC_IOC_MERGE:
- return sync_fence_ioctl_merge(fence, arg);
+ return sync_file_ioctl_merge(sync_file, arg);
case SYNC_IOC_FENCE_INFO:
- return sync_fence_ioctl_fence_info(fence, arg);
+ return sync_file_ioctl_fence_info(sync_file, arg);
default:
return -ENOTTY;
}
}
-static const struct file_operations sync_fence_fops = {
- .release = sync_fence_release,
- .poll = sync_fence_poll,
- .unlocked_ioctl = sync_fence_ioctl,
- .compat_ioctl = sync_fence_ioctl,
+static const struct file_operations sync_file_fops = {
+ .release = sync_file_release,
+ .poll = sync_file_poll,
+ .unlocked_ioctl = sync_file_ioctl,
+ .compat_ioctl = sync_file_ioctl,
};
#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/spinlock.h>
-#include <linux/wait.h>
#include <linux/fence.h>
#include "uapi/sync.h"
struct sync_timeline;
-struct sync_pt;
-struct sync_fence;
+struct sync_file;
/**
* struct sync_timeline_ops - sync object implementation ops
* @driver_name: name of the implementation
- * @dup: duplicate a sync_pt
* @has_signaled: returns:
* 1 if pt has signaled
* 0 if pt has not signaled
* <0 on error
- * @compare: returns:
- * 1 if b will signal before a
- * 0 if a and b will signal at the same time
- * -1 if a will signal before b
- * @free_pt: called before sync_pt is freed
- * @release_obj: called before sync_timeline is freed
- * @fill_driver_data: write implementation specific driver data to data.
- * should return an error if there is not enough room
- * as specified by size. This information is returned
- * to userspace by SYNC_IOC_FENCE_INFO.
* @timeline_value_str: fill str with the value of the sync_timeline's counter
- * @pt_value_str: fill str with the value of the sync_pt
+ * @fence_value_str: fill str with the value of the fence
*/
struct sync_timeline_ops {
const char *driver_name;
/* required */
- struct sync_pt * (*dup)(struct sync_pt *pt);
-
- /* required */
- int (*has_signaled)(struct sync_pt *pt);
-
- /* required */
- int (*compare)(struct sync_pt *a, struct sync_pt *b);
-
- /* optional */
- void (*free_pt)(struct sync_pt *sync_pt);
-
- /* optional */
- void (*release_obj)(struct sync_timeline *sync_timeline);
-
- /* optional */
- int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size);
+ int (*has_signaled)(struct fence *fence);
/* optional */
void (*timeline_value_str)(struct sync_timeline *timeline, char *str,
int size);
/* optional */
- void (*pt_value_str)(struct sync_pt *pt, char *str, int size);
+ void (*fence_value_str)(struct fence *fence, char *str, int size);
};
/**
* @destroyed: set when sync_timeline is destroyed
* @child_list_head: list of children sync_pts for this sync_timeline
* @child_list_lock: lock protecting @child_list_head, destroyed, and
- * sync_pt.status
+ * fence.status
* @active_list_head: list of active (unsignaled/errored) sync_pts
* @sync_timeline_list: membership in global sync_timeline_list
*/
#endif
};
-/**
- * struct sync_pt - sync point
- * @fence: base fence class
- * @child_list: membership in sync_timeline.child_list_head
- * @active_list: membership in sync_timeline.active_list_head
- * @signaled_list: membership in temporary signaled_list on stack
- * @fence: sync_fence to which the sync_pt belongs
- * @pt_list: membership in sync_fence.pt_list_head
- * @status: 1: signaled, 0:active, <0: error
- * @timestamp: time which sync_pt status transitioned from active to
- * signaled or error.
- */
-struct sync_pt {
- struct fence base;
-
- struct list_head child_list;
- struct list_head active_list;
-};
-
-static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt)
+static inline struct sync_timeline *fence_parent(struct fence *fence)
{
- return container_of(pt->base.lock, struct sync_timeline,
+ return container_of(fence->lock, struct sync_timeline,
child_list_lock);
}
-struct sync_fence_cb {
+struct sync_file_cb {
struct fence_cb cb;
- struct fence *sync_pt;
- struct sync_fence *fence;
+ struct fence *fence;
+ struct sync_file *sync_file;
};
/**
- * struct sync_fence - sync fence
+ * struct sync_file - sync file to export to the userspace
* @file: file representing this fence
* @kref: reference count on fence.
- * @name: name of sync_fence. Useful for debugging
- * @pt_list_head: list of sync_pts in the fence. immutable once fence
- * is created
- * @status: 0: signaled, >0:active, <0: error
- *
+ * @name: name of sync_file. Useful for debugging
+ * @sync_file_list: membership in global file list
+ * @num_fences number of sync_pts in the fence
* @wq: wait queue for fence signaling
- * @sync_fence_list: membership in global fence list
+ * @status: 0: signaled, >0:active, <0: error
+ * @cbs: sync_pts callback information
*/
-struct sync_fence {
+struct sync_file {
struct file *file;
struct kref kref;
char name[32];
#ifdef CONFIG_DEBUG_FS
- struct list_head sync_fence_list;
+ struct list_head sync_file_list;
#endif
int num_fences;
wait_queue_head_t wq;
atomic_t status;
- struct sync_fence_cb cbs[];
-};
-
-struct sync_fence_waiter;
-typedef void (*sync_callback_t)(struct sync_fence *fence,
- struct sync_fence_waiter *waiter);
-
-/**
- * struct sync_fence_waiter - metadata for asynchronous waiter on a fence
- * @waiter_list: membership in sync_fence.waiter_list_head
- * @callback: function pointer to call when fence signals
- * @callback_data: pointer to pass to @callback
- */
-struct sync_fence_waiter {
- wait_queue_t work;
- sync_callback_t callback;
+ struct sync_file_cb cbs[];
};
-static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter,
- sync_callback_t callback)
-{
- INIT_LIST_HEAD(&waiter->work.task_list);
- waiter->callback = callback;
-}
-
/*
* API for sync_timeline implementers
*/
*
* Creates a new sync_timeline which will use the implementation specified by
* @ops. @size bytes will be allocated allowing for implementation specific
- * data to be kept after the generic sync_timeline struct.
+ * data to be kept after the generic sync_timeline struct. Returns the
+ * sync_timeline object or NULL in case of error.
*/
struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
int size, const char *name);
*
* A sync implementation should call this when the @obj is going away
* (i.e. module unload.) @obj won't actually be freed until all its children
- * sync_pts are freed.
+ * fences are freed.
*/
void sync_timeline_destroy(struct sync_timeline *obj);
* sync_timeline_signal() - signal a status change on a sync_timeline
* @obj: sync_timeline to signal
*
- * A sync implementation should call this any time one of it's sync_pts
+ * A sync implementation should call this any time one of it's fences
* has signaled or has an error condition.
*/
void sync_timeline_signal(struct sync_timeline *obj);
/**
* sync_pt_create() - creates a sync pt
- * @parent: sync_pt's parent sync_timeline
+ * @parent: fence's parent sync_timeline
* @size: size to allocate for this pt
*
- * Creates a new sync_pt as a child of @parent. @size bytes will be
+ * Creates a new fence as a child of @parent. @size bytes will be
* allocated allowing for implementation specific data to be kept after
- * the generic sync_timeline struct.
- */
-struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size);
-
-/**
- * sync_pt_free() - frees a sync pt
- * @pt: sync_pt to free
- *
- * This should only be called on sync_pts which have been created but
- * not added to a fence.
+ * the generic sync_timeline struct. Returns the fence object or
+ * NULL in case of error.
*/
-void sync_pt_free(struct sync_pt *pt);
+struct fence *sync_pt_create(struct sync_timeline *parent, int size);
/**
* sync_fence_create() - creates a sync fence
* @name: name of fence to create
- * @pt: sync_pt to add to the fence
- *
- * Creates a fence containg @pt. Once this is called, the fence takes
- * ownership of @pt.
- */
-struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt);
-
-/**
- * sync_fence_create_dma() - creates a sync fence from dma-fence
- * @name: name of fence to create
- * @pt: dma-fence to add to the fence
+ * @fence: fence to add to the sync_fence
*
- * Creates a fence containg @pt. Once this is called, the fence takes
- * ownership of @pt.
+ * Creates a sync_file containg @fence. Once this is called, the sync_file
+ * takes ownership of @fence.
*/
-struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt);
+struct sync_file *sync_file_create(const char *name, struct fence *fence);
/*
- * API for sync_fence consumers
+ * API for sync_file consumers
*/
/**
- * sync_fence_merge() - merge two fences
+ * sync_file_merge() - merge two sync_files
* @name: name of new fence
- * @a: fence a
- * @b: fence b
+ * @a: sync_file a
+ * @b: sync_file b
*
- * Creates a new fence which contains copies of all the sync_pts in both
- * @a and @b. @a and @b remain valid, independent fences.
+ * Creates a new sync_file which contains copies of all the fences in both
+ * @a and @b. @a and @b remain valid, independent sync_file. Returns the
+ * new merged sync_file or NULL in case of error.
*/
-struct sync_fence *sync_fence_merge(const char *name,
- struct sync_fence *a, struct sync_fence *b);
+struct sync_file *sync_file_merge(const char *name,
+ struct sync_file *a, struct sync_file *b);
/**
- * sync_fence_fdget() - get a fence from an fd
+ * sync_file_fdget() - get a sync_file from an fd
* @fd: fd referencing a fence
*
- * Ensures @fd references a valid fence, increments the refcount of the backing
- * file, and returns the fence.
+ * Ensures @fd references a valid sync_file, increments the refcount of the
+ * backing file. Returns the sync_file or NULL in case of error.
*/
-struct sync_fence *sync_fence_fdget(int fd);
+struct sync_file *sync_file_fdget(int fd);
/**
- * sync_fence_put() - puts a reference of a sync fence
- * @fence: fence to put
+ * sync_file_put() - puts a reference of a sync_file
+ * @sync_file: sync_file to put
*
- * Puts a reference on @fence. If this is the last reference, the fence and
- * all it's sync_pts will be freed
+ * Puts a reference on @sync_fence. If this is the last reference, the
+ * sync_fil and all it's sync_pts will be freed
*/
-void sync_fence_put(struct sync_fence *fence);
+void sync_file_put(struct sync_file *sync_file);
/**
- * sync_fence_install() - installs a fence into a file descriptor
- * @fence: fence to install
+ * sync_file_install() - installs a sync_file into a file descriptor
+ * @sync_file: sync_file to install
* @fd: file descriptor in which to install the fence
*
- * Installs @fence into @fd. @fd's should be acquired through
+ * Installs @sync_file into @fd. @fd's should be acquired through
* get_unused_fd_flags(O_CLOEXEC).
*/
-void sync_fence_install(struct sync_fence *fence, int fd);
-
-/**
- * sync_fence_wait_async() - registers and async wait on the fence
- * @fence: fence to wait on
- * @waiter: waiter callback struck
- *
- * Returns 1 if @fence has already signaled.
- *
- * Registers a callback to be called when @fence signals or has an error.
- * @waiter should be initialized with sync_fence_waiter_init().
- */
-int sync_fence_wait_async(struct sync_fence *fence,
- struct sync_fence_waiter *waiter);
-
-/**
- * sync_fence_cancel_async() - cancels an async wait
- * @fence: fence to wait on
- * @waiter: waiter callback struck
- *
- * returns 0 if waiter was removed from fence's async waiter list.
- * returns -ENOENT if waiter was not found on fence's async waiter list.
- *
- * Cancels a previously registered async wait. Will fail gracefully if
- * @waiter was never registered or if @fence has already signaled @waiter.
- */
-int sync_fence_cancel_async(struct sync_fence *fence,
- struct sync_fence_waiter *waiter);
-
-/**
- * sync_fence_wait() - wait on fence
- * @fence: fence to wait on
- * @tiemout: timeout in ms
- *
- * Wait for @fence to be signaled or have an error. Waits indefinitely
- * if @timeout < 0
- */
-int sync_fence_wait(struct sync_fence *fence, long timeout);
+void sync_file_install(struct sync_file *sync_file, int fd);
#ifdef CONFIG_DEBUG_FS
void sync_timeline_debug_add(struct sync_timeline *obj);
void sync_timeline_debug_remove(struct sync_timeline *obj);
-void sync_fence_debug_add(struct sync_fence *fence);
-void sync_fence_debug_remove(struct sync_fence *fence);
+void sync_file_debug_add(struct sync_file *fence);
+void sync_file_debug_remove(struct sync_file *fence);
void sync_dump(void);
#else
# define sync_timeline_debug_add(obj)
# define sync_timeline_debug_remove(obj)
-# define sync_fence_debug_add(fence)
-# define sync_fence_debug_remove(fence)
+# define sync_file_debug_add(fence)
+# define sync_file_debug_remove(fence)
# define sync_dump()
#endif
-int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode,
- int wake_flags, void *key);
#endif /* _LINUX_SYNC_H */
*/
#include <linux/debugfs.h>
+#include <linux/module.h>
#include <linux/export.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/anon_inodes.h>
#include <linux/time64.h>
-#include "sync.h"
+#include "sw_sync.h"
#ifdef CONFIG_DEBUG_FS
+static struct dentry *dbgfs;
+
static LIST_HEAD(sync_timeline_list_head);
static DEFINE_SPINLOCK(sync_timeline_list_lock);
-static LIST_HEAD(sync_fence_list_head);
-static DEFINE_SPINLOCK(sync_fence_list_lock);
+static LIST_HEAD(sync_file_list_head);
+static DEFINE_SPINLOCK(sync_file_list_lock);
void sync_timeline_debug_add(struct sync_timeline *obj)
{
spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
}
-void sync_fence_debug_add(struct sync_fence *fence)
+void sync_file_debug_add(struct sync_file *sync_file)
{
unsigned long flags;
- spin_lock_irqsave(&sync_fence_list_lock, flags);
- list_add_tail(&fence->sync_fence_list, &sync_fence_list_head);
- spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+ spin_lock_irqsave(&sync_file_list_lock, flags);
+ list_add_tail(&sync_file->sync_file_list, &sync_file_list_head);
+ spin_unlock_irqrestore(&sync_file_list_lock, flags);
}
-void sync_fence_debug_remove(struct sync_fence *fence)
+void sync_file_debug_remove(struct sync_file *sync_file)
{
unsigned long flags;
- spin_lock_irqsave(&sync_fence_list_lock, flags);
- list_del(&fence->sync_fence_list);
- spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+ spin_lock_irqsave(&sync_file_list_lock, flags);
+ list_del(&sync_file->sync_file_list);
+ spin_unlock_irqrestore(&sync_file_list_lock, flags);
}
static const char *sync_status_str(int status)
return "error";
}
-static void sync_print_pt(struct seq_file *s, struct fence *pt, bool fence)
+static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show)
{
int status = 1;
+ struct sync_timeline *parent = fence_parent(fence);
- if (fence_is_signaled_locked(pt))
- status = pt->status;
+ if (fence_is_signaled_locked(fence))
+ status = fence->status;
- seq_printf(s, " %s%spt %s",
- fence && pt->ops->get_timeline_name ?
- pt->ops->get_timeline_name(pt) : "",
- fence ? "_" : "",
+ seq_printf(s, " %s%sfence %s",
+ show ? parent->name : "",
+ show ? "_" : "",
sync_status_str(status));
if (status <= 0) {
struct timespec64 ts64 =
- ktime_to_timespec64(pt->timestamp);
+ ktime_to_timespec64(fence->timestamp);
seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec);
}
- if ((!fence || pt->ops->timeline_value_str) &&
- pt->ops->fence_value_str) {
+ if ((!fence || fence->ops->timeline_value_str) &&
+ fence->ops->fence_value_str) {
char value[64];
bool success;
- pt->ops->fence_value_str(pt, value, sizeof(value));
+ fence->ops->fence_value_str(fence, value, sizeof(value));
success = strlen(value);
if (success)
seq_printf(s, ": %s", value);
if (success && fence) {
- pt->ops->timeline_value_str(pt, value, sizeof(value));
+ fence->ops->timeline_value_str(fence, value,
+ sizeof(value));
if (strlen(value))
seq_printf(s, " / %s", value);
spin_lock_irqsave(&obj->child_list_lock, flags);
list_for_each(pos, &obj->child_list_head) {
- struct sync_pt *pt =
- container_of(pos, struct sync_pt, child_list);
- sync_print_pt(s, &pt->base, false);
+ struct fence *fence =
+ container_of(pos, struct fence, child_list);
+ sync_print_fence(s, fence, false);
}
spin_unlock_irqrestore(&obj->child_list_lock, flags);
}
-static void sync_print_fence(struct seq_file *s, struct sync_fence *fence)
+static void sync_print_sync_file(struct seq_file *s,
+ struct sync_file *sync_file)
{
- wait_queue_t *pos;
- unsigned long flags;
int i;
- seq_printf(s, "[%p] %s: %s\n", fence, fence->name,
- sync_status_str(atomic_read(&fence->status)));
-
- for (i = 0; i < fence->num_fences; ++i) {
- sync_print_pt(s, fence->cbs[i].sync_pt, true);
- }
-
- spin_lock_irqsave(&fence->wq.lock, flags);
- list_for_each_entry(pos, &fence->wq.task_list, task_list) {
- struct sync_fence_waiter *waiter;
-
- if (pos->func != &sync_fence_wake_up_wq)
- continue;
+ seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name,
+ sync_status_str(atomic_read(&sync_file->status)));
- waiter = container_of(pos, struct sync_fence_waiter, work);
-
- seq_printf(s, "waiter %pF\n", waiter->callback);
- }
- spin_unlock_irqrestore(&fence->wq.lock, flags);
+ for (i = 0; i < sync_file->num_fences; ++i)
+ sync_print_fence(s, sync_file->cbs[i].fence, true);
}
static int sync_debugfs_show(struct seq_file *s, void *unused)
seq_puts(s, "fences:\n--------------\n");
- spin_lock_irqsave(&sync_fence_list_lock, flags);
- list_for_each(pos, &sync_fence_list_head) {
- struct sync_fence *fence =
- container_of(pos, struct sync_fence, sync_fence_list);
+ spin_lock_irqsave(&sync_file_list_lock, flags);
+ list_for_each(pos, &sync_file_list_head) {
+ struct sync_file *sync_file =
+ container_of(pos, struct sync_file, sync_file_list);
- sync_print_fence(s, fence);
+ sync_print_sync_file(s, sync_file);
seq_puts(s, "\n");
}
- spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+ spin_unlock_irqrestore(&sync_file_list_lock, flags);
return 0;
}
-static int sync_debugfs_open(struct inode *inode, struct file *file)
+static int sync_info_debugfs_open(struct inode *inode, struct file *file)
{
return single_open(file, sync_debugfs_show, inode->i_private);
}
-static const struct file_operations sync_debugfs_fops = {
- .open = sync_debugfs_open,
+static const struct file_operations sync_info_debugfs_fops = {
+ .open = sync_info_debugfs_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
+/*
+ * *WARNING*
+ *
+ * improper use of this can result in deadlocking kernel drivers from userspace.
+ */
+
+/* opening sw_sync create a new sync obj */
+static int sw_sync_debugfs_open(struct inode *inode, struct file *file)
+{
+ struct sw_sync_timeline *obj;
+ char task_comm[TASK_COMM_LEN];
+
+ get_task_comm(task_comm, current);
+
+ obj = sw_sync_timeline_create(task_comm);
+ if (!obj)
+ return -ENOMEM;
+
+ file->private_data = obj;
+
+ return 0;
+}
+
+static int sw_sync_debugfs_release(struct inode *inode, struct file *file)
+{
+ struct sw_sync_timeline *obj = file->private_data;
+
+ sync_timeline_destroy(&obj->obj);
+ return 0;
+}
+
+static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj,
+ unsigned long arg)
+{
+ int fd = get_unused_fd_flags(O_CLOEXEC);
+ int err;
+ struct fence *fence;
+ struct sync_file *sync_file;
+ struct sw_sync_create_fence_data data;
+
+ if (fd < 0)
+ return fd;
+
+ if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
+ err = -EFAULT;
+ goto err;
+ }
+
+ fence = sw_sync_pt_create(obj, data.value);
+ if (!fence) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ data.name[sizeof(data.name) - 1] = '\0';
+ sync_file = sync_file_create(data.name, fence);
+ if (!sync_file) {
+ fence_put(fence);
+ err = -ENOMEM;
+ goto err;
+ }
+
+ data.fence = fd;
+ if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
+ sync_file_put(sync_file);
+ err = -EFAULT;
+ goto err;
+ }
+
+ sync_file_install(sync_file, fd);
+
+ return 0;
+
+err:
+ put_unused_fd(fd);
+ return err;
+}
+
+static long sw_sync_ioctl_inc(struct sw_sync_timeline *obj, unsigned long arg)
+{
+ u32 value;
+
+ if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+ return -EFAULT;
+
+ sw_sync_timeline_inc(obj, value);
+
+ return 0;
+}
+
+static long sw_sync_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sw_sync_timeline *obj = file->private_data;
+
+ switch (cmd) {
+ case SW_SYNC_IOC_CREATE_FENCE:
+ return sw_sync_ioctl_create_fence(obj, arg);
+
+ case SW_SYNC_IOC_INC:
+ return sw_sync_ioctl_inc(obj, arg);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+static const struct file_operations sw_sync_debugfs_fops = {
+ .open = sw_sync_debugfs_open,
+ .release = sw_sync_debugfs_release,
+ .unlocked_ioctl = sw_sync_ioctl,
+ .compat_ioctl = sw_sync_ioctl,
+};
+
static __init int sync_debugfs_init(void)
{
- debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops);
+ dbgfs = debugfs_create_dir("sync", NULL);
+
+ debugfs_create_file("info", 0444, dbgfs, NULL, &sync_info_debugfs_fops);
+ debugfs_create_file("sw_sync", 0644, dbgfs, NULL,
+ &sw_sync_debugfs_fops);
+
return 0;
}
late_initcall(sync_debugfs_init);
+static __exit void sync_debugfs_exit(void)
+{
+ if (dbgfs)
+ debugfs_remove_recursive(dbgfs);
+}
+module_exit(sync_debugfs_exit);
+
#define DUMP_CHUNK 256
static char sync_dump_buf[64 * 1024];
void sync_dump(void)
TP_printk("name=%s value=%s", __get_str(name), __entry->value)
);
-TRACE_EVENT(sync_wait,
- TP_PROTO(struct sync_fence *fence, int begin),
-
- TP_ARGS(fence, begin),
-
- TP_STRUCT__entry(
- __string(name, fence->name)
- __field(s32, status)
- __field(u32, begin)
- ),
-
- TP_fast_assign(
- __assign_str(name, fence->name);
- __entry->status = atomic_read(&fence->status);
- __entry->begin = begin;
- ),
-
- TP_printk("%s name=%s state=%d", __entry->begin ? "begin" : "end",
- __get_str(name), __entry->status)
-);
-
-TRACE_EVENT(sync_pt,
- TP_PROTO(struct fence *pt),
-
- TP_ARGS(pt),
-
- TP_STRUCT__entry(
- __string(timeline, pt->ops->get_timeline_name(pt))
- __array(char, value, 32)
- ),
-
- TP_fast_assign(
- __assign_str(timeline, pt->ops->get_timeline_name(pt));
- if (pt->ops->fence_value_str) {
- pt->ops->fence_value_str(pt, __entry->value,
- sizeof(__entry->value));
- } else {
- __entry->value[0] = '\0';
- }
- ),
-
- TP_printk("name=%s value=%s", __get_str(timeline), __entry->value)
-);
-
#endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */
/* This part must be outside protection */
#define _UAPI_LINUX_ASHMEM_H
#include <linux/ioctl.h>
+#include <linux/types.h>
#define ASHMEM_NAME_LEN 256
};
/**
- * struct sync_pt_info - detailed sync_pt information
- * @len: length of sync_pt_info including any driver_data
+ * struct sync_fence_info - detailed fence information
* @obj_name: name of parent sync_timeline
* @driver_name: name of driver implementing the parent
- * @status: status of the sync_pt 0:active 1:signaled <0:error
+ * @status: status of the fence 0:active 1:signaled <0:error
* @timestamp_ns: timestamp of status change in nanoseconds
- * @driver_data: any driver dependent data
*/
-struct sync_pt_info {
- __u32 len;
+struct sync_fence_info {
char obj_name[32];
char driver_name[32];
__s32 status;
__u64 timestamp_ns;
-
- __u8 driver_data[0];
};
/**
- * struct sync_fence_info_data - data returned from fence info ioctl
+ * struct sync_file_info - data returned from fence info ioctl
* @len: ioctl caller writes the size of the buffer its passing in.
- * ioctl returns length of sync_fence_data returned to userspace
- * including pt_info.
+ * ioctl returns length of sync_file_info returned to
+ * userspace including pt_info.
* @name: name of fence
* @status: status of fence. 1: signaled 0:active <0:error
- * @pt_info: a sync_pt_info struct for every sync_pt in the fence
+ * @sync_fence_info: array of sync_fence_info for every fence in the sync_file
*/
-struct sync_fence_info_data {
+struct sync_file_info {
__u32 len;
char name[32];
__s32 status;
- __u8 pt_info[0];
+ __u8 sync_fence_info[0];
};
#define SYNC_IOC_MAGIC '>'
-/**
- * DOC: SYNC_IOC_WAIT - wait for a fence to signal
- *
- * pass timeout in milliseconds. Waits indefinitely timeout < 0.
- */
-#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
-
/**
* DOC: SYNC_IOC_MERGE - merge two fences
*
/**
* DOC: SYNC_IOC_FENCE_INFO - get detailed information on a fence
*
- * Takes a struct sync_fence_info_data with extra space allocated for pt_info.
+ * Takes a struct sync_file_info_data with extra space allocated for pt_info.
* Caller should write the size of the buffer into len. On return, len is
- * updated to reflect the total size of the sync_fence_info_data including
+ * updated to reflect the total size of the sync_file_info_data including
* pt_info.
*
* pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence.
* To iterate over the sync_pt_infos, use the sync_pt_info.len field.
*/
-#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\
- struct sync_fence_info_data)
+#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2, struct sync_file_info)
#endif /* _UAPI_LINUX_SYNC_H */
#include "board.h"
-
static struct fb_videomode lcdc0_mode = {
.name = "AMPIER/AM-800480",
.xres = 800,
if (IS_ERR(pd)) {
pr_err("Cannot find genpd %s (%ld)\n", domain, PTR_ERR(pd));
return PTR_ERR(pd);
-
}
pr_debug("Found genpd %s for device %s\n", pd->name, pdev->name);
#define WZRD_CLK_CFG_REG(n) (0x200 + 4 * (n))
-#define WZRD_CLkOUT0_FRAC_EN BIT(18)
-#define WZRD_CLkFBOUT_FRAC_EN BIT(26)
+#define WZRD_CLKOUT0_FRAC_EN BIT(18)
+#define WZRD_CLKFBOUT_FRAC_EN BIT(26)
#define WZRD_CLKFBOUT_MULT_SHIFT 8
#define WZRD_CLKFBOUT_MULT_MASK (0xff << WZRD_CLKFBOUT_MULT_SHIFT)
int speed_grade;
bool suspended;
};
+
#define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb)
/* maximum frequencies for input/output clocks per speed grade */
/* we don't support fractional div/mul yet */
reg = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)) &
- WZRD_CLkFBOUT_FRAC_EN;
+ WZRD_CLKFBOUT_FRAC_EN;
reg |= readl(clk_wzrd->base + WZRD_CLK_CFG_REG(2)) &
- WZRD_CLkOUT0_FRAC_EN;
+ WZRD_CLKOUT0_FRAC_EN;
if (reg)
dev_warn(&pdev->dev, "fractional div/mul not supported\n");
#define UNIT_mA 1
#define UNIT_none 2
-#define COMEDI_MIN_SPEED ((unsigned int)0xffffffff)
+#define COMEDI_MIN_SPEED 0xffffffffu
/**********************************************************/
/* everything after this line is ALPHA */
struct pcmcia_driver *);
/**
- * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver
+ * module_comedi_pcmcia_driver() - Helper macro for registering a comedi
+ * PCMCIA driver
* @__comedi_driver: comedi_driver struct
* @__pcmcia_driver: pcmcia_driver struct
*
/* Command modifiers (only used with read/write), EXTTRIG can be
used with some other commands.
*/
-#define DT_MOD_DMA (1<<4)
-#define DT_MOD_CONT (1<<5)
-#define DT_MOD_EXTCLK (1<<6)
-#define DT_MOD_EXTTRIG (1<<7)
+#define DT_MOD_DMA BIT(4)
+#define DT_MOD_CONT BIT(5)
+#define DT_MOD_EXTCLK BIT(6)
+#define DT_MOD_EXTTRIG BIT(7)
/* Bits in status register */
-#define DT_S_DATA_OUT_READY (1<<0)
-#define DT_S_DATA_IN_FULL (1<<1)
-#define DT_S_READY (1<<2)
-#define DT_S_COMMAND (1<<3)
-#define DT_S_COMPOSITE_ERROR (1<<7)
+#define DT_S_DATA_OUT_READY BIT(0)
+#define DT_S_DATA_IN_FULL BIT(1)
+#define DT_S_READY BIT(2)
+#define DT_S_COMMAND BIT(3)
+#define DT_S_COMPOSITE_ERROR BIT(7)
/* registers */
#define DT2801_DATA 0
{
struct comedi_async *async = s->async;
unsigned int n_links;
- int i;
if (ring->descriptors) {
dma_free_coherent(ring->hw_dev,
}
ring->n_links = n_links;
- for (i = 0; i < n_links; i++) {
+ return mite_init_ring_descriptors(ring, s, n_links << PAGE_SHIFT);
+}
+EXPORT_SYMBOL_GPL(mite_buf_change);
+
+/*
+ * initializes the ring buffer descriptors to provide correct DMA transfer links
+ * to the exact amount of memory required. When the ring buffer is allocated in
+ * mite_buf_change, the default is to initialize the ring to refer to the entire
+ * DMA data buffer. A command may call this function later to re-initialize and
+ * shorten the amount of memory that will be transferred.
+ */
+int mite_init_ring_descriptors(struct mite_dma_descriptor_ring *ring,
+ struct comedi_subdevice *s,
+ unsigned int nbytes)
+{
+ struct comedi_async *async = s->async;
+ unsigned int n_full_links = nbytes >> PAGE_SHIFT;
+ unsigned int remainder = nbytes % PAGE_SIZE;
+ int i;
+
+ dev_dbg(s->device->class_dev,
+ "mite: init ring buffer to %u bytes\n", nbytes);
+
+ if ((n_full_links + (remainder > 0 ? 1 : 0)) > ring->n_links) {
+ dev_err(s->device->class_dev,
+ "mite: ring buffer too small for requested init\n");
+ return -ENOMEM;
+ }
+
+ /* We set the descriptors for all full links. */
+ for (i = 0; i < n_full_links; ++i) {
ring->descriptors[i].count = cpu_to_le32(PAGE_SIZE);
ring->descriptors[i].addr =
cpu_to_le32(async->buf_map->page_list[i].dma_addr);
ring->descriptors[i].next =
- cpu_to_le32(ring->descriptors_dma_addr + (i +
- 1) *
- sizeof(struct mite_dma_descriptor));
+ cpu_to_le32(ring->descriptors_dma_addr +
+ (i + 1) * sizeof(struct mite_dma_descriptor));
}
- ring->descriptors[n_links - 1].next =
- cpu_to_le32(ring->descriptors_dma_addr);
+
+ /* the last link is either a remainder or was a full link. */
+ if (remainder > 0) {
+ /* set the lesser count for the remainder link */
+ ring->descriptors[i].count = cpu_to_le32(remainder);
+ ring->descriptors[i].addr =
+ cpu_to_le32(async->buf_map->page_list[i].dma_addr);
+ /* increment i so that assignment below refs last link */
+ ++i;
+ }
+
+ /* Assign the last link->next to point back to the head of the list. */
+ ring->descriptors[i - 1].next = cpu_to_le32(ring->descriptors_dma_addr);
+
/*
* barrier is meant to insure that all the writes to the dma descriptors
* have completed before the dma controller is commanded to read them
smp_wmb();
return 0;
}
-EXPORT_SYMBOL_GPL(mite_buf_change);
+EXPORT_SYMBOL_GPL(mite_init_ring_descriptors);
void mite_prep_dma(struct mite_channel *mite_chan,
unsigned int num_device_bits, unsigned int num_memory_bits)
unsigned int old_alloc_count = async->buf_read_alloc_count;
u32 nbytes_ub, nbytes_lb;
int count;
+ bool finite_regen = (cmd->stop_src == TRIG_NONE && stop_count != 0);
/* read alloc as much as we can */
comedi_buf_read_alloc(s, async->prealloc_bufsz);
nbytes_ub = mite_bytes_read_from_memory_ub(mite_chan);
if (cmd->stop_src == TRIG_COUNT && (int)(nbytes_ub - stop_count) > 0)
nbytes_ub = stop_count;
- if ((int)(nbytes_ub - old_alloc_count) > 0) {
+
+ if ((!finite_regen || stop_count > old_alloc_count) &&
+ ((int)(nbytes_ub - old_alloc_count) > 0)) {
dev_warn(s->device->class_dev, "mite: DMA underrun\n");
async->events |= COMEDI_CB_OVERFLOW;
return -1;
}
+
+ if (finite_regen) {
+ /*
+ * This is a special case where we continuously output a finite
+ * buffer. In this case, we do not free any of the memory,
+ * hence we expect that old_alloc_count will reach a maximum of
+ * stop_count bytes.
+ */
+ return 0;
+ }
+
count = nbytes_lb - async->buf_read_count;
if (count <= 0)
return 0;
unsigned int num_device_bits, unsigned int num_memory_bits);
int mite_buf_change(struct mite_dma_descriptor_ring *ring,
struct comedi_subdevice *s);
+int mite_init_ring_descriptors(struct mite_dma_descriptor_ring *ring,
+ struct comedi_subdevice *s,
+ unsigned int nbytes);
enum mite_registers {
/*
s->async->events |= COMEDI_CB_OVERFLOW;
}
- if (b_status & NISTC_AO_STATUS1_BC_TC)
+ if (s->async->cmd.stop_src != TRIG_NONE &&
+ b_status & NISTC_AO_STATUS1_BC_TC)
s->async->events |= COMEDI_CB_EOA;
#ifndef PCIDMA
return devpriv->clock_ns * (timer + 1);
}
+static void ni_cmd_set_mite_transfer(struct mite_dma_descriptor_ring *ring,
+ struct comedi_subdevice *sdev,
+ const struct comedi_cmd *cmd,
+ unsigned int max_count) {
+#ifdef PCIDMA
+ unsigned int nbytes = max_count;
+
+ if (cmd->stop_arg > 0 && cmd->stop_arg < max_count)
+ nbytes = cmd->stop_arg;
+ nbytes *= comedi_bytes_per_scan(sdev);
+
+ if (nbytes > sdev->async->prealloc_bufsz) {
+ if (cmd->stop_arg > 0)
+ dev_err(sdev->device->class_dev,
+ "ni_cmd_set_mite_transfer: tried exact data transfer limits greater than buffer size\n");
+
+ /*
+ * we can only transfer up to the size of the buffer. In this
+ * case, the user is expected to continue to write into the
+ * comedi buffer (already implemented as a ring buffer).
+ */
+ nbytes = sdev->async->prealloc_bufsz;
+ }
+
+ mite_init_ring_descriptors(ring, sdev, nbytes);
+#else
+ dev_err(sdev->device->class_dev,
+ "ni_cmd_set_mite_transfer: exact data transfer limits not implemented yet without DMA\n");
+#endif
+}
+
static unsigned ni_min_ai_scan_period_ns(struct comedi_device *dev,
unsigned num_channels)
{
ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG);
break;
case TRIG_EXT:
- mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 + cmd->convert_arg);
+ mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 +
+ CR_CHAN(cmd->convert_arg));
if ((cmd->convert_arg & CR_INVERT) == 0)
mode1 |= NISTC_AI_MODE1_CONVERT_POLARITY;
ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG);
ni_stc_writew(dev, NISTC_AO_CMD1_UI_ARM |
NISTC_AO_CMD1_UC_ARM |
NISTC_AO_CMD1_BC_ARM |
- NISTC_AO_CMD1_DAC1_UPDATE_MODE |
- NISTC_AO_CMD1_DAC0_UPDATE_MODE |
devpriv->ao_cmd1,
NISTC_AO_CMD1_REG);
return 0;
}
-static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+/*
+ * begin ni_ao_cmd.
+ * Organized similar to NI-STC and MHDDK examples.
+ * ni_ao_cmd is broken out into configuration sub-routines for clarity.
+ */
+
+static void ni_ao_cmd_personalize(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
{
const struct ni_board_struct *board = dev->board_ptr;
- struct ni_private *devpriv = dev->private;
- const struct comedi_cmd *cmd = &s->async->cmd;
- int bits;
- int i;
- unsigned trigvar;
- unsigned val;
-
- if (dev->irq == 0) {
- dev_err(dev->class_dev, "cannot run command without an irq\n");
- return -EIO;
- }
+ unsigned bits;
ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
- ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG);
+ bits =
+ /* fast CPU interface--only eseries */
+ /* ((slow CPU interface) ? 0 : AO_Fast_CPU) | */
+ NISTC_AO_PERSONAL_BC_SRC_SEL |
+ 0 /* (use_original_pulse ? 0 : NISTC_AO_PERSONAL_UPDATE_TIMEBASE) */ |
+ /*
+ * FIXME: start setting following bit when appropriate. Need to
+ * determine whether board is E4 or E1.
+ * FROM MHHDK:
+ * if board is E4 or E1
+ * Set bit "NISTC_AO_PERSONAL_UPDATE_PW" to 0
+ * else
+ * set it to 1
+ */
+ NISTC_AO_PERSONAL_UPDATE_PW |
+ /* FIXME: when should we set following bit to zero? */
+ NISTC_AO_PERSONAL_TMRDACWR_PW |
+ (board->ao_fifo_depth ?
+ NISTC_AO_PERSONAL_FIFO_ENA : NISTC_AO_PERSONAL_DMA_PIO_CTRL)
+ ;
+#if 0
+ /*
+ * FIXME:
+ * add something like ".has_individual_dacs = 0" to ni_board_struct
+ * since, as F Hess pointed out, not all in m series have singles. not
+ * sure if e-series all have duals...
+ */
- if (devpriv->is_6xxx) {
- ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG,
- NI611X_AO_MISC_REG);
+ /*
+ * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit for
+ * 6281, verified with bus analyzer.
+ */
+ if (devpriv->is_m_series)
+ bits |= NISTC_AO_PERSONAL_NUM_DAC;
+#endif
+ ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG);
- bits = 0;
- for (i = 0; i < cmd->chanlist_len; i++) {
- int chan;
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
- chan = CR_CHAN(cmd->chanlist[i]);
- bits |= 1 << chan;
- ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG);
- }
- ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG);
- }
+static void ni_ao_cmd_set_trigger(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
+{
+ struct ni_private *devpriv = dev->private;
- ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+ /* sync */
if (cmd->stop_src == TRIG_NONE) {
devpriv->ao_mode1 |= NISTC_AO_MODE1_CONTINUOUS;
devpriv->ao_mode1 &= ~NISTC_AO_MODE1_TRIGGER_ONCE;
}
ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
- val = devpriv->ao_trigger_select;
- switch (cmd->start_src) {
- case TRIG_INT:
- case TRIG_NOW:
- val &= ~(NISTC_AO_TRIG_START1_POLARITY |
- NISTC_AO_TRIG_START1_SEL_MASK);
- val |= NISTC_AO_TRIG_START1_EDGE |
- NISTC_AO_TRIG_START1_SYNC;
- break;
- case TRIG_EXT:
- val = NISTC_AO_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + 1);
- if (cmd->start_arg & CR_INVERT) {
- /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */
- val |= NISTC_AO_TRIG_START1_POLARITY;
- }
- if (cmd->start_arg & CR_EDGE) {
- /* 0=edge detection disabled, 1=enabled */
- val |= NISTC_AO_TRIG_START1_EDGE;
+ {
+ unsigned int trigsel = devpriv->ao_trigger_select;
+
+ switch (cmd->start_src) {
+ case TRIG_INT:
+ case TRIG_NOW:
+ trigsel &= ~(NISTC_AO_TRIG_START1_POLARITY |
+ NISTC_AO_TRIG_START1_SEL_MASK);
+ trigsel |= NISTC_AO_TRIG_START1_EDGE |
+ NISTC_AO_TRIG_START1_SYNC;
+ break;
+ case TRIG_EXT:
+ trigsel = NISTC_AO_TRIG_START1_SEL(
+ CR_CHAN(cmd->start_arg) + 1);
+ if (cmd->start_arg & CR_INVERT)
+ /*
+ * 0=active high, 1=active low.
+ * see daq-stc 3-24 (p186)
+ */
+ trigsel |= NISTC_AO_TRIG_START1_POLARITY;
+ if (cmd->start_arg & CR_EDGE)
+ /* 0=edge detection disabled, 1=enabled */
+ trigsel |= NISTC_AO_TRIG_START1_EDGE;
+ break;
+ default:
+ BUG();
+ break;
}
+
+ devpriv->ao_trigger_select = trigsel;
ni_stc_writew(dev, devpriv->ao_trigger_select,
NISTC_AO_TRIG_SEL_REG);
- break;
- default:
- BUG();
- break;
}
- devpriv->ao_trigger_select = val;
- ni_stc_writew(dev, devpriv->ao_trigger_select, NISTC_AO_TRIG_SEL_REG);
+ /* AO_Delayed_START1 = 0, we do not support delayed start...yet */
+ /* sync */
+ /* select DA_START1 as PFI6/AO_START1 when configured as an output */
devpriv->ao_mode3 &= ~NISTC_AO_MODE3_TRIG_LEN;
ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
+
+static void ni_ao_cmd_set_counters(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
+{
+ struct ni_private *devpriv = dev->private;
+ /* Not supporting 'waveform staging' or 'local buffer with pauses' */
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+ /*
+ * This relies on ao_mode1/(Trigger_Once | Continuous) being set in
+ * set_trigger above. It is unclear whether we really need to re-write
+ * this register with these values. The mhddk examples for e-series
+ * show writing this in both places, but the examples for m-series show
+ * a single write in the set_counters function (here).
+ */
ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
+
+ /* sync (upload number of buffer iterations -1) */
+ /* indicate that we want to use BC_Load_A_Register as the source */
devpriv->ao_mode2 &= ~NISTC_AO_MODE2_BC_INIT_LOAD_SRC;
ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
- if (cmd->stop_src == TRIG_NONE)
- ni_stc_writel(dev, 0xffffff, NISTC_AO_BC_LOADA_REG);
- else
- ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG);
+
+ /*
+ * if the BC_TC interrupt is still issued in spite of UC, BC, UI
+ * ignoring BC_TC, then we will need to find a way to ignore that
+ * interrupt in continuous mode.
+ */
+ ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG); /* iter once */
+
+ /* sync (issue command to load number of buffer iterations -1) */
ni_stc_writew(dev, NISTC_AO_CMD1_BC_LOAD, NISTC_AO_CMD1_REG);
+
+ /* sync (upload number of updates in buffer) */
+ /* indicate that we want to use UC_Load_A_Register as the source */
devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC;
ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
- switch (cmd->stop_src) {
- case TRIG_COUNT:
+
+ /*
+ * if a user specifies '0', this automatically assumes the entire 24bit
+ * address space is available for the (multiple iterations of single
+ * buffer) MISB. Otherwise, stop_arg specifies the MISB length that
+ * will be used, regardless of whether we are in continuous mode or not.
+ * In continuous mode, the output will just iterate indefinitely over
+ * the MISB.
+ */
+ {
+ unsigned int stop_arg = cmd->stop_arg > 0 ?
+ (cmd->stop_arg & 0xffffff) : 0xffffff;
+
if (devpriv->is_m_series) {
- /* this is how the NI example code does it for m-series boards, verified correct with 6259 */
- ni_stc_writel(dev, cmd->stop_arg - 1,
- NISTC_AO_UC_LOADA_REG);
+ /*
+ * this is how the NI example code does it for m-series
+ * boards, verified correct with 6259
+ */
+ ni_stc_writel(dev, stop_arg - 1, NISTC_AO_UC_LOADA_REG);
+
+ /* sync (issue cmd to load number of updates in MISB) */
ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD,
NISTC_AO_CMD1_REG);
} else {
- ni_stc_writel(dev, cmd->stop_arg,
- NISTC_AO_UC_LOADA_REG);
+ ni_stc_writel(dev, stop_arg, NISTC_AO_UC_LOADA_REG);
+
+ /* sync (issue cmd to load number of updates in MISB) */
ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD,
NISTC_AO_CMD1_REG);
- ni_stc_writel(dev, cmd->stop_arg - 1,
- NISTC_AO_UC_LOADA_REG);
+
+ /*
+ * sync (upload number of updates-1 in MISB)
+ * --eseries only?
+ */
+ ni_stc_writel(dev, stop_arg - 1, NISTC_AO_UC_LOADA_REG);
}
- break;
- case TRIG_NONE:
- ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG);
- ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG);
- ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG);
- break;
- default:
- ni_stc_writel(dev, 0, NISTC_AO_UC_LOADA_REG);
- ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG);
- ni_stc_writel(dev, cmd->stop_arg, NISTC_AO_UC_LOADA_REG);
}
- devpriv->ao_mode1 &= ~(NISTC_AO_MODE1_UPDATE_SRC_MASK |
- NISTC_AO_MODE1_UI_SRC_MASK |
- NISTC_AO_MODE1_UPDATE_SRC_POLARITY |
- NISTC_AO_MODE1_UI_SRC_POLARITY);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
+
+static void ni_ao_cmd_set_update(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
+{
+ struct ni_private *devpriv = dev->private;
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+
+ /*
+ * zero out these bit fields to be set below. Does an ao-reset do this
+ * automatically?
+ */
+ devpriv->ao_mode1 &= ~(
+ NISTC_AO_MODE1_UI_SRC_MASK |
+ NISTC_AO_MODE1_UI_SRC_POLARITY |
+ NISTC_AO_MODE1_UPDATE_SRC_MASK |
+ NISTC_AO_MODE1_UPDATE_SRC_POLARITY
+ );
+
switch (cmd->scan_begin_src) {
case TRIG_TIMER:
- devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA;
- trigvar =
- ni_ns_to_timer(dev, cmd->scan_begin_arg,
- CMDF_ROUND_NEAREST);
- ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG);
- ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG);
- ni_stc_writel(dev, trigvar, NISTC_AO_UI_LOADA_REG);
+ devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA;
+
+ /*
+ * NOTE: there are several other ways of configuring internal
+ * updates, but we'll only support one for now: using
+ * AO_IN_TIMEBASE, w/o waveform staging, w/o a delay between
+ * START1 and first update, and also w/o local buffer mode w/
+ * pauses.
+ */
+
+ /*
+ * This is already done above:
+ * devpriv->ao_mode1 &= ~(
+ * // set UPDATE_Source to UI_TC:
+ * NISTC_AO_MODE1_UPDATE_SRC_MASK |
+ * // set UPDATE_Source_Polarity to rising (required?)
+ * NISTC_AO_MODE1_UPDATE_SRC_POLARITY |
+ * // set UI_Source to AO_IN_TIMEBASE1:
+ * NISTC_AO_MODE1_UI_SRC_MASK |
+ * // set UI_Source_Polarity to rising (required?)
+ * NISTC_AO_MODE1_UI_SRC_POLARITY
+ * );
+ */
+
+ /*
+ * TODO: use ao_ui_clock_source to allow all possible signals
+ * to be routed to UI_Source_Select. See tSTC.h for
+ * eseries/ni67xx and tMSeries.h for mseries.
+ */
+
+ {
+ unsigned trigvar = ni_ns_to_timer(dev,
+ cmd->scan_begin_arg,
+ CMDF_ROUND_NEAREST);
+
+ /*
+ * Wait N TB3 ticks after the start trigger before
+ * clocking(N must be >=2).
+ */
+ /* following line: 2-1 per STC */
+ ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG);
+ ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD,
+ NISTC_AO_CMD1_REG);
+ /* following line: N-1 per STC */
+ ni_stc_writel(dev, trigvar - 1, NISTC_AO_UI_LOADA_REG);
+ }
break;
case TRIG_EXT:
- devpriv->ao_mode1 |=
- NISTC_AO_MODE1_UPDATE_SRC(cmd->scan_begin_arg);
+ /* FIXME: assert scan_begin_arg != 0, ret failure otherwise */
+ devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA;
+ devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC(
+ CR_CHAN(cmd->scan_begin_arg));
if (cmd->scan_begin_arg & CR_INVERT)
devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC_POLARITY;
- devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA;
break;
default:
BUG();
break;
}
+
ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG);
ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
devpriv->ao_mode2 &= ~(NISTC_AO_MODE2_UI_RELOAD_MODE(3) |
NISTC_AO_MODE2_UI_INIT_LOAD_SRC);
ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
+ /* Configure DAQ-STC for Timed update mode */
+ devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE |
+ NISTC_AO_CMD1_DAC0_UPDATE_MODE;
+ /* We are not using UPDATE2-->don't have to set DACx_Source_Select */
+ ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG);
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
+
+static void ni_ao_cmd_set_channels(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct ni_private *devpriv = dev->private;
+ const struct comedi_cmd *cmd = &s->async->cmd;
+ unsigned bits = 0;
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+
+ if (devpriv->is_6xxx) {
+ unsigned int i;
+
+ bits = 0;
+ for (i = 0; i < cmd->chanlist_len; ++i) {
+ int chan = CR_CHAN(cmd->chanlist[i]);
+
+ bits |= 1 << chan;
+ ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG);
+ }
+ ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG);
+ }
+
+ ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1);
+
if (cmd->scan_end_arg > 1) {
devpriv->ao_mode1 |= NISTC_AO_MODE1_MULTI_CHAN;
- ni_stc_writew(dev,
- NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) |
- NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ,
- NISTC_AO_OUT_CTRL_REG);
- } else {
- unsigned bits;
+ bits = NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1)
+ | NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ;
+ } else {
devpriv->ao_mode1 &= ~NISTC_AO_MODE1_MULTI_CHAN;
bits = NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ;
- if (devpriv->is_m_series || devpriv->is_6xxx) {
+ if (devpriv->is_m_series | devpriv->is_6xxx)
bits |= NISTC_AO_OUT_CTRL_CHANS(0);
- } else {
- bits |=
- NISTC_AO_OUT_CTRL_CHANS(CR_CHAN(cmd->chanlist[0]));
- }
- ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG);
+ else
+ bits |= NISTC_AO_OUT_CTRL_CHANS(
+ CR_CHAN(cmd->chanlist[0]));
}
+
ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
+ ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG);
- ni_stc_writew(dev, NISTC_AO_CMD1_DAC1_UPDATE_MODE |
- NISTC_AO_CMD1_DAC0_UPDATE_MODE,
- NISTC_AO_CMD1_REG);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
+
+static void ni_ao_cmd_set_stop_conditions(struct comedi_device *dev,
+ const struct comedi_cmd *cmd)
+{
+ struct ni_private *devpriv = dev->private;
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR;
ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
+ /*
+ * Since we are not supporting waveform staging, we ignore these errors:
+ * NISTC_AO_MODE3_STOP_ON_BC_TC_ERR,
+ * NISTC_AO_MODE3_STOP_ON_BC_TC_TRIG_ERR
+ */
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+}
+
+static void ni_ao_cmd_set_fifo_mode(struct comedi_device *dev)
+{
+ struct ni_private *devpriv = dev->private;
+
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+
devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_MODE_MASK;
#ifdef PCIDMA
devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF_F;
#else
devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF;
#endif
+ /* NOTE: this is where use_onboard_memory=True would be implemented */
devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_REXMIT_ENA;
ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
- bits = NISTC_AO_PERSONAL_BC_SRC_SEL |
- NISTC_AO_PERSONAL_UPDATE_PW |
- NISTC_AO_PERSONAL_TMRDACWR_PW;
- if (board->ao_fifo_depth)
- bits |= NISTC_AO_PERSONAL_FIFO_ENA;
- else
- bits |= NISTC_AO_PERSONAL_DMA_PIO_CTRL;
-#if 0
- /*
- * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit
- * for 6281, verified with bus analyzer.
- */
- if (devpriv->is_m_series)
- bits |= NISTC_AO_PERSONAL_NUM_DAC;
-#endif
- ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG);
- /* enable sending of ao dma requests */
+ /* enable sending of ao fifo requests (dma request) */
ni_stc_writew(dev, NISTC_AO_START_AOFREQ_ENA, NISTC_AO_START_SEL_REG);
ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
- if (cmd->stop_src == TRIG_COUNT) {
- ni_stc_writew(dev, NISTC_INTB_ACK_AO_BC_TC,
- NISTC_INTB_ACK_REG);
+ /* we are not supporting boards with virtual fifos */
+}
+
+static void ni_ao_cmd_set_interrupts(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ if (s->async->cmd.stop_src == TRIG_COUNT)
ni_set_bits(dev, NISTC_INTB_ENA_REG,
NISTC_INTB_ENA_AO_BC_TC, 1);
- }
s->async->inttrig = ni_ao_inttrig;
+}
+
+static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
+{
+ struct ni_private *devpriv = dev->private;
+ const struct comedi_cmd *cmd = &s->async->cmd;
+
+ if (dev->irq == 0) {
+ dev_err(dev->class_dev, "cannot run command without an irq");
+ return -EIO;
+ }
+
+ /* ni_ao_reset should have already been done */
+ ni_ao_cmd_personalize(dev, cmd);
+ /* clearing fifo and preload happens elsewhere */
+ ni_ao_cmd_set_trigger(dev, cmd);
+ ni_ao_cmd_set_counters(dev, cmd);
+ ni_ao_cmd_set_update(dev, cmd);
+ ni_ao_cmd_set_channels(dev, s);
+ ni_ao_cmd_set_stop_conditions(dev, cmd);
+ ni_ao_cmd_set_fifo_mode(dev);
+ ni_cmd_set_mite_transfer(devpriv->ao_mite_ring, s, cmd, 0x00ffffff);
+ ni_ao_cmd_set_interrupts(dev, s);
+
+ /*
+ * arm(ing) and star(ting) happen in ni_ao_inttrig, which _must_ be
+ * called for ao commands since 1) TRIG_NOW is not supported and 2) DMA
+ * must be setup and initially written to before arm/start happen.
+ */
return 0;
}
+/* end ni_ao_cmd */
+
static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
cmd->chanlist_len);
-
- if (cmd->stop_src == TRIG_COUNT)
- err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
- else /* TRIG_NONE */
- err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
+ err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
if (err)
return 3;
static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ /* See 3.6.1.2 "Resetting", of DAQ-STC Technical Reference Manual */
+
+ /*
+ * In the following, the "--sync" comments are meant to denote
+ * asynchronous boundaries for setting the registers as described in the
+ * DAQ-STC mostly in the order also described in the DAQ-STC.
+ */
+
struct ni_private *devpriv = dev->private;
ni_release_ao_mite_channel(dev);
+ /* --sync (reset AO) */
+ if (devpriv->is_m_series)
+ /* following example in mhddk for m-series */
+ ni_stc_writew(dev, NISTC_RESET_AO, NISTC_RESET_REG);
+
+ /*--sync (start config) */
ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+
+ /*--sync (Disarm) */
ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG);
- ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0);
- ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG);
- ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG);
- ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL |
- NISTC_AO_PERSONAL_UPDATE_PW |
- NISTC_AO_PERSONAL_TMRDACWR_PW,
- NISTC_AO_PERSONAL_REG);
- ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG);
- ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG);
- devpriv->ao_cmd1 = 0;
- ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG);
- devpriv->ao_cmd2 = 0;
- ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG);
+
+ /*
+ * --sync
+ * (clear bunch of registers--mseries mhddk examples do not include
+ * this)
+ */
+ devpriv->ao_cmd1 = 0;
+ devpriv->ao_cmd2 = 0;
devpriv->ao_mode1 = 0;
- ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
devpriv->ao_mode2 = 0;
- ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
if (devpriv->is_m_series)
devpriv->ao_mode3 = NISTC_AO_MODE3_LAST_GATE_DISABLE;
else
devpriv->ao_mode3 = 0;
- ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
devpriv->ao_trigger_select = 0;
- ni_stc_writew(dev, devpriv->ao_trigger_select,
- NISTC_AO_TRIG_SEL_REG);
- if (devpriv->is_6xxx) {
- unsigned immediate_bits = 0;
- unsigned i;
- for (i = 0; i < s->n_chan; ++i)
- immediate_bits |= 1 << i;
- ni_ao_win_outw(dev, immediate_bits, NI671X_AO_IMMEDIATE_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_PERSONAL_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_CMD1_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_CMD2_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_MODE1_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_MODE2_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG);
+ ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_TRIG_SEL_REG);
+
+ /*--sync (disable interrupts) */
+ ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0);
+
+ /*--sync (ack) */
+ ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG);
+ ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG);
+
+ /*--not in DAQ-STC. which doc? */
+ if (devpriv->is_6xxx) {
+ ni_ao_win_outw(dev, (1u << s->n_chan) - 1u,
+ NI671X_AO_IMMEDIATE_REG);
ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG,
NI611X_AO_MISC_REG);
}
ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
+ /*--end */
return 0;
}
err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
cmd->chanlist_len);
- err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
+ err |= comedi_check_trigger_arg_max(&cmd->stop_arg,
+ s->async->prealloc_bufsz /
+ comedi_bytes_per_scan(s));
if (err)
return 3;
static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ struct ni_private *devpriv = dev->private;
const struct comedi_cmd *cmd = &s->async->cmd;
unsigned cdo_mode_bits;
int retval;
if (retval < 0)
return retval;
+ ni_cmd_set_mite_transfer(devpriv->cdo_mite_ring, s, cmd,
+ s->async->prealloc_bufsz /
+ comedi_bytes_per_scan(s));
+
s->async->inttrig = ni_cdo_inttrig;
return 0;
unsigned long flags;
#ifdef PCIDMA
struct ni_private *devpriv = dev->private;
- struct mite_struct *mite = devpriv->mite;
#endif
if (!dev->attached)
a_status = ni_stc_readw(dev, NISTC_AI_STATUS1_REG);
b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG);
#ifdef PCIDMA
- if (mite) {
- struct ni_private *devpriv = dev->private;
+ if (devpriv->mite) {
unsigned long flags_too;
spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too);
ao_mite_status = mite_get_status(devpriv->ao_mite_chan);
if (ao_mite_status & CHSR_LINKC)
writel(CHOR_CLRLC,
- mite->mite_io_addr +
+ devpriv->mite->mite_io_addr +
MITE_CHOR(devpriv->
ao_mite_chan->channel));
}
PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E,
PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E,
PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224,
- PCI-6225, PXI-6225, PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PXIe-6251,
+ PCI-6225, PXI-6225, PCI-6229, PCI-6250,
+ PCI-6251, PXI-6251, PCIe-6251, PXIe-6251,
PCI-6254, PCI-6259, PCIe-6259,
PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289,
PCI-6711, PXI-6711, PCI-6713, PXI-6713,
BOARD_PCI6229,
BOARD_PCI6250,
BOARD_PCI6251,
+ BOARD_PXI6251,
BOARD_PCIE6251,
BOARD_PXIE6251,
BOARD_PCI6254,
.ao_speed = 350,
.caldac = { caldac_none },
},
+ [BOARD_PXI6251] = {
+ .name = "pxi-6251",
+ .n_adchan = 16,
+ .ai_maxdata = 0xffff,
+ .ai_fifo_depth = 4095,
+ .gainlkup = ai_gain_628x,
+ .ai_speed = 800,
+ .n_aochan = 2,
+ .ao_maxdata = 0xffff,
+ .ao_fifo_depth = 8191,
+ .ao_range_table = &range_ni_M_625x_ao,
+ .reg_type = ni_reg_625x,
+ .ao_speed = 350,
+ .caldac = { caldac_none },
+ },
[BOARD_PCIE6251] = {
.name = "pcie-6251",
.n_adchan = 16,
{ PCI_VDEVICE(NI, 0x71bc), BOARD_PCI6221_37PIN },
{ PCI_VDEVICE(NI, 0x717d), BOARD_PCIE6251 },
{ PCI_VDEVICE(NI, 0x72e8), BOARD_PXIE6251 },
+ { PCI_VDEVICE(NI, 0x70ad), BOARD_PXI6251 },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, ni_pcimio_pci_table);
unsigned long flags;
int ret = 0;
- if (trig_num != cmd->start_src)
+ if (trig_num != cmd->start_arg)
return -EINVAL;
spin_lock_irqsave(&counter->lock, flags);
+++ /dev/null
-config DGAP
- tristate "Digi EPCA PCI products"
- default n
- depends on TTY && HAS_IOMEM
- ---help---
- Driver for the Digi International EPCA PCI based product line
+++ /dev/null
-obj-$(CONFIG_DGAP) += dgap.o
+++ /dev/null
-/*
- * Copyright 2003 Digi International (www.digi.com)
- * Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- */
-
-/*
- * In the original out of kernel Digi dgap driver, firmware
- * loading was done via user land to driver handshaking.
- *
- * For cards that support a concentrator (port expander),
- * I believe the concentrator its self told the card which
- * concentrator is actually attached and then that info
- * was used to tell user land which concentrator firmware
- * image was to be downloaded. I think even the BIOS or
- * FEP images required could change with the connection
- * of a particular concentrator.
- *
- * Since I have no access to any of these cards or
- * concentrators, I cannot put the correct concentrator
- * firmware file names into the firmware_info structure
- * as is now done for the BIOS and FEP images.
- *
- * I think, but am not certain, that the cards supporting
- * concentrators will function without them. So support
- * of these cards has been left in this driver.
- *
- * In order to fully support those cards, they would
- * either have to be acquired for dissection or maybe
- * Digi International could provide some assistance.
- */
-#undef DIGI_CONCENTRATORS_SUPPORTED
-
-#define pr_fmt(fmt) "dgap: " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h> /* For udelay */
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/sched.h>
-
-#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */
-#include <linux/ctype.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/io.h> /* For read[bwl]/write[bwl] */
-
-#include <linux/string.h>
-#include <linux/device.h>
-#include <linux/kdev_t.h>
-#include <linux/firmware.h>
-
-#include "dgap.h"
-
-/*
- * File operations permitted on Control/Management major.
- */
-static const struct file_operations dgap_board_fops = {
- .owner = THIS_MODULE,
-};
-
-static uint dgap_numboards;
-static struct board_t *dgap_board[MAXBOARDS];
-static ulong dgap_poll_counter;
-static int dgap_driver_state = DRIVER_INITIALIZED;
-static int dgap_poll_tick = 20; /* Poll interval - 20 ms */
-
-static struct class *dgap_class;
-
-static uint dgap_count = 500;
-
-/*
- * Poller stuff
- */
-static DEFINE_SPINLOCK(dgap_poll_lock); /* Poll scheduling lock */
-static ulong dgap_poll_time; /* Time of next poll */
-static uint dgap_poll_stop; /* Used to tell poller to stop */
-static struct timer_list dgap_poll_timer;
-
-/*
- SUPPORTED PRODUCTS
-
- Card Model Number of Ports Interface
- ----------------------------------------------------------------
- Acceleport Xem 4 - 64 (EIA232 & EIA422)
- Acceleport Xr 4 & 8 (EIA232)
- Acceleport Xr 920 4 & 8 (EIA232)
- Acceleport C/X 8 - 128 (EIA232)
- Acceleport EPC/X 8 - 224 (EIA232)
- Acceleport Xr/422 4 & 8 (EIA422)
- Acceleport 2r/920 2 (EIA232)
- Acceleport 4r/920 4 (EIA232)
- Acceleport 8r/920 8 (EIA232)
-
- IBM 8-Port Asynchronous PCI Adapter (EIA232)
- IBM 128-Port Asynchronous PCI Adapter (EIA232 & EIA422)
-*/
-
-static struct pci_device_id dgap_pci_tbl[] = {
- { DIGI_VID, PCI_DEV_XEM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { DIGI_VID, PCI_DEV_CX_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
- { DIGI_VID, PCI_DEV_CX_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
- { DIGI_VID, PCI_DEV_EPCJ_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
- { DIGI_VID, PCI_DEV_920_2_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
- { DIGI_VID, PCI_DEV_920_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
- { DIGI_VID, PCI_DEV_920_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
- { DIGI_VID, PCI_DEV_XR_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
- { DIGI_VID, PCI_DEV_XRJ_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
- { DIGI_VID, PCI_DEV_XR_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 },
- { DIGI_VID, PCI_DEV_XR_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
- { DIGI_VID, PCI_DEV_XR_SAIP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
- { DIGI_VID, PCI_DEV_XR_BULL_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
- { DIGI_VID, PCI_DEV_920_8_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
- { DIGI_VID, PCI_DEV_XEM_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
- {0,} /* 0 terminated list. */
-};
-MODULE_DEVICE_TABLE(pci, dgap_pci_tbl);
-
-/*
- * A generic list of Product names, PCI Vendor ID, and PCI Device ID.
- */
-struct board_id {
- uint config_type;
- u8 *name;
- uint maxports;
- uint dpatype;
-};
-
-static struct board_id dgap_ids[] = {
- {PPCM, PCI_DEV_XEM_NAME, 64, (T_PCXM | T_PCLITE | T_PCIBUS)},
- {PCX, PCI_DEV_CX_NAME, 128, (T_CX | T_PCIBUS) },
- {PCX, PCI_DEV_CX_IBM_NAME, 128, (T_CX | T_PCIBUS) },
- {PEPC, PCI_DEV_EPCJ_NAME, 224, (T_EPC | T_PCIBUS) },
- {APORT2_920P, PCI_DEV_920_2_NAME, 2, (T_PCXR | T_PCLITE | T_PCIBUS)},
- {APORT4_920P, PCI_DEV_920_4_NAME, 4, (T_PCXR | T_PCLITE | T_PCIBUS)},
- {APORT8_920P, PCI_DEV_920_8_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
- {PAPORT8, PCI_DEV_XR_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
- {PAPORT8, PCI_DEV_XRJ_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
- {PAPORT8, PCI_DEV_XR_422_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
- {PAPORT8, PCI_DEV_XR_IBM_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
- {PAPORT8, PCI_DEV_XR_SAIP_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
- {PAPORT8, PCI_DEV_XR_BULL_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
- {APORT8_920P, PCI_DEV_920_8_HP_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)},
- {PPCM, PCI_DEV_XEM_HP_NAME, 64, (T_PCXM | T_PCLITE | T_PCIBUS)},
- {0,} /* 0 terminated list. */
-};
-
-struct firmware_info {
- u8 *conf_name; /* dgap.conf */
- u8 *bios_name; /* BIOS filename */
- u8 *fep_name; /* FEP filename */
- u8 *con_name; /* Concentrator filename FIXME*/
- int num; /* sequence number */
-};
-
-/*
- * Firmware - BIOS, FEP, and CONC filenames
- */
-static struct firmware_info fw_info[] = {
- { "dgap/dgap.conf", "dgap/sxbios.bin", "dgap/sxfep.bin", NULL, 0 },
- { "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", NULL, 1 },
- { "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", NULL, 2 },
- { "dgap/dgap.conf", "dgap/pcibios.bin", "dgap/pcifep.bin", NULL, 3 },
- { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 4 },
- { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 5 },
- { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 6 },
- { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 7 },
- { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 8 },
- { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 9 },
- { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 10 },
- { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 11 },
- { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 12 },
- { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 13 },
- { "dgap/dgap.conf", "dgap/sxbios.bin", "dgap/sxfep.bin", NULL, 14 },
- {NULL,}
-};
-
-/*
- * Default transparent print information.
- */
-static struct digi_t dgap_digi_init = {
- .digi_flags = DIGI_COOK, /* Flags */
- .digi_maxcps = 100, /* Max CPS */
- .digi_maxchar = 50, /* Max chars in print queue */
- .digi_bufsize = 100, /* Printer buffer size */
- .digi_onlen = 4, /* size of printer on string */
- .digi_offlen = 4, /* size of printer off string */
- .digi_onstr = "\033[5i", /* ANSI printer on string ] */
- .digi_offstr = "\033[4i", /* ANSI printer off string ] */
- .digi_term = "ansi" /* default terminal type */
-};
-
-/*
- * Define a local default termios struct. All ports will be created
- * with this termios initially.
- *
- * This defines a raw port at 9600 baud, 8 data bits, no parity,
- * 1 stop bit.
- */
-
-static struct ktermios dgap_default_termios = {
- .c_iflag = (DEFAULT_IFLAGS), /* iflags */
- .c_oflag = (DEFAULT_OFLAGS), /* oflags */
- .c_cflag = (DEFAULT_CFLAGS), /* cflags */
- .c_lflag = (DEFAULT_LFLAGS), /* lflags */
- .c_cc = INIT_C_CC,
- .c_line = 0,
-};
-
-/*
- * Our needed internal static variables from dgap_parse.c
- */
-static struct cnode dgap_head;
-#define MAXCWORD 200
-static char dgap_cword[MAXCWORD];
-
-struct toklist {
- int token;
- char *string;
-};
-
-static struct toklist dgap_brdtype[] = {
- { PCX, "Digi_AccelePort_C/X_PCI" },
- { PEPC, "Digi_AccelePort_EPC/X_PCI" },
- { PPCM, "Digi_AccelePort_Xem_PCI" },
- { APORT2_920P, "Digi_AccelePort_2r_920_PCI" },
- { APORT4_920P, "Digi_AccelePort_4r_920_PCI" },
- { APORT8_920P, "Digi_AccelePort_8r_920_PCI" },
- { PAPORT4, "Digi_AccelePort_4r_PCI(EIA-232/RS-422)" },
- { PAPORT8, "Digi_AccelePort_8r_PCI(EIA-232/RS-422)" },
- { 0, NULL }
-};
-
-static struct toklist dgap_tlist[] = {
- { BEGIN, "config_begin" },
- { END, "config_end" },
- { BOARD, "board" },
- { PCIINFO, "pciinfo" },
- { LINE, "line" },
- { CONC, "conc" },
- { CONC, "concentrator" },
- { CX, "cx" },
- { CX, "ccon" },
- { EPC, "epccon" },
- { EPC, "epc" },
- { MOD, "module" },
- { ID, "id" },
- { STARTO, "start" },
- { SPEED, "speed" },
- { CABLE, "cable" },
- { CONNECT, "connect" },
- { METHOD, "method" },
- { STATUS, "status" },
- { CUSTOM, "Custom" },
- { BASIC, "Basic" },
- { MEM, "mem" },
- { MEM, "memory" },
- { PORTS, "ports" },
- { MODEM, "modem" },
- { NPORTS, "nports" },
- { TTYN, "ttyname" },
- { CU, "cuname" },
- { PRINT, "prname" },
- { CMAJOR, "major" },
- { ALTPIN, "altpin" },
- { USEINTR, "useintr" },
- { TTSIZ, "ttysize" },
- { CHSIZ, "chsize" },
- { BSSIZ, "boardsize" },
- { UNTSIZ, "schedsize" },
- { F2SIZ, "f2200size" },
- { VPSIZ, "vpixsize" },
- { 0, NULL }
-};
-
-/*
- * get a word from the input stream, also keep track of current line number.
- * words are separated by whitespace.
- */
-static char *dgap_getword(char **in)
-{
- char *ret_ptr = *in;
-
- char *ptr = strpbrk(*in, " \t\n");
-
- /* If no word found, return null */
- if (!ptr)
- return NULL;
-
- /* Mark new location for our buffer */
- *ptr = '\0';
- *in = ptr + 1;
-
- /* Eat any extra spaces/tabs/newlines that might be present */
- while (*in && **in && ((**in == ' ') ||
- (**in == '\t') ||
- (**in == '\n'))) {
- **in = '\0';
- *in = *in + 1;
- }
-
- return ret_ptr;
-}
-
-
-/*
- * Get a token from the input file; return 0 if end of file is reached
- */
-static int dgap_gettok(char **in)
-{
- char *w;
- struct toklist *t;
-
- if (strstr(dgap_cword, "board")) {
- w = dgap_getword(in);
- if (!w)
- return 0;
- snprintf(dgap_cword, MAXCWORD, "%s", w);
- for (t = dgap_brdtype; t->token != 0; t++) {
- if (!strcmp(w, t->string))
- return t->token;
- }
- } else {
- while ((w = dgap_getword(in))) {
- snprintf(dgap_cword, MAXCWORD, "%s", w);
- for (t = dgap_tlist; t->token != 0; t++) {
- if (!strcmp(w, t->string))
- return t->token;
- }
- }
- }
-
- return 0;
-}
-
-/*
- * dgap_checknode: see if all the necessary info has been supplied for a node
- * before creating the next node.
- */
-static int dgap_checknode(struct cnode *p)
-{
- switch (p->type) {
- case LNODE:
- if (p->u.line.v_speed == 0) {
- pr_err("line speed not specified");
- return 1;
- }
- return 0;
-
- case CNODE:
- if (p->u.conc.v_speed == 0) {
- pr_err("concentrator line speed not specified");
- return 1;
- }
- if (p->u.conc.v_nport == 0) {
- pr_err("number of ports on concentrator not specified");
- return 1;
- }
- if (p->u.conc.v_id == 0) {
- pr_err("concentrator id letter not specified");
- return 1;
- }
- return 0;
-
- case MNODE:
- if (p->u.module.v_nport == 0) {
- pr_err("number of ports on EBI module not specified");
- return 1;
- }
- if (p->u.module.v_id == 0) {
- pr_err("EBI module id letter not specified");
- return 1;
- }
- return 0;
- }
- return 0;
-}
-
-/*
- * Given a board pointer, returns whether we should use interrupts or not.
- */
-static uint dgap_config_get_useintr(struct board_t *bd)
-{
- struct cnode *p;
-
- if (!bd)
- return 0;
-
- for (p = bd->bd_config; p; p = p->next) {
- if (p->type == INTRNODE) {
- /*
- * check for pcxr types.
- */
- return p->u.useintr;
- }
- }
-
- /* If not found, then don't turn on interrupts. */
- return 0;
-}
-
-/*
- * Given a board pointer, returns whether we turn on altpin or not.
- */
-static uint dgap_config_get_altpin(struct board_t *bd)
-{
- struct cnode *p;
-
- if (!bd)
- return 0;
-
- for (p = bd->bd_config; p; p = p->next) {
- if (p->type == ANODE) {
- /*
- * check for pcxr types.
- */
- return p->u.altpin;
- }
- }
-
- /* If not found, then don't turn on interrupts. */
- return 0;
-}
-
-/*
- * Given a specific type of board, if found, detached link and
- * returns the first occurrence in the list.
- */
-static struct cnode *dgap_find_config(int type, int bus, int slot)
-{
- struct cnode *p, *prev, *prev2, *found;
-
- p = &dgap_head;
-
- while (p->next) {
- prev = p;
- p = p->next;
-
- if (p->type != BNODE)
- continue;
-
- if (p->u.board.type != type)
- continue;
-
- if (p->u.board.v_pcibus &&
- p->u.board.pcibus != bus)
- continue;
-
- if (p->u.board.v_pcislot &&
- p->u.board.pcislot != slot)
- continue;
-
- found = p;
- /*
- * Keep walking thru the list till we
- * find the next board.
- */
- while (p->next) {
- prev2 = p;
- p = p->next;
-
- if (p->type != BNODE)
- continue;
-
- /*
- * Mark the end of our 1 board
- * chain of configs.
- */
- prev2->next = NULL;
-
- /*
- * Link the "next" board to the
- * previous board, effectively
- * "unlinking" our board from
- * the main config.
- */
- prev->next = p;
-
- return found;
- }
- /*
- * It must be the last board in the list.
- */
- prev->next = NULL;
- return found;
- }
- return NULL;
-}
-
-/*
- * Given a board pointer, walks the config link, counting up
- * all ports user specified should be on the board.
- * (This does NOT mean they are all actually present right now tho)
- */
-static uint dgap_config_get_num_prts(struct board_t *bd)
-{
- int count = 0;
- struct cnode *p;
-
- if (!bd)
- return 0;
-
- for (p = bd->bd_config; p; p = p->next) {
- switch (p->type) {
- case BNODE:
- /*
- * check for pcxr types.
- */
- if (p->u.board.type > EPCFE)
- count += p->u.board.nport;
- break;
- case CNODE:
- count += p->u.conc.nport;
- break;
- case MNODE:
- count += p->u.module.nport;
- break;
- }
- }
- return count;
-}
-
-static char *dgap_create_config_string(struct board_t *bd, char *string)
-{
- char *ptr = string;
- struct cnode *p;
- struct cnode *q;
- int speed;
-
- if (!bd) {
- *ptr = 0xff;
- return string;
- }
-
- for (p = bd->bd_config; p; p = p->next) {
- switch (p->type) {
- case LNODE:
- *ptr = '\0';
- ptr++;
- *ptr = p->u.line.speed;
- ptr++;
- break;
- case CNODE:
- /*
- * Because the EPC/con concentrators can have EM modules
- * hanging off of them, we have to walk ahead in the
- * list and keep adding the number of ports on each EM
- * to the config. UGH!
- */
- speed = p->u.conc.speed;
- q = p->next;
- if (q && (q->type == MNODE)) {
- *ptr = (p->u.conc.nport + 0x80);
- ptr++;
- p = q;
- while (q->next && (q->next->type) == MNODE) {
- *ptr = (q->u.module.nport + 0x80);
- ptr++;
- p = q;
- q = q->next;
- }
- *ptr = q->u.module.nport;
- ptr++;
- } else {
- *ptr = p->u.conc.nport;
- ptr++;
- }
-
- *ptr = speed;
- ptr++;
- break;
- }
- }
-
- *ptr = 0xff;
- return string;
-}
-
-/*
- * Parse a configuration file read into memory as a string.
- */
-static int dgap_parsefile(char **in)
-{
- struct cnode *p, *brd, *line, *conc;
- int rc;
- char *s;
- int linecnt = 0;
-
- p = &dgap_head;
- brd = line = conc = NULL;
-
- /* perhaps we are adding to an existing list? */
- while (p->next)
- p = p->next;
-
- /* file must start with a BEGIN */
- while ((rc = dgap_gettok(in)) != BEGIN) {
- if (rc == 0) {
- pr_err("unexpected EOF");
- return -1;
- }
- }
-
- for (; ;) {
- int board_type = 0;
- int conc_type = 0;
- int module_type = 0;
-
- rc = dgap_gettok(in);
- if (rc == 0) {
- pr_err("unexpected EOF");
- return -1;
- }
-
- switch (rc) {
- case BEGIN: /* should only be 1 begin */
- pr_err("unexpected config_begin\n");
- return -1;
-
- case END:
- return 0;
-
- case BOARD: /* board info */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
-
- p->type = BNODE;
- p->u.board.status = kstrdup("No", GFP_KERNEL);
- line = conc = NULL;
- brd = p;
- linecnt = -1;
-
- board_type = dgap_gettok(in);
- if (board_type == 0) {
- pr_err("board !!type not specified");
- return -1;
- }
-
- p->u.board.type = board_type;
-
- break;
-
- case MEM: /* memory address */
- if (p->type != BNODE) {
- pr_err("memory address only valid for boards");
- return -1;
- }
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- kfree(p->u.board.addrstr);
- p->u.board.addrstr = kstrdup(s, GFP_KERNEL);
- if (kstrtoul(s, 0, &p->u.board.addr)) {
- pr_err("bad number for memory address");
- return -1;
- }
- p->u.board.v_addr = 1;
- break;
-
- case PCIINFO: /* pci information */
- if (p->type != BNODE) {
- pr_err("memory address only valid for boards");
- return -1;
- }
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- kfree(p->u.board.pcibusstr);
- p->u.board.pcibusstr = kstrdup(s, GFP_KERNEL);
- if (kstrtoul(s, 0, &p->u.board.pcibus)) {
- pr_err("bad number for pci bus");
- return -1;
- }
- p->u.board.v_pcibus = 1;
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- kfree(p->u.board.pcislotstr);
- p->u.board.pcislotstr = kstrdup(s, GFP_KERNEL);
- if (kstrtoul(s, 0, &p->u.board.pcislot)) {
- pr_err("bad number for pci slot");
- return -1;
- }
- p->u.board.v_pcislot = 1;
- break;
-
- case METHOD:
- if (p->type != BNODE) {
- pr_err("install method only valid for boards");
- return -1;
- }
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- kfree(p->u.board.method);
- p->u.board.method = kstrdup(s, GFP_KERNEL);
- p->u.board.v_method = 1;
- break;
-
- case STATUS:
- if (p->type != BNODE) {
- pr_err("config status only valid for boards");
- return -1;
- }
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- kfree(p->u.board.status);
- p->u.board.status = kstrdup(s, GFP_KERNEL);
- break;
-
- case NPORTS: /* number of ports */
- if (p->type == BNODE) {
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.board.nport)) {
- pr_err("bad number for number of ports");
- return -1;
- }
- p->u.board.v_nport = 1;
- } else if (p->type == CNODE) {
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.conc.nport)) {
- pr_err("bad number for number of ports");
- return -1;
- }
- p->u.conc.v_nport = 1;
- } else if (p->type == MNODE) {
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.module.nport)) {
- pr_err("bad number for number of ports");
- return -1;
- }
- p->u.module.v_nport = 1;
- } else {
- pr_err("nports only valid for concentrators or modules");
- return -1;
- }
- break;
-
- case ID: /* letter ID used in tty name */
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- kfree(p->u.board.status);
- p->u.board.status = kstrdup(s, GFP_KERNEL);
-
- if (p->type == CNODE) {
- kfree(p->u.conc.id);
- p->u.conc.id = kstrdup(s, GFP_KERNEL);
- p->u.conc.v_id = 1;
- } else if (p->type == MNODE) {
- kfree(p->u.module.id);
- p->u.module.id = kstrdup(s, GFP_KERNEL);
- p->u.module.v_id = 1;
- } else {
- pr_err("id only valid for concentrators or modules");
- return -1;
- }
- break;
-
- case STARTO: /* start offset of ID */
- if (p->type == BNODE) {
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.board.start)) {
- pr_err("bad number for start of tty count");
- return -1;
- }
- p->u.board.v_start = 1;
- } else if (p->type == CNODE) {
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.conc.start)) {
- pr_err("bad number for start of tty count");
- return -1;
- }
- p->u.conc.v_start = 1;
- } else if (p->type == MNODE) {
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.module.start)) {
- pr_err("bad number for start of tty count");
- return -1;
- }
- p->u.module.v_start = 1;
- } else {
- pr_err("start only valid for concentrators or modules");
- return -1;
- }
- break;
-
- case TTYN: /* tty name prefix */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = TNODE;
-
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpeced end of file");
- return -1;
- }
- p->u.ttyname = kstrdup(s, GFP_KERNEL);
- if (!p->u.ttyname)
- return -1;
-
- break;
-
- case CU: /* cu name prefix */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = CUNODE;
-
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpeced end of file");
- return -1;
- }
- p->u.cuname = kstrdup(s, GFP_KERNEL);
- if (!p->u.cuname)
- return -1;
-
- break;
-
- case LINE: /* line information */
- if (dgap_checknode(p))
- return -1;
- if (!brd) {
- pr_err("must specify board before line info");
- return -1;
- }
- switch (brd->u.board.type) {
- case PPCM:
- pr_err("line not valid for PC/em");
- return -1;
- }
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = LNODE;
- conc = NULL;
- line = p;
- linecnt++;
- break;
-
- case CONC: /* concentrator information */
- if (dgap_checknode(p))
- return -1;
- if (!line) {
- pr_err("must specify line info before concentrator");
- return -1;
- }
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = CNODE;
- conc = p;
-
- if (linecnt)
- brd->u.board.conc2++;
- else
- brd->u.board.conc1++;
-
- conc_type = dgap_gettok(in);
- if (conc_type == 0 ||
- (conc_type != CX && conc_type != EPC)) {
- pr_err("failed to set a type of concentratros");
- return -1;
- }
-
- p->u.conc.type = conc_type;
-
- break;
-
- case MOD: /* EBI module */
- if (dgap_checknode(p))
- return -1;
- if (!brd) {
- pr_err("must specify board info before EBI modules");
- return -1;
- }
- switch (brd->u.board.type) {
- case PPCM:
- linecnt = 0;
- break;
- default:
- if (!conc) {
- pr_err("must specify concentrator info before EBI module");
- return -1;
- }
- }
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = MNODE;
-
- if (linecnt)
- brd->u.board.module2++;
- else
- brd->u.board.module1++;
-
- module_type = dgap_gettok(in);
- if (module_type == 0 ||
- (module_type != PORTS && module_type != MODEM)) {
- pr_err("failed to set a type of module");
- return -1;
- }
-
- p->u.module.type = module_type;
-
- break;
-
- case CABLE:
- if (p->type == LNODE) {
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- kfree(p->u.line.cable);
- p->u.line.cable = kstrdup(s, GFP_KERNEL);
- p->u.line.v_cable = 1;
- }
- break;
-
- case SPEED: /* sync line speed indication */
- if (p->type == LNODE) {
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.line.speed)) {
- pr_err("bad number for line speed");
- return -1;
- }
- p->u.line.v_speed = 1;
- } else if (p->type == CNODE) {
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.conc.speed)) {
- pr_err("bad number for line speed");
- return -1;
- }
- p->u.conc.v_speed = 1;
- } else {
- pr_err("speed valid only for lines or concentrators.");
- return -1;
- }
- break;
-
- case CONNECT:
- if (p->type == CNODE) {
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- kfree(p->u.conc.connect);
- p->u.conc.connect = kstrdup(s, GFP_KERNEL);
- p->u.conc.v_connect = 1;
- }
- break;
- case PRINT: /* transparent print name prefix */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = PNODE;
-
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpeced end of file");
- return -1;
- }
- p->u.printname = kstrdup(s, GFP_KERNEL);
- if (!p->u.printname)
- return -1;
-
- break;
-
- case CMAJOR: /* major number */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = JNODE;
-
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.majornumber)) {
- pr_err("bad number for major number");
- return -1;
- }
- break;
-
- case ALTPIN: /* altpin setting */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = ANODE;
-
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.altpin)) {
- pr_err("bad number for altpin");
- return -1;
- }
- break;
-
- case USEINTR: /* enable interrupt setting */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = INTRNODE;
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.useintr)) {
- pr_err("bad number for useintr");
- return -1;
- }
- break;
-
- case TTSIZ: /* size of tty structure */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = TSNODE;
-
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.ttysize)) {
- pr_err("bad number for ttysize");
- return -1;
- }
- break;
-
- case CHSIZ: /* channel structure size */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = CSNODE;
-
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.chsize)) {
- pr_err("bad number for chsize");
- return -1;
- }
- break;
-
- case BSSIZ: /* board structure size */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = BSNODE;
-
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.bssize)) {
- pr_err("bad number for bssize");
- return -1;
- }
- break;
-
- case UNTSIZ: /* sched structure size */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = USNODE;
-
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.unsize)) {
- pr_err("bad number for schedsize");
- return -1;
- }
- break;
-
- case F2SIZ: /* f2200 structure size */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = FSNODE;
-
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.f2size)) {
- pr_err("bad number for f2200size");
- return -1;
- }
- break;
-
- case VPSIZ: /* vpix structure size */
- if (dgap_checknode(p))
- return -1;
-
- p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL);
- if (!p->next)
- return -ENOMEM;
-
- p = p->next;
- p->type = VSNODE;
-
- s = dgap_getword(in);
- if (!s) {
- pr_err("unexpected end of file");
- return -1;
- }
- if (kstrtol(s, 0, &p->u.vpixsize)) {
- pr_err("bad number for vpixsize");
- return -1;
- }
- break;
- }
- }
-}
-
-static void dgap_cleanup_nodes(void)
-{
- struct cnode *p;
-
- p = &dgap_head;
-
- while (p) {
- struct cnode *tmp = p->next;
-
- if (p->type == NULLNODE) {
- p = tmp;
- continue;
- }
-
- switch (p->type) {
- case BNODE:
- kfree(p->u.board.addrstr);
- kfree(p->u.board.pcibusstr);
- kfree(p->u.board.pcislotstr);
- kfree(p->u.board.method);
- break;
- case CNODE:
- kfree(p->u.conc.id);
- kfree(p->u.conc.connect);
- break;
- case MNODE:
- kfree(p->u.module.id);
- break;
- case TNODE:
- kfree(p->u.ttyname);
- break;
- case CUNODE:
- kfree(p->u.cuname);
- break;
- case LNODE:
- kfree(p->u.line.cable);
- break;
- case PNODE:
- kfree(p->u.printname);
- break;
- }
-
- kfree(p->u.board.status);
- kfree(p);
- p = tmp;
- }
-}
-
-/*
- * Retrives the current custom baud rate from FEP memory,
- * and returns it back to the user.
- * Returns 0 on error.
- */
-static uint dgap_get_custom_baud(struct channel_t *ch)
-{
- u8 __iomem *vaddr;
- ulong offset;
-
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
-
- if (!ch->ch_bd || ch->ch_bd->magic != DGAP_BOARD_MAGIC)
- return 0;
-
- if (!(ch->ch_bd->bd_flags & BD_FEP5PLUS))
- return 0;
-
- vaddr = ch->ch_bd->re_map_membase;
-
- if (!vaddr)
- return 0;
-
- /*
- * Go get from fep mem, what the fep
- * believes the custom baud rate is.
- */
- offset = (ioread16(vaddr + ECS_SEG) << 4) + (ch->ch_portnum * 0x28)
- + LINE_SPEED;
-
- return readw(vaddr + offset);
-}
-
-/*
- * Remap PCI memory.
- */
-static int dgap_remap(struct board_t *brd)
-{
- if (!brd || brd->magic != DGAP_BOARD_MAGIC)
- return -EIO;
-
- if (!request_mem_region(brd->membase, 0x200000, "dgap"))
- return -ENOMEM;
-
- if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, "dgap"))
- goto err_req_mem;
-
- brd->re_map_membase = ioremap(brd->membase, 0x200000);
- if (!brd->re_map_membase)
- goto err_remap_mem;
-
- brd->re_map_port = ioremap((brd->membase + PCI_IO_OFFSET), 0x200000);
- if (!brd->re_map_port)
- goto err_remap_port;
-
- return 0;
-
-err_remap_port:
- iounmap(brd->re_map_membase);
-err_remap_mem:
- release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
-err_req_mem:
- release_mem_region(brd->membase, 0x200000);
-
- return -ENOMEM;
-}
-
-static void dgap_unmap(struct board_t *brd)
-{
- iounmap(brd->re_map_port);
- iounmap(brd->re_map_membase);
- release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000);
- release_mem_region(brd->membase, 0x200000);
-}
-
-/*
- * dgap_parity_scan()
- *
- * Convert the FEP5 way of reporting parity errors and breaks into
- * the Linux line discipline way.
- */
-static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf,
- unsigned char *fbuf, int *len)
-{
- int l = *len;
- int count = 0;
- unsigned char *in, *cout, *fout;
- unsigned char c;
-
- in = cbuf;
- cout = cbuf;
- fout = fbuf;
-
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- while (l--) {
- c = *in++;
- switch (ch->pscan_state) {
- default:
- /* reset to sanity and fall through */
- ch->pscan_state = 0;
-
- case 0:
- /* No FF seen yet */
- if (c == (unsigned char)'\377')
- /* delete this character from stream */
- ch->pscan_state = 1;
- else {
- *cout++ = c;
- *fout++ = TTY_NORMAL;
- count += 1;
- }
- break;
-
- case 1:
- /* first FF seen */
- if (c == (unsigned char)'\377') {
- /* doubled ff, transform to single ff */
- *cout++ = c;
- *fout++ = TTY_NORMAL;
- count += 1;
- ch->pscan_state = 0;
- } else {
- /* save value examination in next state */
- ch->pscan_savechar = c;
- ch->pscan_state = 2;
- }
- break;
-
- case 2:
- /* third character of ff sequence */
-
- *cout++ = c;
-
- if (ch->pscan_savechar == 0x0) {
- if (c == 0x0) {
- ch->ch_err_break++;
- *fout++ = TTY_BREAK;
- } else {
- ch->ch_err_parity++;
- *fout++ = TTY_PARITY;
- }
- }
-
- count += 1;
- ch->pscan_state = 0;
- }
- }
- *len = count;
-}
-
-/*=======================================================================
- *
- * dgap_input - Process received data.
- *
- * ch - Pointer to channel structure.
- *
- *=======================================================================*/
-
-static void dgap_input(struct channel_t *ch)
-{
- struct board_t *bd;
- struct bs_t __iomem *bs;
- struct tty_struct *tp;
- struct tty_ldisc *ld;
- uint rmask;
- uint head;
- uint tail;
- int data_len;
- ulong lock_flags;
- ulong lock_flags2;
- int flip_len;
- int len;
- int n;
- u8 *buf;
- u8 tmpchar;
- int s;
-
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- tp = ch->ch_tun.un_tty;
-
- bs = ch->ch_bs;
- if (!bs)
- return;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- /*
- * Figure the number of characters in the buffer.
- * Exit immediately if none.
- */
-
- rmask = ch->ch_rsize - 1;
-
- head = readw(&bs->rx_head);
- head &= rmask;
- tail = readw(&bs->rx_tail);
- tail &= rmask;
-
- data_len = (head - tail) & rmask;
-
- if (data_len == 0) {
- writeb(1, &bs->idata);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return;
- }
-
- /*
- * If the device is not open, or CREAD is off, flush
- * input data and return immediately.
- */
- if ((bd->state != BOARD_READY) || !tp ||
- (tp->magic != TTY_MAGIC) ||
- !(ch->ch_tun.un_flags & UN_ISOPEN) ||
- !C_CREAD(tp) ||
- (ch->ch_tun.un_flags & UN_CLOSING)) {
- writew(head, &bs->rx_tail);
- writeb(1, &bs->idata);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return;
- }
-
- /*
- * If we are throttled, simply don't read any data.
- */
- if (ch->ch_flags & CH_RXBLOCK) {
- writeb(1, &bs->idata);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return;
- }
-
- /*
- * Ignore oruns.
- */
- tmpchar = readb(&bs->orun);
- if (tmpchar) {
- ch->ch_err_overrun++;
- writeb(0, &bs->orun);
- }
-
- /* Decide how much data we can send into the tty layer */
- flip_len = TTY_FLIPBUF_SIZE;
-
- /* Chop down the length, if needed */
- len = min(data_len, flip_len);
- len = min(len, (N_TTY_BUF_SIZE - 1));
-
- ld = tty_ldisc_ref(tp);
-
-#ifdef TTY_DONT_FLIP
- /*
- * If the DONT_FLIP flag is on, don't flush our buffer, and act
- * like the ld doesn't have any space to put the data right now.
- */
- if (test_bit(TTY_DONT_FLIP, &tp->flags))
- len = 0;
-#endif
-
- /*
- * If we were unable to get a reference to the ld,
- * don't flush our buffer, and act like the ld doesn't
- * have any space to put the data right now.
- */
- if (!ld) {
- len = 0;
- } else {
- /*
- * If ld doesn't have a pointer to a receive_buf function,
- * flush the data, then act like the ld doesn't have any
- * space to put the data right now.
- */
- if (!ld->ops->receive_buf) {
- writew(head, &bs->rx_tail);
- len = 0;
- }
- }
-
- if (len <= 0) {
- writeb(1, &bs->idata);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- if (ld)
- tty_ldisc_deref(ld);
- return;
- }
-
- buf = ch->ch_bd->flipbuf;
- n = len;
-
- /*
- * n now contains the most amount of data we can copy,
- * bounded either by our buffer size or the amount
- * of data the card actually has pending...
- */
- while (n) {
- s = ((head >= tail) ? head : ch->ch_rsize) - tail;
- s = min(s, n);
-
- if (s <= 0)
- break;
-
- memcpy_fromio(buf, ch->ch_raddr + tail, s);
-
- tail += s;
- buf += s;
-
- n -= s;
- /* Flip queue if needed */
- tail &= rmask;
- }
-
- writew(tail, &bs->rx_tail);
- writeb(1, &bs->idata);
- ch->ch_rxcount += len;
-
- /*
- * If we are completely raw, we don't need to go through a lot
- * of the tty layers that exist.
- * In this case, we take the shortest and fastest route we
- * can to relay the data to the user.
- *
- * On the other hand, if we are not raw, we need to go through
- * the tty layer, which has its API more well defined.
- */
- if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) {
- dgap_parity_scan(ch, ch->ch_bd->flipbuf,
- ch->ch_bd->flipflagbuf, &len);
-
- len = tty_buffer_request_room(tp->port, len);
- tty_insert_flip_string_flags(tp->port, ch->ch_bd->flipbuf,
- ch->ch_bd->flipflagbuf, len);
- } else {
- len = tty_buffer_request_room(tp->port, len);
- tty_insert_flip_string(tp->port, ch->ch_bd->flipbuf, len);
- }
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- /* Tell the tty layer its okay to "eat" the data now */
- tty_flip_buffer_push(tp->port);
-
- if (ld)
- tty_ldisc_deref(ld);
-}
-
-static void dgap_write_wakeup(struct board_t *bd, struct channel_t *ch,
- struct un_t *un, u32 mask)
-{
- if (!(un->un_flags & mask))
- return;
-
- un->un_flags &= ~mask;
-
- if (!(un->un_flags & UN_ISOPEN))
- return;
-
- tty_wakeup(un->un_tty);
- wake_up_interruptible(&un->un_flags_wait);
-}
-
-/************************************************************************
- * Determines when CARRIER changes state and takes appropriate
- * action.
- ************************************************************************/
-static void dgap_carrier(struct channel_t *ch)
-{
- struct board_t *bd;
-
- int virt_carrier = 0;
- int phys_carrier = 0;
-
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- bd = ch->ch_bd;
-
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- /* Make sure altpin is always set correctly */
- if (ch->ch_digi.digi_flags & DIGI_ALTPIN) {
- ch->ch_dsr = DM_CD;
- ch->ch_cd = DM_DSR;
- } else {
- ch->ch_dsr = DM_DSR;
- ch->ch_cd = DM_CD;
- }
-
- if (ch->ch_mistat & D_CD(ch))
- phys_carrier = 1;
-
- if (ch->ch_digi.digi_flags & DIGI_FORCEDCD)
- virt_carrier = 1;
-
- if (ch->ch_c_cflag & CLOCAL)
- virt_carrier = 1;
-
- /*
- * Test for a VIRTUAL carrier transition to HIGH.
- */
- if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) {
- /*
- * When carrier rises, wake any threads waiting
- * for carrier in the open routine.
- */
-
- if (waitqueue_active(&(ch->ch_flags_wait)))
- wake_up_interruptible(&ch->ch_flags_wait);
- }
-
- /*
- * Test for a PHYSICAL carrier transition to HIGH.
- */
- if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) {
- /*
- * When carrier rises, wake any threads waiting
- * for carrier in the open routine.
- */
-
- if (waitqueue_active(&(ch->ch_flags_wait)))
- wake_up_interruptible(&ch->ch_flags_wait);
- }
-
- /*
- * Test for a PHYSICAL transition to low, so long as we aren't
- * currently ignoring physical transitions (which is what "virtual
- * carrier" indicates).
- *
- * The transition of the virtual carrier to low really doesn't
- * matter... it really only means "ignore carrier state", not
- * "make pretend that carrier is there".
- */
- if ((virt_carrier == 0) &&
- ((ch->ch_flags & CH_CD) != 0) &&
- (phys_carrier == 0)) {
- /*
- * When carrier drops:
- *
- * Drop carrier on all open units.
- *
- * Flush queues, waking up any task waiting in the
- * line discipline.
- *
- * Send a hangup to the control terminal.
- *
- * Enable all select calls.
- */
- if (waitqueue_active(&(ch->ch_flags_wait)))
- wake_up_interruptible(&ch->ch_flags_wait);
-
- if (ch->ch_tun.un_open_count > 0)
- tty_hangup(ch->ch_tun.un_tty);
-
- if (ch->ch_pun.un_open_count > 0)
- tty_hangup(ch->ch_pun.un_tty);
- }
-
- /*
- * Make sure that our cached values reflect the current reality.
- */
- if (virt_carrier == 1)
- ch->ch_flags |= CH_FCAR;
- else
- ch->ch_flags &= ~CH_FCAR;
-
- if (phys_carrier == 1)
- ch->ch_flags |= CH_CD;
- else
- ch->ch_flags &= ~CH_CD;
-}
-
-/*=======================================================================
- *
- * dgap_event - FEP to host event processing routine.
- *
- * bd - Board of current event.
- *
- *=======================================================================*/
-static int dgap_event(struct board_t *bd)
-{
- struct channel_t *ch;
- ulong lock_flags;
- ulong lock_flags2;
- struct bs_t __iomem *bs;
- u8 __iomem *event;
- u8 __iomem *vaddr;
- struct ev_t __iomem *eaddr;
- uint head;
- uint tail;
- int port;
- int reason;
- int modem;
-
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return -EIO;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
-
- vaddr = bd->re_map_membase;
-
- if (!vaddr) {
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return -EIO;
- }
-
- eaddr = (struct ev_t __iomem *)(vaddr + EVBUF);
-
- /* Get our head and tail */
- head = readw(&eaddr->ev_head);
- tail = readw(&eaddr->ev_tail);
-
- /*
- * Forget it if pointers out of range.
- */
-
- if (head >= EVMAX - EVSTART || tail >= EVMAX - EVSTART ||
- (head | tail) & 03) {
- /* Let go of board lock */
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return -EIO;
- }
-
- /*
- * Loop to process all the events in the buffer.
- */
- while (tail != head) {
- /*
- * Get interrupt information.
- */
-
- event = bd->re_map_membase + tail + EVSTART;
-
- port = ioread8(event);
- reason = ioread8(event + 1);
- modem = ioread8(event + 2);
- ioread8(event + 3);
-
- /*
- * Make sure the interrupt is valid.
- */
- if (port >= bd->nasync)
- goto next;
-
- if (!(reason & (IFMODEM | IFBREAK | IFTLW | IFTEM | IFDATA)))
- goto next;
-
- ch = bd->channels[port];
-
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- goto next;
-
- /*
- * If we have made it here, the event was valid.
- * Lock down the channel.
- */
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- bs = ch->ch_bs;
-
- if (!bs) {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- goto next;
- }
-
- /*
- * Process received data.
- */
- if (reason & IFDATA) {
- /*
- * ALL LOCKS *MUST* BE DROPPED BEFORE CALLING INPUT!
- * input could send some data to ld, which in turn
- * could do a callback to one of our other functions.
- */
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- dgap_input(ch);
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- if (ch->ch_flags & CH_RACTIVE)
- ch->ch_flags |= CH_RENABLE;
- else
- writeb(1, &bs->idata);
-
- if (ch->ch_flags & CH_RWAIT) {
- ch->ch_flags &= ~CH_RWAIT;
-
- wake_up_interruptible
- (&ch->ch_tun.un_flags_wait);
- }
- }
-
- /*
- * Process Modem change signals.
- */
- if (reason & IFMODEM) {
- ch->ch_mistat = modem;
- dgap_carrier(ch);
- }
-
- /*
- * Process break.
- */
- if (reason & IFBREAK) {
- if (ch->ch_tun.un_tty) {
- /* A break has been indicated */
- ch->ch_err_break++;
- tty_buffer_request_room
- (ch->ch_tun.un_tty->port, 1);
- tty_insert_flip_char(ch->ch_tun.un_tty->port,
- 0, TTY_BREAK);
- tty_flip_buffer_push(ch->ch_tun.un_tty->port);
- }
- }
-
- /*
- * Process Transmit low.
- */
- if (reason & IFTLW) {
- dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_LOW);
- dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_LOW);
- if (ch->ch_flags & CH_WLOW) {
- ch->ch_flags &= ~CH_WLOW;
- wake_up_interruptible(&ch->ch_flags_wait);
- }
- }
-
- /*
- * Process Transmit empty.
- */
- if (reason & IFTEM) {
- dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_EMPTY);
- dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_EMPTY);
- if (ch->ch_flags & CH_WEMPTY) {
- ch->ch_flags &= ~CH_WEMPTY;
- wake_up_interruptible(&ch->ch_flags_wait);
- }
- }
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
-
-next:
- tail = (tail + 4) & (EVMAX - EVSTART - 4);
- }
-
- writew(tail, &eaddr->ev_tail);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return 0;
-}
-
-/*
- * Our board poller function.
- */
-static void dgap_poll_tasklet(unsigned long data)
-{
- struct board_t *bd = (struct board_t *)data;
- ulong lock_flags;
- char __iomem *vaddr;
- u16 head, tail;
-
- if (!bd || (bd->magic != DGAP_BOARD_MAGIC))
- return;
-
- if (bd->inhibit_poller)
- return;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
-
- vaddr = bd->re_map_membase;
-
- /*
- * If board is ready, parse deeper to see if there is anything to do.
- */
- if (bd->state == BOARD_READY) {
- struct ev_t __iomem *eaddr;
-
- if (!bd->re_map_membase) {
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return;
- }
- if (!bd->re_map_port) {
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return;
- }
-
- if (!bd->nasync)
- goto out;
-
- eaddr = (struct ev_t __iomem *)(vaddr + EVBUF);
-
- /* Get our head and tail */
- head = readw(&eaddr->ev_head);
- tail = readw(&eaddr->ev_tail);
-
- /*
- * If there is an event pending. Go service it.
- */
- if (head != tail) {
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- dgap_event(bd);
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- }
-
-out:
- /*
- * If board is doing interrupts, ACK the interrupt.
- */
- if (bd->intr_running)
- readb(bd->re_map_port + 2);
-
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return;
- }
-
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-}
-
-/*
- * dgap_found_board()
- *
- * A board has been found, init it.
- */
-static struct board_t *dgap_found_board(struct pci_dev *pdev, int id,
- int boardnum)
-{
- struct board_t *brd;
- unsigned int pci_irq;
- int i;
- int ret;
-
- /* get the board structure and prep it */
- brd = kzalloc(sizeof(struct board_t), GFP_KERNEL);
- if (!brd)
- return ERR_PTR(-ENOMEM);
-
- /* store the info for the board we've found */
- brd->magic = DGAP_BOARD_MAGIC;
- brd->boardnum = boardnum;
- brd->vendor = dgap_pci_tbl[id].vendor;
- brd->device = dgap_pci_tbl[id].device;
- brd->pdev = pdev;
- brd->pci_bus = pdev->bus->number;
- brd->pci_slot = PCI_SLOT(pdev->devfn);
- brd->name = dgap_ids[id].name;
- brd->maxports = dgap_ids[id].maxports;
- brd->type = dgap_ids[id].config_type;
- brd->dpatype = dgap_ids[id].dpatype;
- brd->dpastatus = BD_NOFEP;
- init_waitqueue_head(&brd->state_wait);
-
- spin_lock_init(&brd->bd_lock);
-
- brd->inhibit_poller = FALSE;
- brd->wait_for_bios = 0;
- brd->wait_for_fep = 0;
-
- for (i = 0; i < MAXPORTS; i++)
- brd->channels[i] = NULL;
-
- /* store which card & revision we have */
- pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor);
- pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice);
- pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
-
- pci_irq = pdev->irq;
- brd->irq = pci_irq;
-
- /* get the PCI Base Address Registers */
-
- /* Xr Jupiter and EPC use BAR 2 */
- if (brd->device == PCI_DEV_XRJ_DID || brd->device == PCI_DEV_EPCJ_DID) {
- brd->membase = pci_resource_start(pdev, 2);
- brd->membase_end = pci_resource_end(pdev, 2);
- }
- /* Everyone else uses BAR 0 */
- else {
- brd->membase = pci_resource_start(pdev, 0);
- brd->membase_end = pci_resource_end(pdev, 0);
- }
-
- if (!brd->membase) {
- ret = -ENODEV;
- goto free_brd;
- }
-
- if (brd->membase & 1)
- brd->membase &= ~3;
- else
- brd->membase &= ~15;
-
- /*
- * On the PCI boards, there is no IO space allocated
- * The I/O registers will be in the first 3 bytes of the
- * upper 2MB of the 4MB memory space. The board memory
- * will be mapped into the low 2MB of the 4MB memory space
- */
- brd->port = brd->membase + PCI_IO_OFFSET;
- brd->port_end = brd->port + PCI_IO_SIZE_DGAP;
-
- /*
- * Special initialization for non-PLX boards
- */
- if (brd->device != PCI_DEV_XRJ_DID && brd->device != PCI_DEV_EPCJ_DID) {
- unsigned short cmd;
-
- pci_write_config_byte(pdev, 0x40, 0);
- pci_write_config_byte(pdev, 0x46, 0);
-
- /* Limit burst length to 2 doubleword transactions */
- pci_write_config_byte(pdev, 0x42, 1);
-
- /*
- * Enable IO and mem if not already done.
- * This was needed for support on Itanium.
- */
- pci_read_config_word(pdev, PCI_COMMAND, &cmd);
- cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
- pci_write_config_word(pdev, PCI_COMMAND, cmd);
- }
-
- /* init our poll helper tasklet */
- tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet,
- (unsigned long)brd);
-
- ret = dgap_remap(brd);
- if (ret)
- goto free_brd;
-
- pr_info("dgap: board %d: %s (rev %d), irq %ld\n",
- boardnum, brd->name, brd->rev, brd->irq);
-
- return brd;
-
-free_brd:
- kfree(brd);
-
- return ERR_PTR(ret);
-}
-
-/*
- * dgap_intr()
- *
- * Driver interrupt handler.
- */
-static irqreturn_t dgap_intr(int irq, void *voidbrd)
-{
- struct board_t *brd = voidbrd;
-
- if (!brd)
- return IRQ_NONE;
-
- /*
- * Check to make sure its for us.
- */
- if (brd->magic != DGAP_BOARD_MAGIC)
- return IRQ_NONE;
-
- brd->intr_count++;
-
- /*
- * Schedule tasklet to run at a better time.
- */
- tasklet_schedule(&brd->helper_tasklet);
- return IRQ_HANDLED;
-}
-
-/*****************************************************************************
-*
-* Function:
-*
-* dgap_poll_handler
-*
-* Author:
-*
-* Scott H Kilau
-*
-* Parameters:
-*
-* dummy -- ignored
-*
-* Return Values:
-*
-* none
-*
-* Description:
-*
-* As each timer expires, it determines (a) whether the "transmit"
-* waiter needs to be woken up, and (b) whether the poller needs to
-* be rescheduled.
-*
-******************************************************************************/
-
-static void dgap_poll_handler(ulong dummy)
-{
- unsigned int i;
- struct board_t *brd;
- unsigned long lock_flags;
- ulong new_time;
-
- dgap_poll_counter++;
-
- /*
- * Do not start the board state machine until
- * driver tells us its up and running, and has
- * everything it needs.
- */
- if (dgap_driver_state != DRIVER_READY)
- goto schedule_poller;
-
- /*
- * If we have just 1 board, or the system is not SMP,
- * then use the typical old style poller.
- * Otherwise, use our new tasklet based poller, which should
- * speed things up for multiple boards.
- */
- if ((dgap_numboards == 1) || (num_online_cpus() <= 1)) {
- for (i = 0; i < dgap_numboards; i++) {
- brd = dgap_board[i];
-
- if (brd->state == BOARD_FAILED)
- continue;
- if (!brd->intr_running)
- /* Call the real board poller directly */
- dgap_poll_tasklet((unsigned long)brd);
- }
- } else {
- /*
- * Go thru each board, kicking off a
- * tasklet for each if needed
- */
- for (i = 0; i < dgap_numboards; i++) {
- brd = dgap_board[i];
-
- /*
- * Attempt to grab the board lock.
- *
- * If we can't get it, no big deal, the next poll
- * will get it. Basically, I just really don't want
- * to spin in here, because I want to kick off my
- * tasklets as fast as I can, and then get out the
- * poller.
- */
- if (!spin_trylock(&brd->bd_lock))
- continue;
-
- /*
- * If board is in a failed state, don't bother
- * scheduling a tasklet
- */
- if (brd->state == BOARD_FAILED) {
- spin_unlock(&brd->bd_lock);
- continue;
- }
-
- /* Schedule a poll helper task */
- if (!brd->intr_running)
- tasklet_schedule(&brd->helper_tasklet);
-
- /*
- * Can't do DGAP_UNLOCK here, as we don't have
- * lock_flags because we did a trylock above.
- */
- spin_unlock(&brd->bd_lock);
- }
- }
-
-schedule_poller:
-
- /*
- * Schedule ourself back at the nominal wakeup interval.
- */
- spin_lock_irqsave(&dgap_poll_lock, lock_flags);
- dgap_poll_time += dgap_jiffies_from_ms(dgap_poll_tick);
-
- new_time = dgap_poll_time - jiffies;
-
- if ((ulong)new_time >= 2 * dgap_poll_tick) {
- dgap_poll_time =
- jiffies + dgap_jiffies_from_ms(dgap_poll_tick);
- }
-
- dgap_poll_timer.function = dgap_poll_handler;
- dgap_poll_timer.data = 0;
- dgap_poll_timer.expires = dgap_poll_time;
- spin_unlock_irqrestore(&dgap_poll_lock, lock_flags);
-
- if (!dgap_poll_stop)
- add_timer(&dgap_poll_timer);
-}
-
-/*=======================================================================
- *
- * dgap_cmdb - Sends a 2 byte command to the FEP.
- *
- * ch - Pointer to channel structure.
- * cmd - Command to be sent.
- * byte1 - Integer containing first byte to be sent.
- * byte2 - Integer containing second byte to be sent.
- * ncmds - Wait until ncmds or fewer cmds are left
- * in the cmd buffer before returning.
- *
- *=======================================================================*/
-static void dgap_cmdb(struct channel_t *ch, u8 cmd, u8 byte1,
- u8 byte2, uint ncmds)
-{
- char __iomem *vaddr;
- struct __iomem cm_t *cm_addr;
- uint count;
- uint n;
- u16 head;
- u16 tail;
-
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- /*
- * Check if board is still alive.
- */
- if (ch->ch_bd->state == BOARD_FAILED)
- return;
-
- /*
- * Make sure the pointers are in range before
- * writing to the FEP memory.
- */
- vaddr = ch->ch_bd->re_map_membase;
-
- if (!vaddr)
- return;
-
- cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF);
- head = readw(&cm_addr->cm_head);
-
- /*
- * Forget it if pointers out of range.
- */
- if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
- ch->ch_bd->state = BOARD_FAILED;
- return;
- }
-
- /*
- * Put the data in the circular command buffer.
- */
- writeb(cmd, (vaddr + head + CMDSTART + 0));
- writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1));
- writeb(byte1, (vaddr + head + CMDSTART + 2));
- writeb(byte2, (vaddr + head + CMDSTART + 3));
-
- head = (head + 4) & (CMDMAX - CMDSTART - 4);
-
- writew(head, &cm_addr->cm_head);
-
- /*
- * Wait if necessary before updating the head
- * pointer to limit the number of outstanding
- * commands to the FEP. If the time spent waiting
- * is outlandish, declare the FEP dead.
- */
- for (count = dgap_count ;;) {
- head = readw(&cm_addr->cm_head);
- tail = readw(&cm_addr->cm_tail);
-
- n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
- if (n <= ncmds * sizeof(struct cm_t))
- break;
-
- if (--count == 0) {
- ch->ch_bd->state = BOARD_FAILED;
- return;
- }
- udelay(10);
- }
-}
-
-/*=======================================================================
- *
- * dgap_cmdw - Sends a 1 word command to the FEP.
- *
- * ch - Pointer to channel structure.
- * cmd - Command to be sent.
- * word - Integer containing word to be sent.
- * ncmds - Wait until ncmds or fewer cmds are left
- * in the cmd buffer before returning.
- *
- *=======================================================================*/
-static void dgap_cmdw(struct channel_t *ch, u8 cmd, u16 word, uint ncmds)
-{
- char __iomem *vaddr;
- struct __iomem cm_t *cm_addr;
- uint count;
- uint n;
- u16 head;
- u16 tail;
-
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- /*
- * Check if board is still alive.
- */
- if (ch->ch_bd->state == BOARD_FAILED)
- return;
-
- /*
- * Make sure the pointers are in range before
- * writing to the FEP memory.
- */
- vaddr = ch->ch_bd->re_map_membase;
- if (!vaddr)
- return;
-
- cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF);
- head = readw(&cm_addr->cm_head);
-
- /*
- * Forget it if pointers out of range.
- */
- if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
- ch->ch_bd->state = BOARD_FAILED;
- return;
- }
-
- /*
- * Put the data in the circular command buffer.
- */
- writeb(cmd, (vaddr + head + CMDSTART + 0));
- writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1));
- writew((u16)word, (vaddr + head + CMDSTART + 2));
-
- head = (head + 4) & (CMDMAX - CMDSTART - 4);
-
- writew(head, &cm_addr->cm_head);
-
- /*
- * Wait if necessary before updating the head
- * pointer to limit the number of outstanding
- * commands to the FEP. If the time spent waiting
- * is outlandish, declare the FEP dead.
- */
- for (count = dgap_count ;;) {
- head = readw(&cm_addr->cm_head);
- tail = readw(&cm_addr->cm_tail);
-
- n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
- if (n <= ncmds * sizeof(struct cm_t))
- break;
-
- if (--count == 0) {
- ch->ch_bd->state = BOARD_FAILED;
- return;
- }
- udelay(10);
- }
-}
-
-/*=======================================================================
- *
- * dgap_cmdw_ext - Sends a extended word command to the FEP.
- *
- * ch - Pointer to channel structure.
- * cmd - Command to be sent.
- * word - Integer containing word to be sent.
- * ncmds - Wait until ncmds or fewer cmds are left
- * in the cmd buffer before returning.
- *
- *=======================================================================*/
-static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds)
-{
- char __iomem *vaddr;
- struct __iomem cm_t *cm_addr;
- uint count;
- uint n;
- u16 head;
- u16 tail;
-
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- /*
- * Check if board is still alive.
- */
- if (ch->ch_bd->state == BOARD_FAILED)
- return;
-
- /*
- * Make sure the pointers are in range before
- * writing to the FEP memory.
- */
- vaddr = ch->ch_bd->re_map_membase;
- if (!vaddr)
- return;
-
- cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF);
- head = readw(&cm_addr->cm_head);
-
- /*
- * Forget it if pointers out of range.
- */
- if (head >= (CMDMAX - CMDSTART) || (head & 03)) {
- ch->ch_bd->state = BOARD_FAILED;
- return;
- }
-
- /*
- * Put the data in the circular command buffer.
- */
-
- /* Write an FF to tell the FEP that we want an extended command */
- writeb((u8)0xff, (vaddr + head + CMDSTART + 0));
-
- writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1));
- writew((u16)cmd, (vaddr + head + CMDSTART + 2));
-
- /*
- * If the second part of the command won't fit,
- * put it at the beginning of the circular buffer.
- */
- if (((head + 4) >= ((CMDMAX - CMDSTART)) || (head & 03)))
- writew((u16)word, (vaddr + CMDSTART));
- else
- writew((u16)word, (vaddr + head + CMDSTART + 4));
-
- head = (head + 8) & (CMDMAX - CMDSTART - 4);
-
- writew(head, &cm_addr->cm_head);
-
- /*
- * Wait if necessary before updating the head
- * pointer to limit the number of outstanding
- * commands to the FEP. If the time spent waiting
- * is outlandish, declare the FEP dead.
- */
- for (count = dgap_count ;;) {
- head = readw(&cm_addr->cm_head);
- tail = readw(&cm_addr->cm_tail);
-
- n = (head - tail) & (CMDMAX - CMDSTART - 4);
-
- if (n <= ncmds * sizeof(struct cm_t))
- break;
-
- if (--count == 0) {
- ch->ch_bd->state = BOARD_FAILED;
- return;
- }
- udelay(10);
- }
-}
-
-/*=======================================================================
- *
- * dgap_wmove - Write data to FEP buffer.
- *
- * ch - Pointer to channel structure.
- * buf - Pointer to characters to be moved.
- * cnt - Number of characters to move.
- *
- *=======================================================================*/
-static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt)
-{
- int n;
- char __iomem *taddr;
- struct bs_t __iomem *bs;
- u16 head;
-
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- /*
- * Check parameters.
- */
- bs = ch->ch_bs;
- head = readw(&bs->tx_head);
-
- /*
- * If pointers are out of range, just return.
- */
- if ((cnt > ch->ch_tsize) ||
- (unsigned)(head - ch->ch_tstart) >= ch->ch_tsize)
- return;
-
- /*
- * If the write wraps over the top of the circular buffer,
- * move the portion up to the wrap point, and reset the
- * pointers to the bottom.
- */
- n = ch->ch_tstart + ch->ch_tsize - head;
-
- if (cnt >= n) {
- cnt -= n;
- taddr = ch->ch_taddr + head;
- memcpy_toio(taddr, buf, n);
- head = ch->ch_tstart;
- buf += n;
- }
-
- /*
- * Move rest of data.
- */
- taddr = ch->ch_taddr + head;
- n = cnt;
- memcpy_toio(taddr, buf, n);
- head += cnt;
-
- writew(head, &bs->tx_head);
-}
-
-/*
- * Calls the firmware to reset this channel.
- */
-static void dgap_firmware_reset_port(struct channel_t *ch)
-{
- dgap_cmdb(ch, CHRESET, 0, 0, 0);
-
- /*
- * Now that the channel is reset, we need to make sure
- * all the current settings get reapplied to the port
- * in the firmware.
- *
- * So we will set the driver's cache of firmware
- * settings all to 0, and then call param.
- */
- ch->ch_fepiflag = 0;
- ch->ch_fepcflag = 0;
- ch->ch_fepoflag = 0;
- ch->ch_fepstartc = 0;
- ch->ch_fepstopc = 0;
- ch->ch_fepastartc = 0;
- ch->ch_fepastopc = 0;
- ch->ch_mostat = 0;
- ch->ch_hflow = 0;
-}
-
-/*=======================================================================
- *
- * dgap_param - Set Digi parameters.
- *
- * struct tty_struct * - TTY for port.
- *
- *=======================================================================*/
-static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type)
-{
- u16 head;
- u16 cflag;
- u16 iflag;
- u8 mval;
- u8 hflow;
-
- /*
- * If baud rate is zero, flush queues, and set mval to drop DTR.
- */
- if ((ch->ch_c_cflag & (CBAUD)) == 0) {
- /* flush rx */
- head = readw(&ch->ch_bs->rx_head);
- writew(head, &ch->ch_bs->rx_tail);
-
- /* flush tx */
- head = readw(&ch->ch_bs->tx_head);
- writew(head, &ch->ch_bs->tx_tail);
-
- ch->ch_flags |= (CH_BAUD0);
-
- /* Drop RTS and DTR */
- ch->ch_mval &= ~(D_RTS(ch) | D_DTR(ch));
- mval = D_DTR(ch) | D_RTS(ch);
- ch->ch_baud_info = 0;
-
- } else if (ch->ch_custom_speed && (bd->bd_flags & BD_FEP5PLUS)) {
- /*
- * Tell the fep to do the command
- */
-
- dgap_cmdw_ext(ch, 0xff01, ch->ch_custom_speed, 0);
-
- /*
- * Now go get from fep mem, what the fep
- * believes the custom baud rate is.
- */
- ch->ch_custom_speed = dgap_get_custom_baud(ch);
- ch->ch_baud_info = ch->ch_custom_speed;
-
- /* Handle transition from B0 */
- if (ch->ch_flags & CH_BAUD0) {
- ch->ch_flags &= ~(CH_BAUD0);
- ch->ch_mval |= (D_RTS(ch) | D_DTR(ch));
- }
- mval = D_DTR(ch) | D_RTS(ch);
-
- } else {
- /*
- * Set baud rate, character size, and parity.
- */
-
-
- int iindex = 0;
- int jindex = 0;
- int baud = 0;
-
- ulong bauds[4][16] = {
- { /* slowbaud */
- 0, 50, 75, 110,
- 134, 150, 200, 300,
- 600, 1200, 1800, 2400,
- 4800, 9600, 19200, 38400 },
- { /* slowbaud & CBAUDEX */
- 0, 57600, 115200, 230400,
- 460800, 150, 200, 921600,
- 600, 1200, 1800, 2400,
- 4800, 9600, 19200, 38400 },
- { /* fastbaud */
- 0, 57600, 76800, 115200,
- 14400, 57600, 230400, 76800,
- 115200, 230400, 28800, 460800,
- 921600, 9600, 19200, 38400 },
- { /* fastbaud & CBAUDEX */
- 0, 57600, 115200, 230400,
- 460800, 150, 200, 921600,
- 600, 1200, 1800, 2400,
- 4800, 9600, 19200, 38400 }
- };
-
- /*
- * Only use the TXPrint baud rate if the
- * terminal unit is NOT open
- */
- if (!(ch->ch_tun.un_flags & UN_ISOPEN) &&
- un_type == DGAP_PRINT)
- baud = C_BAUD(ch->ch_pun.un_tty) & 0xff;
- else
- baud = C_BAUD(ch->ch_tun.un_tty) & 0xff;
-
- if (ch->ch_c_cflag & CBAUDEX)
- iindex = 1;
-
- if (ch->ch_digi.digi_flags & DIGI_FAST)
- iindex += 2;
-
- jindex = baud;
-
- if ((iindex >= 0) && (iindex < 4) &&
- (jindex >= 0) && (jindex < 16))
- baud = bauds[iindex][jindex];
- else
- baud = 0;
-
- if (baud == 0)
- baud = 9600;
-
- ch->ch_baud_info = baud;
-
- /*
- * CBAUD has bit position 0x1000 set these days to
- * indicate Linux baud rate remap.
- * We use a different bit assignment for high speed.
- * Clear this bit out while grabbing the parts of
- * "cflag" we want.
- */
- cflag = ch->ch_c_cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB |
- CSTOPB | CSIZE);
-
- /*
- * HUPCL bit is used by FEP to indicate fast baud
- * table is to be used.
- */
- if ((ch->ch_digi.digi_flags & DIGI_FAST) ||
- (ch->ch_c_cflag & CBAUDEX))
- cflag |= HUPCL;
-
- if ((ch->ch_c_cflag & CBAUDEX) &&
- !(ch->ch_digi.digi_flags & DIGI_FAST)) {
- /*
- * The below code is trying to guarantee that only
- * baud rates 115200, 230400, 460800, 921600 are
- * remapped. We use exclusive or because the various
- * baud rates share common bit positions and therefore
- * can't be tested for easily.
- */
- tcflag_t tcflag = (ch->ch_c_cflag & CBAUD) | CBAUDEX;
- int baudpart = 0;
-
- /*
- * Map high speed requests to index
- * into FEP's baud table
- */
- switch (tcflag) {
- case B57600:
- baudpart = 1;
- break;
-#ifdef B76800
- case B76800:
- baudpart = 2;
- break;
-#endif
- case B115200:
- baudpart = 3;
- break;
- case B230400:
- baudpart = 9;
- break;
- case B460800:
- baudpart = 11;
- break;
-#ifdef B921600
- case B921600:
- baudpart = 12;
- break;
-#endif
- default:
- baudpart = 0;
- }
-
- if (baudpart)
- cflag = (cflag & ~(CBAUD | CBAUDEX)) | baudpart;
- }
-
- cflag &= 0xffff;
-
- if (cflag != ch->ch_fepcflag) {
- ch->ch_fepcflag = (u16)(cflag & 0xffff);
-
- /*
- * Okay to have channel and board
- * locks held calling this
- */
- dgap_cmdw(ch, SCFLAG, (u16)cflag, 0);
- }
-
- /* Handle transition from B0 */
- if (ch->ch_flags & CH_BAUD0) {
- ch->ch_flags &= ~(CH_BAUD0);
- ch->ch_mval |= (D_RTS(ch) | D_DTR(ch));
- }
- mval = D_DTR(ch) | D_RTS(ch);
- }
-
- /*
- * Get input flags.
- */
- iflag = ch->ch_c_iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
- INPCK | ISTRIP | IXON | IXANY | IXOFF);
-
- if ((ch->ch_startc == _POSIX_VDISABLE) ||
- (ch->ch_stopc == _POSIX_VDISABLE)) {
- iflag &= ~(IXON | IXOFF);
- ch->ch_c_iflag &= ~(IXON | IXOFF);
- }
-
- /*
- * Only the IBM Xr card can switch between
- * 232 and 422 modes on the fly
- */
- if (bd->device == PCI_DEV_XR_IBM_DID) {
- if (ch->ch_digi.digi_flags & DIGI_422)
- dgap_cmdb(ch, SCOMMODE, MODE_422, 0, 0);
- else
- dgap_cmdb(ch, SCOMMODE, MODE_232, 0, 0);
- }
-
- if (ch->ch_digi.digi_flags & DIGI_ALTPIN)
- iflag |= IALTPIN;
-
- if (iflag != ch->ch_fepiflag) {
- ch->ch_fepiflag = iflag;
-
- /* Okay to have channel and board locks held calling this */
- dgap_cmdw(ch, SIFLAG, (u16)ch->ch_fepiflag, 0);
- }
-
- /*
- * Select hardware handshaking.
- */
- hflow = 0;
-
- if (ch->ch_c_cflag & CRTSCTS)
- hflow |= (D_RTS(ch) | D_CTS(ch));
- if (ch->ch_digi.digi_flags & RTSPACE)
- hflow |= D_RTS(ch);
- if (ch->ch_digi.digi_flags & DTRPACE)
- hflow |= D_DTR(ch);
- if (ch->ch_digi.digi_flags & CTSPACE)
- hflow |= D_CTS(ch);
- if (ch->ch_digi.digi_flags & DSRPACE)
- hflow |= D_DSR(ch);
- if (ch->ch_digi.digi_flags & DCDPACE)
- hflow |= D_CD(ch);
-
- if (hflow != ch->ch_hflow) {
- ch->ch_hflow = hflow;
-
- /* Okay to have channel and board locks held calling this */
- dgap_cmdb(ch, SHFLOW, (u8)hflow, 0xff, 0);
- }
-
- /*
- * Set RTS and/or DTR Toggle if needed,
- * but only if product is FEP5+ based.
- */
- if (bd->bd_flags & BD_FEP5PLUS) {
- u16 hflow2 = 0;
-
- if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)
- hflow2 |= (D_RTS(ch));
- if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)
- hflow2 |= (D_DTR(ch));
-
- dgap_cmdw_ext(ch, 0xff03, hflow2, 0);
- }
-
- /*
- * Set modem control lines.
- */
-
- mval ^= ch->ch_mforce & (mval ^ ch->ch_mval);
-
- if (ch->ch_mostat ^ mval) {
- ch->ch_mostat = mval;
-
- /* Okay to have channel and board locks held calling this */
- dgap_cmdb(ch, SMODEM, (u8)mval, D_RTS(ch) | D_DTR(ch), 0);
- }
-
- /*
- * Read modem signals, and then call carrier function.
- */
- ch->ch_mistat = readb(&ch->ch_bs->m_stat);
- dgap_carrier(ch);
-
- /*
- * Set the start and stop characters.
- */
- if (ch->ch_startc != ch->ch_fepstartc ||
- ch->ch_stopc != ch->ch_fepstopc) {
- ch->ch_fepstartc = ch->ch_startc;
- ch->ch_fepstopc = ch->ch_stopc;
-
- /* Okay to have channel and board locks held calling this */
- dgap_cmdb(ch, SFLOWC, ch->ch_fepstartc, ch->ch_fepstopc, 0);
- }
-
- /*
- * Set the Auxiliary start and stop characters.
- */
- if (ch->ch_astartc != ch->ch_fepastartc ||
- ch->ch_astopc != ch->ch_fepastopc) {
- ch->ch_fepastartc = ch->ch_astartc;
- ch->ch_fepastopc = ch->ch_astopc;
-
- /* Okay to have channel and board locks held calling this */
- dgap_cmdb(ch, SAFLOWC, ch->ch_fepastartc, ch->ch_fepastopc, 0);
- }
-
- return 0;
-}
-
-/*
- * dgap_block_til_ready()
- *
- * Wait for DCD, if needed.
- */
-static int dgap_block_til_ready(struct tty_struct *tty, struct file *file,
- struct channel_t *ch)
-{
- int retval = 0;
- struct un_t *un;
- ulong lock_flags;
- uint old_flags;
- int sleep_on_un_flags;
-
- if (!tty || tty->magic != TTY_MAGIC || !file || !ch ||
- ch->magic != DGAP_CHANNEL_MAGIC)
- return -EIO;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return -EIO;
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
-
- ch->ch_wopen++;
-
- /* Loop forever */
- while (1) {
- sleep_on_un_flags = 0;
-
- /*
- * If board has failed somehow during our sleep,
- * bail with error.
- */
- if (ch->ch_bd->state == BOARD_FAILED) {
- retval = -EIO;
- break;
- }
-
- /* If tty was hung up, break out of loop and set error. */
- if (tty_hung_up_p(file)) {
- retval = -EAGAIN;
- break;
- }
-
- /*
- * If either unit is in the middle of the fragile part of close,
- * we just cannot touch the channel safely.
- * Go back to sleep, knowing that when the channel can be
- * touched safely, the close routine will signal the
- * ch_wait_flags to wake us back up.
- */
- if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) &
- UN_CLOSING)) {
- /*
- * Our conditions to leave cleanly and happily:
- * 1) NONBLOCKING on the tty is set.
- * 2) CLOCAL is set.
- * 3) DCD (fake or real) is active.
- */
-
- if (file->f_flags & O_NONBLOCK)
- break;
-
- if (tty->flags & (1 << TTY_IO_ERROR))
- break;
-
- if (ch->ch_flags & CH_CD)
- break;
-
- if (ch->ch_flags & CH_FCAR)
- break;
- } else {
- sleep_on_un_flags = 1;
- }
-
- /*
- * If there is a signal pending, the user probably
- * interrupted (ctrl-c) us.
- * Leave loop with error set.
- */
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
-
- /*
- * Store the flags before we let go of channel lock
- */
- if (sleep_on_un_flags)
- old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags;
- else
- old_flags = ch->ch_flags;
-
- /*
- * Let go of channel lock before calling schedule.
- * Our poller will get any FEP events and wake us up when DCD
- * eventually goes active.
- */
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- /*
- * Wait for something in the flags to change
- * from the current value.
- */
- if (sleep_on_un_flags) {
- retval = wait_event_interruptible(un->un_flags_wait,
- (old_flags != (ch->ch_tun.un_flags |
- ch->ch_pun.un_flags)));
- } else {
- retval = wait_event_interruptible(ch->ch_flags_wait,
- (old_flags != ch->ch_flags));
- }
-
- /*
- * We got woken up for some reason.
- * Before looping around, grab our channel lock.
- */
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- }
-
- ch->ch_wopen--;
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- return retval;
-}
-
-/*
- * dgap_tty_flush_buffer()
- *
- * Flush Tx buffer (make in == out)
- */
-static void dgap_tty_flush_buffer(struct tty_struct *tty)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- ulong lock_flags;
- ulong lock_flags2;
- u16 head;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- ch->ch_flags &= ~CH_STOP;
- head = readw(&ch->ch_bs->tx_head);
- dgap_cmdw(ch, FLUSHTX, (u16)head, 0);
- dgap_cmdw(ch, RESUMETX, 0, 0);
- if (ch->ch_tun.un_flags & (UN_LOW | UN_EMPTY)) {
- ch->ch_tun.un_flags &= ~(UN_LOW | UN_EMPTY);
- wake_up_interruptible(&ch->ch_tun.un_flags_wait);
- }
- if (ch->ch_pun.un_flags & (UN_LOW | UN_EMPTY)) {
- ch->ch_pun.un_flags &= ~(UN_LOW | UN_EMPTY);
- wake_up_interruptible(&ch->ch_pun.un_flags_wait);
- }
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- tty_wakeup(tty);
-}
-
-/*
- * dgap_tty_hangup()
- *
- * Hangup the port. Like a close, but don't wait for output to drain.
- */
-static void dgap_tty_hangup(struct tty_struct *tty)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- /* flush the transmit queues */
- dgap_tty_flush_buffer(tty);
-}
-
-/*
- * dgap_tty_chars_in_buffer()
- *
- * Return number of characters that have not been transmitted yet.
- *
- * This routine is used by the line discipline to determine if there
- * is data waiting to be transmitted/drained/flushed or not.
- */
-static int dgap_tty_chars_in_buffer(struct tty_struct *tty)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- struct bs_t __iomem *bs;
- u8 tbusy;
- uint chars;
- u16 thead, ttail, tmask, chead, ctail;
- ulong lock_flags = 0;
- ulong lock_flags2 = 0;
-
- if (!tty)
- return 0;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
-
- bs = ch->ch_bs;
- if (!bs)
- return 0;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- tmask = (ch->ch_tsize - 1);
-
- /* Get Transmit queue pointers */
- thead = readw(&bs->tx_head) & tmask;
- ttail = readw(&bs->tx_tail) & tmask;
-
- /* Get tbusy flag */
- tbusy = readb(&bs->tbusy);
-
- /* Get Command queue pointers */
- chead = readw(&ch->ch_cm->cm_head);
- ctail = readw(&ch->ch_cm->cm_tail);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- /*
- * The only way we know for sure if there is no pending
- * data left to be transferred, is if:
- * 1) Transmit head and tail are equal (empty).
- * 2) Command queue head and tail are equal (empty).
- * 3) The "TBUSY" flag is 0. (Transmitter not busy).
- */
-
- if ((ttail == thead) && (tbusy == 0) && (chead == ctail)) {
- chars = 0;
- } else {
- if (thead >= ttail)
- chars = thead - ttail;
- else
- chars = thead - ttail + ch->ch_tsize;
- /*
- * Fudge factor here.
- * If chars is zero, we know that the command queue had
- * something in it or tbusy was set. Because we cannot
- * be sure if there is still some data to be transmitted,
- * lets lie, and tell ld we have 1 byte left.
- */
- if (chars == 0) {
- /*
- * If TBUSY is still set, and our tx buffers are empty,
- * force the firmware to send me another wakeup after
- * TBUSY has been cleared.
- */
- if (tbusy != 0) {
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- un->un_flags |= UN_EMPTY;
- writeb(1, &bs->iempty);
- spin_unlock_irqrestore(&ch->ch_lock,
- lock_flags);
- }
- chars = 1;
- }
- }
-
- return chars;
-}
-
-static int dgap_wait_for_drain(struct tty_struct *tty)
-{
- struct channel_t *ch;
- struct un_t *un;
- struct bs_t __iomem *bs;
- int ret = 0;
- uint count = 1;
- ulong lock_flags = 0;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return -EIO;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return -EIO;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return -EIO;
-
- bs = ch->ch_bs;
- if (!bs)
- return -EIO;
-
- /* Loop until data is drained */
- while (count != 0) {
- count = dgap_tty_chars_in_buffer(tty);
-
- if (count == 0)
- break;
-
- /* Set flag waiting for drain */
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- un->un_flags |= UN_EMPTY;
- writeb(1, &bs->iempty);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- /* Go to sleep till we get woken up */
- ret = wait_event_interruptible(un->un_flags_wait,
- ((un->un_flags & UN_EMPTY) == 0));
- /* If ret is non-zero, user ctrl-c'ed us */
- if (ret)
- break;
- }
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- un->un_flags &= ~(UN_EMPTY);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- return ret;
-}
-
-/*
- * dgap_maxcps_room
- *
- * Reduces bytes_available to the max number of characters
- * that can be sent currently given the maxcps value, and
- * returns the new bytes_available. This only affects printer
- * output.
- */
-static int dgap_maxcps_room(struct channel_t *ch, struct un_t *un,
- int bytes_available)
-{
- /*
- * If its not the Transparent print device, return
- * the full data amount.
- */
- if (un->un_type != DGAP_PRINT)
- return bytes_available;
-
- if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0) {
- int cps_limit = 0;
- unsigned long current_time = jiffies;
- unsigned long buffer_time = current_time +
- (HZ * ch->ch_digi.digi_bufsize) /
- ch->ch_digi.digi_maxcps;
-
- if (ch->ch_cpstime < current_time) {
- /* buffer is empty */
- ch->ch_cpstime = current_time; /* reset ch_cpstime */
- cps_limit = ch->ch_digi.digi_bufsize;
- } else if (ch->ch_cpstime < buffer_time) {
- /* still room in the buffer */
- cps_limit = ((buffer_time - ch->ch_cpstime) *
- ch->ch_digi.digi_maxcps) / HZ;
- } else {
- /* no room in the buffer */
- cps_limit = 0;
- }
-
- bytes_available = min(cps_limit, bytes_available);
- }
-
- return bytes_available;
-}
-
-static inline void dgap_set_firmware_event(struct un_t *un, unsigned int event)
-{
- struct channel_t *ch;
- struct bs_t __iomem *bs;
-
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
- bs = ch->ch_bs;
- if (!bs)
- return;
-
- if ((event & UN_LOW) != 0) {
- if ((un->un_flags & UN_LOW) == 0) {
- un->un_flags |= UN_LOW;
- writeb(1, &bs->ilow);
- }
- }
- if ((event & UN_LOW) != 0) {
- if ((un->un_flags & UN_EMPTY) == 0) {
- un->un_flags |= UN_EMPTY;
- writeb(1, &bs->iempty);
- }
- }
-}
-
-/*
- * dgap_tty_write_room()
- *
- * Return space available in Tx buffer
- */
-static int dgap_tty_write_room(struct tty_struct *tty)
-{
- struct channel_t *ch;
- struct un_t *un;
- struct bs_t __iomem *bs;
- u16 head, tail, tmask;
- int ret;
- ulong lock_flags = 0;
-
- if (!tty)
- return 0;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
-
- bs = ch->ch_bs;
- if (!bs)
- return 0;
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
-
- tmask = ch->ch_tsize - 1;
- head = readw(&bs->tx_head) & tmask;
- tail = readw(&bs->tx_tail) & tmask;
-
- ret = tail - head - 1;
- if (ret < 0)
- ret += ch->ch_tsize;
-
- /* Limit printer to maxcps */
- ret = dgap_maxcps_room(ch, un, ret);
-
- /*
- * If we are printer device, leave space for
- * possibly both the on and off strings.
- */
- if (un->un_type == DGAP_PRINT) {
- if (!(ch->ch_flags & CH_PRON))
- ret -= ch->ch_digi.digi_onlen;
- ret -= ch->ch_digi.digi_offlen;
- } else {
- if (ch->ch_flags & CH_PRON)
- ret -= ch->ch_digi.digi_offlen;
- }
-
- if (ret < 0)
- ret = 0;
-
- /*
- * Schedule FEP to wake us up if needed.
- *
- * TODO: This might be overkill...
- * Do we really need to schedule callbacks from the FEP
- * in every case? Can we get smarter based on ret?
- */
- dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- return ret;
-}
-
-/*
- * dgap_tty_write()
- *
- * Take data from the user or kernel and send it out to the FEP.
- * In here exists all the Transparent Print magic as well.
- */
-static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf,
- int count)
-{
- struct channel_t *ch;
- struct un_t *un;
- struct bs_t __iomem *bs;
- char __iomem *vaddr;
- u16 head, tail, tmask, remain;
- int bufcount, n;
- ulong lock_flags;
-
- if (!tty)
- return 0;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
-
- bs = ch->ch_bs;
- if (!bs)
- return 0;
-
- if (!count)
- return 0;
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
-
- /* Get our space available for the channel from the board */
- tmask = ch->ch_tsize - 1;
- head = readw(&(bs->tx_head)) & tmask;
- tail = readw(&(bs->tx_tail)) & tmask;
-
- bufcount = tail - head - 1;
- if (bufcount < 0)
- bufcount += ch->ch_tsize;
-
- /*
- * Limit printer output to maxcps overall, with bursts allowed
- * up to bufsize characters.
- */
- bufcount = dgap_maxcps_room(ch, un, bufcount);
-
- /*
- * Take minimum of what the user wants to send, and the
- * space available in the FEP buffer.
- */
- count = min(count, bufcount);
-
- /*
- * Bail if no space left.
- */
- if (count <= 0) {
- dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- return 0;
- }
-
- /*
- * Output the printer ON string, if we are in terminal mode, but
- * need to be in printer mode.
- */
- if ((un->un_type == DGAP_PRINT) && !(ch->ch_flags & CH_PRON)) {
- dgap_wmove(ch, ch->ch_digi.digi_onstr,
- (int)ch->ch_digi.digi_onlen);
- head = readw(&bs->tx_head) & tmask;
- ch->ch_flags |= CH_PRON;
- }
-
- /*
- * On the other hand, output the printer OFF string, if we are
- * currently in printer mode, but need to output to the terminal.
- */
- if ((un->un_type != DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
- dgap_wmove(ch, ch->ch_digi.digi_offstr,
- (int)ch->ch_digi.digi_offlen);
- head = readw(&bs->tx_head) & tmask;
- ch->ch_flags &= ~CH_PRON;
- }
-
- n = count;
-
- /*
- * If the write wraps over the top of the circular buffer,
- * move the portion up to the wrap point, and reset the
- * pointers to the bottom.
- */
- remain = ch->ch_tstart + ch->ch_tsize - head;
-
- if (n >= remain) {
- n -= remain;
- vaddr = ch->ch_taddr + head;
-
- memcpy_toio(vaddr, (u8 *)buf, remain);
-
- head = ch->ch_tstart;
- buf += remain;
- }
-
- if (n > 0) {
- /*
- * Move rest of data.
- */
- vaddr = ch->ch_taddr + head;
- remain = n;
-
- memcpy_toio(vaddr, (u8 *)buf, remain);
- head += remain;
- }
-
- if (count) {
- ch->ch_txcount += count;
- head &= tmask;
- writew(head, &bs->tx_head);
- }
-
- dgap_set_firmware_event(un, UN_LOW | UN_EMPTY);
-
- /*
- * If this is the print device, and the
- * printer is still on, we need to turn it
- * off before going idle. If the buffer is
- * non-empty, wait until it goes empty.
- * Otherwise turn it off right now.
- */
- if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
- tail = readw(&bs->tx_tail) & tmask;
-
- if (tail != head) {
- un->un_flags |= UN_EMPTY;
- writeb(1, &bs->iempty);
- } else {
- dgap_wmove(ch, ch->ch_digi.digi_offstr,
- (int)ch->ch_digi.digi_offlen);
- head = readw(&bs->tx_head) & tmask;
- ch->ch_flags &= ~CH_PRON;
- }
- }
-
- /* Update printer buffer empty time. */
- if ((un->un_type == DGAP_PRINT) && (ch->ch_digi.digi_maxcps > 0)
- && (ch->ch_digi.digi_bufsize > 0)) {
- ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps;
- }
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- return count;
-}
-
-/*
- * dgap_tty_put_char()
- *
- * Put a character into ch->ch_buf
- *
- * - used by the line discipline for OPOST processing
- */
-static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c)
-{
- /*
- * Simply call tty_write.
- */
- dgap_tty_write(tty, &c, 1);
- return 1;
-}
-
-/*
- * Return modem signals to ld.
- */
-static int dgap_tty_tiocmget(struct tty_struct *tty)
-{
- struct channel_t *ch;
- struct un_t *un;
- int result;
- u8 mstat;
- ulong lock_flags;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return -EIO;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return -EIO;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return -EIO;
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
-
- mstat = readb(&ch->ch_bs->m_stat);
- /* Append any outbound signals that might be pending... */
- mstat |= ch->ch_mostat;
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- result = 0;
-
- if (mstat & D_DTR(ch))
- result |= TIOCM_DTR;
- if (mstat & D_RTS(ch))
- result |= TIOCM_RTS;
- if (mstat & D_CTS(ch))
- result |= TIOCM_CTS;
- if (mstat & D_DSR(ch))
- result |= TIOCM_DSR;
- if (mstat & D_RI(ch))
- result |= TIOCM_RI;
- if (mstat & D_CD(ch))
- result |= TIOCM_CD;
-
- return result;
-}
-
-/*
- * dgap_tty_tiocmset()
- *
- * Set modem signals, called by ld.
- */
-static int dgap_tty_tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- ulong lock_flags;
- ulong lock_flags2;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return -EIO;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return -EIO;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return -EIO;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return -EIO;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- if (set & TIOCM_RTS) {
- ch->ch_mforce |= D_RTS(ch);
- ch->ch_mval |= D_RTS(ch);
- }
-
- if (set & TIOCM_DTR) {
- ch->ch_mforce |= D_DTR(ch);
- ch->ch_mval |= D_DTR(ch);
- }
-
- if (clear & TIOCM_RTS) {
- ch->ch_mforce |= D_RTS(ch);
- ch->ch_mval &= ~(D_RTS(ch));
- }
-
- if (clear & TIOCM_DTR) {
- ch->ch_mforce |= D_DTR(ch);
- ch->ch_mval &= ~(D_DTR(ch));
- }
-
- dgap_param(ch, bd, un->un_type);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return 0;
-}
-
-/*
- * dgap_tty_send_break()
- *
- * Send a Break, called by ld.
- */
-static int dgap_tty_send_break(struct tty_struct *tty, int msec)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- ulong lock_flags;
- ulong lock_flags2;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return -EIO;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return -EIO;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return -EIO;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return -EIO;
-
- switch (msec) {
- case -1:
- msec = 0xFFFF;
- break;
- case 0:
- msec = 1;
- break;
- default:
- msec /= 10;
- break;
- }
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-#if 0
- dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0);
-#endif
- dgap_cmdw(ch, SBREAK, (u16)msec, 0);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return 0;
-}
-
-/*
- * dgap_tty_wait_until_sent()
- *
- * wait until data has been transmitted, called by ld.
- */
-static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout)
-{
- dgap_wait_for_drain(tty);
-}
-
-/*
- * dgap_send_xchar()
- *
- * send a high priority character, called by ld.
- */
-static void dgap_tty_send_xchar(struct tty_struct *tty, char c)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- ulong lock_flags;
- ulong lock_flags2;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- /*
- * This is technically what we should do.
- * However, the NIST tests specifically want
- * to see each XON or XOFF character that it
- * sends, so lets just send each character
- * by hand...
- */
-#if 0
- if (c == STOP_CHAR(tty))
- dgap_cmdw(ch, RPAUSE, 0, 0);
- else if (c == START_CHAR(tty))
- dgap_cmdw(ch, RRESUME, 0, 0);
- else
- dgap_wmove(ch, &c, 1);
-#else
- dgap_wmove(ch, &c, 1);
-#endif
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-}
-
-/*
- * Return modem signals to ld.
- */
-static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value)
-{
- int result;
- u8 mstat;
- ulong lock_flags;
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
-
- mstat = readb(&ch->ch_bs->m_stat);
- /* Append any outbound signals that might be pending... */
- mstat |= ch->ch_mostat;
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- result = 0;
-
- if (mstat & D_DTR(ch))
- result |= TIOCM_DTR;
- if (mstat & D_RTS(ch))
- result |= TIOCM_RTS;
- if (mstat & D_CTS(ch))
- result |= TIOCM_CTS;
- if (mstat & D_DSR(ch))
- result |= TIOCM_DSR;
- if (mstat & D_RI(ch))
- result |= TIOCM_RI;
- if (mstat & D_CD(ch))
- result |= TIOCM_CD;
-
- return put_user(result, value);
-}
-
-/*
- * dgap_set_modem_info()
- *
- * Set modem signals, called by ld.
- */
-static int dgap_set_modem_info(struct channel_t *ch, struct board_t *bd,
- struct un_t *un, unsigned int command,
- unsigned int __user *value)
-{
- int ret;
- unsigned int arg;
- ulong lock_flags;
- ulong lock_flags2;
-
- ret = get_user(arg, value);
- if (ret)
- return ret;
-
- switch (command) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS) {
- ch->ch_mforce |= D_RTS(ch);
- ch->ch_mval |= D_RTS(ch);
- }
-
- if (arg & TIOCM_DTR) {
- ch->ch_mforce |= D_DTR(ch);
- ch->ch_mval |= D_DTR(ch);
- }
-
- break;
-
- case TIOCMBIC:
- if (arg & TIOCM_RTS) {
- ch->ch_mforce |= D_RTS(ch);
- ch->ch_mval &= ~(D_RTS(ch));
- }
-
- if (arg & TIOCM_DTR) {
- ch->ch_mforce |= D_DTR(ch);
- ch->ch_mval &= ~(D_DTR(ch));
- }
-
- break;
-
- case TIOCMSET:
- ch->ch_mforce = D_DTR(ch) | D_RTS(ch);
-
- if (arg & TIOCM_RTS)
- ch->ch_mval |= D_RTS(ch);
- else
- ch->ch_mval &= ~(D_RTS(ch));
-
- if (arg & TIOCM_DTR)
- ch->ch_mval |= (D_DTR(ch));
- else
- ch->ch_mval &= ~(D_DTR(ch));
-
- break;
-
- default:
- return -EINVAL;
- }
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- dgap_param(ch, bd, un->un_type);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return 0;
-}
-
-/*
- * dgap_tty_digigeta()
- *
- * Ioctl to get the information for ditty.
- *
- *
- *
- */
-static int dgap_tty_digigeta(struct channel_t *ch,
- struct digi_t __user *retinfo)
-{
- struct digi_t tmp;
- ulong lock_flags;
-
- if (!retinfo)
- return -EFAULT;
-
- memset(&tmp, 0, sizeof(tmp));
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- memcpy(&tmp, &ch->ch_digi, sizeof(tmp));
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
- return -EFAULT;
-
- return 0;
-}
-
-/*
- * dgap_tty_digiseta()
- *
- * Ioctl to set the information for ditty.
- *
- *
- *
- */
-static int dgap_tty_digiseta(struct channel_t *ch, struct board_t *bd,
- struct un_t *un, struct digi_t __user *new_info)
-{
- struct digi_t new_digi;
- ulong lock_flags = 0;
- unsigned long lock_flags2;
-
- if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t)))
- return -EFAULT;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t));
-
- if (ch->ch_digi.digi_maxcps < 1)
- ch->ch_digi.digi_maxcps = 1;
-
- if (ch->ch_digi.digi_maxcps > 10000)
- ch->ch_digi.digi_maxcps = 10000;
-
- if (ch->ch_digi.digi_bufsize < 10)
- ch->ch_digi.digi_bufsize = 10;
-
- if (ch->ch_digi.digi_maxchar < 1)
- ch->ch_digi.digi_maxchar = 1;
-
- if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize)
- ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize;
-
- if (ch->ch_digi.digi_onlen > DIGI_PLEN)
- ch->ch_digi.digi_onlen = DIGI_PLEN;
-
- if (ch->ch_digi.digi_offlen > DIGI_PLEN)
- ch->ch_digi.digi_offlen = DIGI_PLEN;
-
- dgap_param(ch, bd, un->un_type);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return 0;
-}
-
-/*
- * dgap_tty_digigetedelay()
- *
- * Ioctl to get the current edelay setting.
- *
- *
- *
- */
-static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo)
-{
- struct channel_t *ch;
- struct un_t *un;
- int tmp;
- ulong lock_flags;
-
- if (!retinfo)
- return -EFAULT;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return -EFAULT;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return -EFAULT;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return -EFAULT;
-
- memset(&tmp, 0, sizeof(tmp));
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- tmp = readw(&ch->ch_bs->edelay);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
- return -EFAULT;
-
- return 0;
-}
-
-/*
- * dgap_tty_digisetedelay()
- *
- * Ioctl to set the EDELAY setting
- *
- */
-static int dgap_tty_digisetedelay(struct channel_t *ch, struct board_t *bd,
- struct un_t *un, int __user *new_info)
-{
- int new_digi;
- ulong lock_flags;
- ulong lock_flags2;
-
- if (copy_from_user(&new_digi, new_info, sizeof(int)))
- return -EFAULT;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- writew((u16)new_digi, &ch->ch_bs->edelay);
-
- dgap_param(ch, bd, un->un_type);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return 0;
-}
-
-/*
- * dgap_tty_digigetcustombaud()
- *
- * Ioctl to get the current custom baud rate setting.
- */
-static int dgap_tty_digigetcustombaud(struct channel_t *ch, struct un_t *un,
- int __user *retinfo)
-{
- int tmp;
- ulong lock_flags;
-
- if (!retinfo)
- return -EFAULT;
-
- memset(&tmp, 0, sizeof(tmp));
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- tmp = dgap_get_custom_baud(ch);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
- return -EFAULT;
-
- return 0;
-}
-
-/*
- * dgap_tty_digisetcustombaud()
- *
- * Ioctl to set the custom baud rate setting
- */
-static int dgap_tty_digisetcustombaud(struct channel_t *ch, struct board_t *bd,
- struct un_t *un, int __user *new_info)
-{
- uint new_rate;
- ulong lock_flags;
- ulong lock_flags2;
-
- if (copy_from_user(&new_rate, new_info, sizeof(unsigned int)))
- return -EFAULT;
-
- if (bd->bd_flags & BD_FEP5PLUS) {
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- ch->ch_custom_speed = new_rate;
-
- dgap_param(ch, bd, un->un_type);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- }
-
- return 0;
-}
-
-/*
- * dgap_set_termios()
- */
-static void dgap_tty_set_termios(struct tty_struct *tty,
- struct ktermios *old_termios)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- unsigned long lock_flags;
- unsigned long lock_flags2;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- ch->ch_c_cflag = tty->termios.c_cflag;
- ch->ch_c_iflag = tty->termios.c_iflag;
- ch->ch_c_oflag = tty->termios.c_oflag;
- ch->ch_c_lflag = tty->termios.c_lflag;
- ch->ch_startc = tty->termios.c_cc[VSTART];
- ch->ch_stopc = tty->termios.c_cc[VSTOP];
-
- dgap_carrier(ch);
- dgap_param(ch, bd, un->un_type);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-}
-
-static void dgap_tty_throttle(struct tty_struct *tty)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- ulong lock_flags;
- ulong lock_flags2;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- ch->ch_flags |= (CH_RXBLOCK);
-#if 1
- dgap_cmdw(ch, RPAUSE, 0, 0);
-#endif
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-}
-
-static void dgap_tty_unthrottle(struct tty_struct *tty)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- ulong lock_flags;
- ulong lock_flags2;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- ch->ch_flags &= ~(CH_RXBLOCK);
-
-#if 1
- dgap_cmdw(ch, RRESUME, 0, 0);
-#endif
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-}
-
-static struct board_t *find_board_by_major(unsigned int major)
-{
- unsigned int i;
-
- for (i = 0; i < MAXBOARDS; i++) {
- struct board_t *brd = dgap_board[i];
-
- if (!brd)
- return NULL;
- if (major == brd->serial_driver->major ||
- major == brd->print_driver->major)
- return brd;
- }
-
- return NULL;
-}
-
-/************************************************************************
- *
- * TTY Entry points and helper functions
- *
- ************************************************************************/
-
-/*
- * dgap_tty_open()
- *
- */
-static int dgap_tty_open(struct tty_struct *tty, struct file *file)
-{
- struct board_t *brd;
- struct channel_t *ch;
- struct un_t *un;
- struct bs_t __iomem *bs;
- uint major;
- uint minor;
- int rc;
- ulong lock_flags;
- ulong lock_flags2;
- u16 head;
-
- major = MAJOR(tty_devnum(tty));
- minor = MINOR(tty_devnum(tty));
-
- brd = find_board_by_major(major);
- if (!brd)
- return -EIO;
-
- /*
- * If board is not yet up to a state of READY, go to
- * sleep waiting for it to happen or they cancel the open.
- */
- rc = wait_event_interruptible(brd->state_wait,
- (brd->state & BOARD_READY));
-
- if (rc)
- return rc;
-
- spin_lock_irqsave(&brd->bd_lock, lock_flags);
-
- /* The wait above should guarantee this cannot happen */
- if (brd->state != BOARD_READY) {
- spin_unlock_irqrestore(&brd->bd_lock, lock_flags);
- return -EIO;
- }
-
- /* If opened device is greater than our number of ports, bail. */
- if (MINOR(tty_devnum(tty)) > brd->nasync) {
- spin_unlock_irqrestore(&brd->bd_lock, lock_flags);
- return -EIO;
- }
-
- ch = brd->channels[minor];
- if (!ch) {
- spin_unlock_irqrestore(&brd->bd_lock, lock_flags);
- return -EIO;
- }
-
- /* Grab channel lock */
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- /* Figure out our type */
- if (major == brd->serial_driver->major) {
- un = &brd->channels[minor]->ch_tun;
- un->un_type = DGAP_SERIAL;
- } else if (major == brd->print_driver->major) {
- un = &brd->channels[minor]->ch_pun;
- un->un_type = DGAP_PRINT;
- } else {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&brd->bd_lock, lock_flags);
- return -EIO;
- }
-
- /* Store our unit into driver_data, so we always have it available. */
- tty->driver_data = un;
-
- /*
- * Error if channel info pointer is NULL.
- */
- bs = ch->ch_bs;
- if (!bs) {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&brd->bd_lock, lock_flags);
- return -EIO;
- }
-
- /*
- * Initialize tty's
- */
- if (!(un->un_flags & UN_ISOPEN)) {
- /* Store important variables. */
- un->un_tty = tty;
-
- /* Maybe do something here to the TTY struct as well? */
- }
-
- /*
- * Initialize if neither terminal or printer is open.
- */
- if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) {
- ch->ch_mforce = 0;
- ch->ch_mval = 0;
-
- /*
- * Flush input queue.
- */
- head = readw(&bs->rx_head);
- writew(head, &bs->rx_tail);
-
- ch->ch_flags = 0;
- ch->pscan_state = 0;
- ch->pscan_savechar = 0;
-
- ch->ch_c_cflag = tty->termios.c_cflag;
- ch->ch_c_iflag = tty->termios.c_iflag;
- ch->ch_c_oflag = tty->termios.c_oflag;
- ch->ch_c_lflag = tty->termios.c_lflag;
- ch->ch_startc = tty->termios.c_cc[VSTART];
- ch->ch_stopc = tty->termios.c_cc[VSTOP];
-
- /* TODO: flush our TTY struct here? */
- }
-
- dgap_carrier(ch);
- /*
- * Run param in case we changed anything
- */
- dgap_param(ch, brd, un->un_type);
-
- /*
- * follow protocol for opening port
- */
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&brd->bd_lock, lock_flags);
-
- rc = dgap_block_til_ready(tty, file, ch);
-
- if (!un->un_tty)
- return -ENODEV;
-
- /* No going back now, increment our unit and channel counters */
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- ch->ch_open_count++;
- un->un_open_count++;
- un->un_flags |= (UN_ISOPEN);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- return rc;
-}
-
-/*
- * dgap_tty_close()
- *
- */
-static void dgap_tty_close(struct tty_struct *tty, struct file *file)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- ulong lock_flags;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
-
- /*
- * Determine if this is the last close or not - and if we agree about
- * which type of close it is with the Line Discipline
- */
- if ((tty->count == 1) && (un->un_open_count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. un_open_count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- un->un_open_count = 1;
- }
-
- if (--un->un_open_count < 0)
- un->un_open_count = 0;
-
- ch->ch_open_count--;
-
- if (ch->ch_open_count && un->un_open_count) {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
- return;
- }
-
- /* OK, its the last close on the unit */
-
- un->un_flags |= UN_CLOSING;
-
- tty->closing = 1;
-
- /*
- * Only officially close channel if count is 0 and
- * DIGI_PRINTER bit is not set.
- */
- if ((ch->ch_open_count == 0) &&
- !(ch->ch_digi.digi_flags & DIGI_PRINTER)) {
- ch->ch_flags &= ~(CH_RXBLOCK);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-
- /* wait for output to drain */
- /* This will also return if we take an interrupt */
-
- dgap_wait_for_drain(tty);
-
- dgap_tty_flush_buffer(tty);
- tty_ldisc_flush(tty);
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
-
- tty->closing = 0;
-
- /*
- * If we have HUPCL set, lower DTR and RTS
- */
- if (ch->ch_c_cflag & HUPCL) {
- ch->ch_mostat &= ~(D_RTS(ch) | D_DTR(ch));
- dgap_cmdb(ch, SMODEM, 0, D_DTR(ch) | D_RTS(ch), 0);
-
- /*
- * Go to sleep to ensure RTS/DTR
- * have been dropped for modems to see it.
- */
- spin_unlock_irqrestore(&ch->ch_lock,
- lock_flags);
-
- /* .25 second delay for dropping RTS/DTR */
- schedule_timeout_interruptible(msecs_to_jiffies(250));
-
- spin_lock_irqsave(&ch->ch_lock, lock_flags);
- }
-
- ch->pscan_state = 0;
- ch->pscan_savechar = 0;
- ch->ch_baud_info = 0;
- }
-
- /*
- * turn off print device when closing print device.
- */
- if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) {
- dgap_wmove(ch, ch->ch_digi.digi_offstr,
- (int)ch->ch_digi.digi_offlen);
- ch->ch_flags &= ~CH_PRON;
- }
-
- un->un_tty = NULL;
- un->un_flags &= ~(UN_ISOPEN | UN_CLOSING);
- tty->driver_data = NULL;
-
- wake_up_interruptible(&ch->ch_flags_wait);
- wake_up_interruptible(&un->un_flags_wait);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
-}
-
-static void dgap_tty_start(struct tty_struct *tty)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- ulong lock_flags;
- ulong lock_flags2;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- dgap_cmdw(ch, RESUMETX, 0, 0);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-}
-
-static void dgap_tty_stop(struct tty_struct *tty)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- ulong lock_flags;
- ulong lock_flags2;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- dgap_cmdw(ch, PAUSETX, 0, 0);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-}
-
-/*
- * dgap_tty_flush_chars()
- *
- * Flush the cook buffer
- *
- * Note to self, and any other poor souls who venture here:
- *
- * flush in this case DOES NOT mean dispose of the data.
- * instead, it means "stop buffering and send it if you
- * haven't already." Just guess how I figured that out... SRW 2-Jun-98
- *
- * It is also always called in interrupt context - JAR 8-Sept-99
- */
-static void dgap_tty_flush_chars(struct tty_struct *tty)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- ulong lock_flags;
- ulong lock_flags2;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- /* TODO: Do something here */
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-}
-
-/*****************************************************************************
- *
- * The IOCTL function and all of its helpers
- *
- *****************************************************************************/
-
-/*
- * dgap_tty_ioctl()
- *
- * The usual assortment of ioctl's
- */
-static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
- unsigned long arg)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- int rc;
- u16 head;
- ulong lock_flags = 0;
- ulong lock_flags2 = 0;
- void __user *uarg = (void __user *)arg;
-
- if (!tty || tty->magic != TTY_MAGIC)
- return -ENODEV;
-
- un = tty->driver_data;
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return -ENODEV;
-
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return -ENODEV;
-
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return -ENODEV;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- if (un->un_open_count <= 0) {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return -EIO;
- }
-
- switch (cmd) {
- /* Here are all the standard ioctl's that we MUST implement */
- case TCSBRK:
- /*
- * TCSBRK is SVID version: non-zero arg --> no break
- * this behaviour is exploited by tcdrain().
- *
- * According to POSIX.1 spec (7.2.2.1.2) breaks should be
- * between 0.25 and 0.5 seconds so we'll ask for something
- * in the middle: 0.375 seconds.
- */
- rc = tty_check_change(tty);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- if (rc)
- return rc;
-
- rc = dgap_wait_for_drain(tty);
-
- if (rc)
- return -EINTR;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- if (((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP))
- dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return 0;
-
- case TCSBRKP:
- /* support for POSIX tcsendbreak()
-
- * According to POSIX.1 spec (7.2.2.1.2) breaks should be
- * between 0.25 and 0.5 seconds so we'll ask for something
- * in the middle: 0.375 seconds.
- */
- rc = tty_check_change(tty);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- if (rc)
- return rc;
-
- rc = dgap_wait_for_drain(tty);
- if (rc)
- return -EINTR;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return 0;
-
- case TIOCSBRK:
- /*
- * FEP5 doesn't support turning on a break unconditionally.
- * The FEP5 device will stop sending a break automatically
- * after the specified time value that was sent when turning on
- * the break.
- */
- rc = tty_check_change(tty);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- if (rc)
- return rc;
-
- rc = dgap_wait_for_drain(tty);
- if (rc)
- return -EINTR;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
-
- dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0);
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return 0;
-
- case TIOCCBRK:
- /*
- * FEP5 doesn't support turning off a break unconditionally.
- * The FEP5 device will stop sending a break automatically
- * after the specified time value that was sent when turning on
- * the break.
- */
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return 0;
-
- case TIOCGSOFTCAR:
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return put_user(C_CLOCAL(tty) ? 1 : 0,
- (unsigned long __user *)arg);
-
- case TIOCSSOFTCAR:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- rc = get_user(arg, (unsigned long __user *)arg);
- if (rc)
- return rc;
-
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
- tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0));
- dgap_param(ch, bd, un->un_type);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return 0;
-
- case TIOCMGET:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return dgap_get_modem_info(ch, uarg);
-
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return dgap_set_modem_info(ch, bd, un, cmd, uarg);
-
- /*
- * Here are any additional ioctl's that we want to implement
- */
-
- case TCFLSH:
- /*
- * The linux tty driver doesn't have a flush
- * input routine for the driver, assuming all backed
- * up data is in the line disc. buffers. However,
- * we all know that's not the case. Here, we
- * act on the ioctl, but then lie and say we didn't
- * so the line discipline will process the flush
- * also.
- */
- rc = tty_check_change(tty);
- if (rc) {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return rc;
- }
-
- if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) {
- if (!(un->un_type == DGAP_PRINT)) {
- head = readw(&ch->ch_bs->rx_head);
- writew(head, &ch->ch_bs->rx_tail);
- writeb(0, &ch->ch_bs->orun);
- }
- }
-
- if ((arg != TCOFLUSH) && (arg != TCIOFLUSH)) {
- /* pretend we didn't recognize this IOCTL */
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return -ENOIOCTLCMD;
- }
-
- ch->ch_flags &= ~CH_STOP;
- head = readw(&ch->ch_bs->tx_head);
- dgap_cmdw(ch, FLUSHTX, (u16)head, 0);
- dgap_cmdw(ch, RESUMETX, 0, 0);
- if (ch->ch_tun.un_flags & (UN_LOW | UN_EMPTY)) {
- ch->ch_tun.un_flags &= ~(UN_LOW | UN_EMPTY);
- wake_up_interruptible(&ch->ch_tun.un_flags_wait);
- }
- if (ch->ch_pun.un_flags & (UN_LOW | UN_EMPTY)) {
- ch->ch_pun.un_flags &= ~(UN_LOW | UN_EMPTY);
- wake_up_interruptible(&ch->ch_pun.un_flags_wait);
- }
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- tty_wakeup(tty);
-
- /* pretend we didn't recognize this IOCTL */
- return -ENOIOCTLCMD;
-
- case TCSETSF:
- case TCSETSW:
- /*
- * The linux tty driver doesn't have a flush
- * input routine for the driver, assuming all backed
- * up data is in the line disc. buffers. However,
- * we all know that's not the case. Here, we
- * act on the ioctl, but then lie and say we didn't
- * so the line discipline will process the flush
- * also.
- */
- if (cmd == TCSETSF) {
- /* flush rx */
- ch->ch_flags &= ~CH_STOP;
- head = readw(&ch->ch_bs->rx_head);
- writew(head, &ch->ch_bs->rx_tail);
- }
-
- /* now wait for all the output to drain */
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- rc = dgap_wait_for_drain(tty);
- if (rc)
- return -EINTR;
-
- /* pretend we didn't recognize this */
- return -ENOIOCTLCMD;
-
- case TCSETAW:
-
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- rc = dgap_wait_for_drain(tty);
- if (rc)
- return -EINTR;
-
- /* pretend we didn't recognize this */
- return -ENOIOCTLCMD;
-
- case TCXONC:
- /*
- * The Linux Line Discipline (LD) would do this for us if we
- * let it, but we have the special firmware options to do this
- * the "right way" regardless of hardware or software flow
- * control so we'll do it outselves instead of letting the LD
- * do it.
- */
- rc = tty_check_change(tty);
- if (rc) {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return rc;
- }
-
- switch (arg) {
- case TCOON:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- dgap_tty_start(tty);
- return 0;
- case TCOOFF:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- dgap_tty_stop(tty);
- return 0;
- case TCION:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- /* Make the ld do it */
- return -ENOIOCTLCMD;
- case TCIOFF:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- /* Make the ld do it */
- return -ENOIOCTLCMD;
- default:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return -EINVAL;
- }
-
- case DIGI_GETA:
- /* get information for ditty */
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return dgap_tty_digigeta(ch, uarg);
-
- case DIGI_SETAW:
- case DIGI_SETAF:
-
- /* set information for ditty */
- if (cmd == (DIGI_SETAW)) {
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- rc = dgap_wait_for_drain(tty);
- if (rc)
- return -EINTR;
- spin_lock_irqsave(&bd->bd_lock, lock_flags);
- spin_lock_irqsave(&ch->ch_lock, lock_flags2);
- } else
- tty_ldisc_flush(tty);
- /* fall thru */
-
- case DIGI_SETA:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return dgap_tty_digiseta(ch, bd, un, uarg);
-
- case DIGI_GEDELAY:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return dgap_tty_digigetedelay(tty, uarg);
-
- case DIGI_SEDELAY:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return dgap_tty_digisetedelay(ch, bd, un, uarg);
-
- case DIGI_GETCUSTOMBAUD:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return dgap_tty_digigetcustombaud(ch, un, uarg);
-
- case DIGI_SETCUSTOMBAUD:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return dgap_tty_digisetcustombaud(ch, bd, un, uarg);
-
- case DIGI_RESET_PORT:
- dgap_firmware_reset_port(ch);
- dgap_param(ch, bd, un->un_type);
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- return 0;
-
- default:
- spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
- spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
-
- return -ENOIOCTLCMD;
- }
-}
-
-static const struct tty_operations dgap_tty_ops = {
- .open = dgap_tty_open,
- .close = dgap_tty_close,
- .write = dgap_tty_write,
- .write_room = dgap_tty_write_room,
- .flush_buffer = dgap_tty_flush_buffer,
- .chars_in_buffer = dgap_tty_chars_in_buffer,
- .flush_chars = dgap_tty_flush_chars,
- .ioctl = dgap_tty_ioctl,
- .set_termios = dgap_tty_set_termios,
- .stop = dgap_tty_stop,
- .start = dgap_tty_start,
- .throttle = dgap_tty_throttle,
- .unthrottle = dgap_tty_unthrottle,
- .hangup = dgap_tty_hangup,
- .put_char = dgap_tty_put_char,
- .tiocmget = dgap_tty_tiocmget,
- .tiocmset = dgap_tty_tiocmset,
- .break_ctl = dgap_tty_send_break,
- .wait_until_sent = dgap_tty_wait_until_sent,
- .send_xchar = dgap_tty_send_xchar
-};
-
-/************************************************************************
- *
- * TTY Initialization/Cleanup Functions
- *
- ************************************************************************/
-
-/*
- * dgap_tty_register()
- *
- * Init the tty subsystem for this board.
- */
-static int dgap_tty_register(struct board_t *brd)
-{
- int rc;
-
- brd->serial_driver = tty_alloc_driver(MAXPORTS,
- TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_DYNAMIC_DEV |
- TTY_DRIVER_HARDWARE_BREAK);
- if (IS_ERR(brd->serial_driver))
- return PTR_ERR(brd->serial_driver);
-
- snprintf(brd->serial_name, MAXTTYNAMELEN, "tty_dgap_%d_",
- brd->boardnum);
- brd->serial_driver->name = brd->serial_name;
- brd->serial_driver->name_base = 0;
- brd->serial_driver->major = 0;
- brd->serial_driver->minor_start = 0;
- brd->serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
- brd->serial_driver->subtype = SERIAL_TYPE_NORMAL;
- brd->serial_driver->init_termios = dgap_default_termios;
- brd->serial_driver->driver_name = DRVSTR;
-
- /*
- * Entry points for driver. Called by the kernel from
- * tty_io.c and n_tty.c.
- */
- tty_set_operations(brd->serial_driver, &dgap_tty_ops);
-
- /*
- * If we're doing transparent print, we have to do all of the above
- * again, separately so we don't get the LD confused about what major
- * we are when we get into the dgap_tty_open() routine.
- */
- brd->print_driver = tty_alloc_driver(MAXPORTS,
- TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_DYNAMIC_DEV |
- TTY_DRIVER_HARDWARE_BREAK);
- if (IS_ERR(brd->print_driver)) {
- rc = PTR_ERR(brd->print_driver);
- goto free_serial_drv;
- }
-
- snprintf(brd->print_name, MAXTTYNAMELEN, "pr_dgap_%d_",
- brd->boardnum);
- brd->print_driver->name = brd->print_name;
- brd->print_driver->name_base = 0;
- brd->print_driver->major = 0;
- brd->print_driver->minor_start = 0;
- brd->print_driver->type = TTY_DRIVER_TYPE_SERIAL;
- brd->print_driver->subtype = SERIAL_TYPE_NORMAL;
- brd->print_driver->init_termios = dgap_default_termios;
- brd->print_driver->driver_name = DRVSTR;
-
- /*
- * Entry points for driver. Called by the kernel from
- * tty_io.c and n_tty.c.
- */
- tty_set_operations(brd->print_driver, &dgap_tty_ops);
-
- /* Register tty devices */
- rc = tty_register_driver(brd->serial_driver);
- if (rc < 0)
- goto free_print_drv;
-
- /* Register Transparent Print devices */
- rc = tty_register_driver(brd->print_driver);
- if (rc < 0)
- goto unregister_serial_drv;
-
- return 0;
-
-unregister_serial_drv:
- tty_unregister_driver(brd->serial_driver);
-free_print_drv:
- put_tty_driver(brd->print_driver);
-free_serial_drv:
- put_tty_driver(brd->serial_driver);
-
- return rc;
-}
-
-static void dgap_tty_unregister(struct board_t *brd)
-{
- tty_unregister_driver(brd->print_driver);
- tty_unregister_driver(brd->serial_driver);
- put_tty_driver(brd->print_driver);
- put_tty_driver(brd->serial_driver);
-}
-
-static int dgap_alloc_flipbuf(struct board_t *brd)
-{
- /*
- * allocate flip buffer for board.
- */
- brd->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL);
- if (!brd->flipbuf)
- return -ENOMEM;
-
- brd->flipflagbuf = kmalloc(MYFLIPLEN, GFP_KERNEL);
- if (!brd->flipflagbuf) {
- kfree(brd->flipbuf);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static void dgap_free_flipbuf(struct board_t *brd)
-{
- kfree(brd->flipbuf);
- kfree(brd->flipflagbuf);
-}
-
-static struct board_t *dgap_verify_board(struct device *p)
-{
- struct board_t *bd;
-
- if (!p)
- return NULL;
-
- bd = dev_get_drvdata(p);
- if (!bd || bd->magic != DGAP_BOARD_MAGIC || bd->state != BOARD_READY)
- return NULL;
-
- return bd;
-}
-
-static ssize_t dgap_ports_state_show(struct device *p,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- int count = 0;
- unsigned int i;
-
- bd = dgap_verify_board(p);
- if (!bd)
- return 0;
-
- for (i = 0; i < bd->nasync; i++) {
- count += snprintf(buf + count, PAGE_SIZE - count,
- "%d %s\n", bd->channels[i]->ch_portnum,
- bd->channels[i]->ch_open_count ? "Open" : "Closed");
- }
- return count;
-}
-static DEVICE_ATTR(ports_state, S_IRUSR, dgap_ports_state_show, NULL);
-
-static ssize_t dgap_ports_baud_show(struct device *p,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- int count = 0;
- unsigned int i;
-
- bd = dgap_verify_board(p);
- if (!bd)
- return 0;
-
- for (i = 0; i < bd->nasync; i++) {
- count += snprintf(buf + count, PAGE_SIZE - count, "%d %d\n",
- bd->channels[i]->ch_portnum,
- bd->channels[i]->ch_baud_info);
- }
- return count;
-}
-static DEVICE_ATTR(ports_baud, S_IRUSR, dgap_ports_baud_show, NULL);
-
-static ssize_t dgap_ports_msignals_show(struct device *p,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- int count = 0;
- unsigned int i;
-
- bd = dgap_verify_board(p);
- if (!bd)
- return 0;
-
- for (i = 0; i < bd->nasync; i++) {
- if (bd->channels[i]->ch_open_count)
- count += snprintf(buf + count, PAGE_SIZE - count,
- "%d %s %s %s %s %s %s\n",
- bd->channels[i]->ch_portnum,
- (bd->channels[i]->ch_mostat &
- UART_MCR_RTS) ? "RTS" : "",
- (bd->channels[i]->ch_mistat &
- UART_MSR_CTS) ? "CTS" : "",
- (bd->channels[i]->ch_mostat &
- UART_MCR_DTR) ? "DTR" : "",
- (bd->channels[i]->ch_mistat &
- UART_MSR_DSR) ? "DSR" : "",
- (bd->channels[i]->ch_mistat &
- UART_MSR_DCD) ? "DCD" : "",
- (bd->channels[i]->ch_mistat &
- UART_MSR_RI) ? "RI" : "");
- else
- count += snprintf(buf + count, PAGE_SIZE - count,
- "%d\n", bd->channels[i]->ch_portnum);
- }
- return count;
-}
-static DEVICE_ATTR(ports_msignals, S_IRUSR, dgap_ports_msignals_show, NULL);
-
-static ssize_t dgap_ports_iflag_show(struct device *p,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- int count = 0;
- unsigned int i;
-
- bd = dgap_verify_board(p);
- if (!bd)
- return 0;
-
- for (i = 0; i < bd->nasync; i++)
- count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
- bd->channels[i]->ch_portnum,
- bd->channels[i]->ch_c_iflag);
- return count;
-}
-static DEVICE_ATTR(ports_iflag, S_IRUSR, dgap_ports_iflag_show, NULL);
-
-static ssize_t dgap_ports_cflag_show(struct device *p,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- int count = 0;
- unsigned int i;
-
- bd = dgap_verify_board(p);
- if (!bd)
- return 0;
-
- for (i = 0; i < bd->nasync; i++)
- count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
- bd->channels[i]->ch_portnum,
- bd->channels[i]->ch_c_cflag);
- return count;
-}
-static DEVICE_ATTR(ports_cflag, S_IRUSR, dgap_ports_cflag_show, NULL);
-
-static ssize_t dgap_ports_oflag_show(struct device *p,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- int count = 0;
- unsigned int i;
-
- bd = dgap_verify_board(p);
- if (!bd)
- return 0;
-
- for (i = 0; i < bd->nasync; i++)
- count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
- bd->channels[i]->ch_portnum,
- bd->channels[i]->ch_c_oflag);
- return count;
-}
-static DEVICE_ATTR(ports_oflag, S_IRUSR, dgap_ports_oflag_show, NULL);
-
-static ssize_t dgap_ports_lflag_show(struct device *p,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- int count = 0;
- unsigned int i;
-
- bd = dgap_verify_board(p);
- if (!bd)
- return 0;
-
- for (i = 0; i < bd->nasync; i++)
- count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
- bd->channels[i]->ch_portnum,
- bd->channels[i]->ch_c_lflag);
- return count;
-}
-static DEVICE_ATTR(ports_lflag, S_IRUSR, dgap_ports_lflag_show, NULL);
-
-static ssize_t dgap_ports_digi_flag_show(struct device *p,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- int count = 0;
- unsigned int i;
-
- bd = dgap_verify_board(p);
- if (!bd)
- return 0;
-
- for (i = 0; i < bd->nasync; i++)
- count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
- bd->channels[i]->ch_portnum,
- bd->channels[i]->ch_digi.digi_flags);
- return count;
-}
-static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgap_ports_digi_flag_show, NULL);
-
-static ssize_t dgap_ports_rxcount_show(struct device *p,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- int count = 0;
- unsigned int i;
-
- bd = dgap_verify_board(p);
- if (!bd)
- return 0;
-
- for (i = 0; i < bd->nasync; i++)
- count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
- bd->channels[i]->ch_portnum,
- bd->channels[i]->ch_rxcount);
- return count;
-}
-static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgap_ports_rxcount_show, NULL);
-
-static ssize_t dgap_ports_txcount_show(struct device *p,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- int count = 0;
- unsigned int i;
-
- bd = dgap_verify_board(p);
- if (!bd)
- return 0;
-
- for (i = 0; i < bd->nasync; i++)
- count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
- bd->channels[i]->ch_portnum,
- bd->channels[i]->ch_txcount);
- return count;
-}
-static DEVICE_ATTR(ports_txcount, S_IRUSR, dgap_ports_txcount_show, NULL);
-
-static ssize_t dgap_tty_state_show(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
-
- if (!d)
- return 0;
- un = dev_get_drvdata(d);
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
- if (bd->state != BOARD_READY)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ?
- "Open" : "Closed");
-}
-static DEVICE_ATTR(state, S_IRUSR, dgap_tty_state_show, NULL);
-
-static ssize_t dgap_tty_baud_show(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
-
- if (!d)
- return 0;
- un = dev_get_drvdata(d);
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
- if (bd->state != BOARD_READY)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_baud_info);
-}
-static DEVICE_ATTR(baud, S_IRUSR, dgap_tty_baud_show, NULL);
-
-static ssize_t dgap_tty_msignals_show(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
-
- if (!d)
- return 0;
- un = dev_get_drvdata(d);
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
- if (bd->state != BOARD_READY)
- return 0;
-
- if (ch->ch_open_count) {
- return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
- (ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
- (ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
- (ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
- (ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
- (ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
- (ch->ch_mistat & UART_MSR_RI) ? "RI" : "");
- }
- return 0;
-}
-static DEVICE_ATTR(msignals, S_IRUSR, dgap_tty_msignals_show, NULL);
-
-static ssize_t dgap_tty_iflag_show(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
-
- if (!d)
- return 0;
- un = dev_get_drvdata(d);
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
- if (bd->state != BOARD_READY)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
-}
-static DEVICE_ATTR(iflag, S_IRUSR, dgap_tty_iflag_show, NULL);
-
-static ssize_t dgap_tty_cflag_show(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
-
- if (!d)
- return 0;
- un = dev_get_drvdata(d);
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
- if (bd->state != BOARD_READY)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
-}
-static DEVICE_ATTR(cflag, S_IRUSR, dgap_tty_cflag_show, NULL);
-
-static ssize_t dgap_tty_oflag_show(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
-
- if (!d)
- return 0;
- un = dev_get_drvdata(d);
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
- if (bd->state != BOARD_READY)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
-}
-static DEVICE_ATTR(oflag, S_IRUSR, dgap_tty_oflag_show, NULL);
-
-static ssize_t dgap_tty_lflag_show(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
-
- if (!d)
- return 0;
- un = dev_get_drvdata(d);
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
- if (bd->state != BOARD_READY)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
-}
-static DEVICE_ATTR(lflag, S_IRUSR, dgap_tty_lflag_show, NULL);
-
-static ssize_t dgap_tty_digi_flag_show(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
-
- if (!d)
- return 0;
- un = dev_get_drvdata(d);
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
- if (bd->state != BOARD_READY)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
-}
-static DEVICE_ATTR(digi_flag, S_IRUSR, dgap_tty_digi_flag_show, NULL);
-
-static ssize_t dgap_tty_rxcount_show(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
-
- if (!d)
- return 0;
- un = dev_get_drvdata(d);
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
- if (bd->state != BOARD_READY)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
-}
-static DEVICE_ATTR(rxcount, S_IRUSR, dgap_tty_rxcount_show, NULL);
-
-static ssize_t dgap_tty_txcount_show(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
-
- if (!d)
- return 0;
- un = dev_get_drvdata(d);
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
- if (bd->state != BOARD_READY)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
-}
-static DEVICE_ATTR(txcount, S_IRUSR, dgap_tty_txcount_show, NULL);
-
-static ssize_t dgap_tty_name_show(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct board_t *bd;
- struct channel_t *ch;
- struct un_t *un;
- int cn;
- int bn;
- struct cnode *cptr;
- int found = FALSE;
- int ncount = 0;
- int starto = 0;
- int i;
-
- if (!d)
- return 0;
- un = dev_get_drvdata(d);
- if (!un || un->magic != DGAP_UNIT_MAGIC)
- return 0;
- ch = un->un_ch;
- if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
- return 0;
- bd = ch->ch_bd;
- if (!bd || bd->magic != DGAP_BOARD_MAGIC)
- return 0;
- if (bd->state != BOARD_READY)
- return 0;
-
- bn = bd->boardnum;
- cn = ch->ch_portnum;
-
- for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
- if ((cptr->type == BNODE) &&
- ((cptr->u.board.type == APORT2_920P) ||
- (cptr->u.board.type == APORT4_920P) ||
- (cptr->u.board.type == APORT8_920P) ||
- (cptr->u.board.type == PAPORT4) ||
- (cptr->u.board.type == PAPORT8))) {
- found = TRUE;
- if (cptr->u.board.v_start)
- starto = cptr->u.board.start;
- else
- starto = 1;
- }
-
- if (cptr->type == TNODE && found == TRUE) {
- char *ptr1;
-
- if (strstr(cptr->u.ttyname, "tty")) {
- ptr1 = cptr->u.ttyname;
- ptr1 += 3;
- } else
- ptr1 = cptr->u.ttyname;
-
- for (i = 0; i < dgap_config_get_num_prts(bd); i++) {
- if (cn != i)
- continue;
-
- return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
- (un->un_type == DGAP_PRINT) ?
- "pr" : "tty",
- ptr1, i + starto);
- }
- }
-
- if (cptr->type == CNODE) {
- for (i = 0; i < cptr->u.conc.nport; i++) {
- if (cn != (i + ncount))
- continue;
-
- return snprintf(buf, PAGE_SIZE, "%s%s%02ld\n",
- (un->un_type == DGAP_PRINT) ?
- "pr" : "tty",
- cptr->u.conc.id,
- i + (cptr->u.conc.v_start ?
- cptr->u.conc.start : 1));
- }
-
- ncount += cptr->u.conc.nport;
- }
-
- if (cptr->type == MNODE) {
- for (i = 0; i < cptr->u.module.nport; i++) {
- if (cn != (i + ncount))
- continue;
-
- return snprintf(buf, PAGE_SIZE, "%s%s%02ld\n",
- (un->un_type == DGAP_PRINT) ?
- "pr" : "tty",
- cptr->u.module.id,
- i + (cptr->u.module.v_start ?
- cptr->u.module.start : 1));
- }
-
- ncount += cptr->u.module.nport;
- }
- }
-
- return snprintf(buf, PAGE_SIZE, "%s_dgap_%d_%d\n",
- (un->un_type == DGAP_PRINT) ? "pr" : "tty", bn, cn);
-}
-static DEVICE_ATTR(custom_name, S_IRUSR, dgap_tty_name_show, NULL);
-
-static struct attribute *dgap_sysfs_tty_entries[] = {
- &dev_attr_state.attr,
- &dev_attr_baud.attr,
- &dev_attr_msignals.attr,
- &dev_attr_iflag.attr,
- &dev_attr_cflag.attr,
- &dev_attr_oflag.attr,
- &dev_attr_lflag.attr,
- &dev_attr_digi_flag.attr,
- &dev_attr_rxcount.attr,
- &dev_attr_txcount.attr,
- &dev_attr_custom_name.attr,
- NULL
-};
-
-
-/* this function creates the sys files that will export each signal status
- * to sysfs each value will be put in a separate filename
- */
-static void dgap_create_ports_sysfiles(struct board_t *bd)
-{
- dev_set_drvdata(&bd->pdev->dev, bd);
- device_create_file(&bd->pdev->dev, &dev_attr_ports_state);
- device_create_file(&bd->pdev->dev, &dev_attr_ports_baud);
- device_create_file(&bd->pdev->dev, &dev_attr_ports_msignals);
- device_create_file(&bd->pdev->dev, &dev_attr_ports_iflag);
- device_create_file(&bd->pdev->dev, &dev_attr_ports_cflag);
- device_create_file(&bd->pdev->dev, &dev_attr_ports_oflag);
- device_create_file(&bd->pdev->dev, &dev_attr_ports_lflag);
- device_create_file(&bd->pdev->dev, &dev_attr_ports_digi_flag);
- device_create_file(&bd->pdev->dev, &dev_attr_ports_rxcount);
- device_create_file(&bd->pdev->dev, &dev_attr_ports_txcount);
-}
-
-/* removes all the sys files created for that port */
-static void dgap_remove_ports_sysfiles(struct board_t *bd)
-{
- device_remove_file(&bd->pdev->dev, &dev_attr_ports_state);
- device_remove_file(&bd->pdev->dev, &dev_attr_ports_baud);
- device_remove_file(&bd->pdev->dev, &dev_attr_ports_msignals);
- device_remove_file(&bd->pdev->dev, &dev_attr_ports_iflag);
- device_remove_file(&bd->pdev->dev, &dev_attr_ports_cflag);
- device_remove_file(&bd->pdev->dev, &dev_attr_ports_oflag);
- device_remove_file(&bd->pdev->dev, &dev_attr_ports_lflag);
- device_remove_file(&bd->pdev->dev, &dev_attr_ports_digi_flag);
- device_remove_file(&bd->pdev->dev, &dev_attr_ports_rxcount);
- device_remove_file(&bd->pdev->dev, &dev_attr_ports_txcount);
-}
-
-/*
- * Copies the BIOS code from the user to the board,
- * and starts the BIOS running.
- */
-static void dgap_do_bios_load(struct board_t *brd, const u8 *ubios, int len)
-{
- u8 __iomem *addr;
- uint offset;
- unsigned int i;
-
- if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
- return;
-
- addr = brd->re_map_membase;
-
- /*
- * clear POST area
- */
- for (i = 0; i < 16; i++)
- writeb(0, addr + POSTAREA + i);
-
- /*
- * Download bios
- */
- offset = 0x1000;
- memcpy_toio(addr + offset, ubios, len);
-
- writel(0x0bf00401, addr);
- writel(0, (addr + 4));
-
- /* Clear the reset, and change states. */
- writeb(FEPCLR, brd->re_map_port);
-}
-
-/*
- * Checks to see if the BIOS completed running on the card.
- */
-static int dgap_test_bios(struct board_t *brd)
-{
- u8 __iomem *addr;
- u16 word;
- u16 err1;
- u16 err2;
-
- if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
- return -EINVAL;
-
- addr = brd->re_map_membase;
- word = readw(addr + POSTAREA);
-
- /*
- * It can take 5-6 seconds for a board to
- * pass the bios self test and post results.
- * Give it 10 seconds.
- */
- brd->wait_for_bios = 0;
- while (brd->wait_for_bios < 1000) {
- /* Check to see if BIOS thinks board is good. (GD). */
- if (word == *(u16 *)"GD")
- return 0;
- msleep_interruptible(10);
- brd->wait_for_bios++;
- word = readw(addr + POSTAREA);
- }
-
- /* Gave up on board after too long of time taken */
- err1 = readw(addr + SEQUENCE);
- err2 = readw(addr + ERROR);
- dev_warn(&brd->pdev->dev, "%s failed diagnostics. Error #(%x,%x).\n",
- brd->name, err1, err2);
- brd->state = BOARD_FAILED;
- brd->dpastatus = BD_NOBIOS;
-
- return -EIO;
-}
-
-/*
- * Copies the FEP code from the user to the board,
- * and starts the FEP running.
- */
-static void dgap_do_fep_load(struct board_t *brd, const u8 *ufep, int len)
-{
- u8 __iomem *addr;
- uint offset;
-
- if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
- return;
-
- addr = brd->re_map_membase;
-
- /*
- * Download FEP
- */
- offset = 0x1000;
- memcpy_toio(addr + offset, ufep, len);
-
- /*
- * If board is a concentrator product, we need to give
- * it its config string describing how the concentrators look.
- */
- if ((brd->type == PCX) || (brd->type == PEPC)) {
- u8 string[100];
- u8 __iomem *config;
- u8 *xconfig;
- unsigned int i = 0;
-
- xconfig = dgap_create_config_string(brd, string);
-
- /* Write string to board memory */
- config = addr + CONFIG;
- for (; i < CONFIGSIZE; i++, config++, xconfig++) {
- writeb(*xconfig, config);
- if ((*xconfig & 0xff) == 0xff)
- break;
- }
- }
-
- writel(0xbfc01004, (addr + 0xc34));
- writel(0x3, (addr + 0xc30));
-}
-
-/*
- * Waits for the FEP to report thats its ready for us to use.
- */
-static int dgap_test_fep(struct board_t *brd)
-{
- u8 __iomem *addr;
- u16 word;
- u16 err1;
- u16 err2;
-
- if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
- return -EINVAL;
-
- addr = brd->re_map_membase;
- word = readw(addr + FEPSTAT);
-
- /*
- * It can take 2-3 seconds for the FEP to
- * be up and running. Give it 5 secs.
- */
- brd->wait_for_fep = 0;
- while (brd->wait_for_fep < 500) {
- /* Check to see if FEP is up and running now. */
- if (word == *(u16 *)"OS") {
- /*
- * Check to see if the board can support FEP5+ commands.
- */
- word = readw(addr + FEP5_PLUS);
- if (word == *(u16 *)"5A")
- brd->bd_flags |= BD_FEP5PLUS;
-
- return 0;
- }
- msleep_interruptible(10);
- brd->wait_for_fep++;
- word = readw(addr + FEPSTAT);
- }
-
- /* Gave up on board after too long of time taken */
- err1 = readw(addr + SEQUENCE);
- err2 = readw(addr + ERROR);
- dev_warn(&brd->pdev->dev,
- "FEPOS for %s not functioning. Error #(%x,%x).\n",
- brd->name, err1, err2);
- brd->state = BOARD_FAILED;
- brd->dpastatus = BD_NOFEP;
-
- return -EIO;
-}
-
-/*
- * Physically forces the FEP5 card to reset itself.
- */
-static void dgap_do_reset_board(struct board_t *brd)
-{
- u8 check;
- u32 check1;
- u32 check2;
- unsigned int i;
-
- if (!brd || (brd->magic != DGAP_BOARD_MAGIC) ||
- !brd->re_map_membase || !brd->re_map_port)
- return;
-
- /* FEPRST does not vary among supported boards */
- writeb(FEPRST, brd->re_map_port);
-
- for (i = 0; i <= 1000; i++) {
- check = readb(brd->re_map_port) & 0xe;
- if (check == FEPRST)
- break;
- udelay(10);
- }
- if (i > 1000) {
- dev_warn(&brd->pdev->dev,
- "dgap: Board not resetting... Failing board.\n");
- brd->state = BOARD_FAILED;
- brd->dpastatus = BD_NOFEP;
- return;
- }
-
- /*
- * Make sure there really is memory out there.
- */
- writel(0xa55a3cc3, (brd->re_map_membase + LOWMEM));
- writel(0x5aa5c33c, (brd->re_map_membase + HIGHMEM));
- check1 = readl(brd->re_map_membase + LOWMEM);
- check2 = readl(brd->re_map_membase + HIGHMEM);
-
- if ((check1 != 0xa55a3cc3) || (check2 != 0x5aa5c33c)) {
- dev_warn(&brd->pdev->dev,
- "No memory at %p for board.\n",
- brd->re_map_membase);
- brd->state = BOARD_FAILED;
- brd->dpastatus = BD_NOFEP;
- return;
- }
-}
-
-#ifdef DIGI_CONCENTRATORS_SUPPORTED
-/*
- * Sends a concentrator image into the FEP5 board.
- */
-static void dgap_do_conc_load(struct board_t *brd, u8 *uaddr, int len)
-{
- char __iomem *vaddr;
- u16 offset;
- struct downld_t *to_dp;
-
- if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase)
- return;
-
- vaddr = brd->re_map_membase;
-
- offset = readw((u16 *)(vaddr + DOWNREQ));
- to_dp = (struct downld_t *)(vaddr + (int)offset);
- memcpy_toio(to_dp, uaddr, len);
-
- /* Tell card we have data for it */
- writew(0, vaddr + (DOWNREQ));
-
- brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS;
-}
-#endif
-
-#define EXPANSION_ROM_SIZE (64 * 1024)
-#define FEP5_ROM_MAGIC (0xFEFFFFFF)
-
-static void dgap_get_vpd(struct board_t *brd)
-{
- u32 magic;
- u32 base_offset;
- u16 rom_offset;
- u16 vpd_offset;
- u16 image_length;
- u16 i;
- u8 byte1;
- u8 byte2;
-
- /*
- * Poke the magic number at the PCI Rom Address location.
- * If VPD is supported, the value read from that address
- * will be non-zero.
- */
- magic = FEP5_ROM_MAGIC;
- pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
- pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
-
- /* VPD not supported, bail */
- if (!magic)
- return;
-
- /*
- * To get to the OTPROM memory, we have to send the boards base
- * address or'ed with 1 into the PCI Rom Address location.
- */
- magic = brd->membase | 0x01;
- pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
- pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic);
-
- byte1 = readb(brd->re_map_membase);
- byte2 = readb(brd->re_map_membase + 1);
-
- /*
- * If the board correctly swapped to the OTPROM memory,
- * the first 2 bytes (header) should be 0x55, 0xAA
- */
- if (byte1 == 0x55 && byte2 == 0xAA) {
- base_offset = 0;
-
- /*
- * We have to run through all the OTPROM memory looking
- * for the VPD offset.
- */
- while (base_offset <= EXPANSION_ROM_SIZE) {
- /*
- * Lots of magic numbers here.
- *
- * The VPD offset is located inside the ROM Data
- * Structure.
- *
- * We also have to remember the length of each
- * ROM Data Structure, so we can "hop" to the next
- * entry if the VPD isn't in the current
- * ROM Data Structure.
- */
- rom_offset = readw(brd->re_map_membase +
- base_offset + 0x18);
- image_length = readw(brd->re_map_membase +
- rom_offset + 0x10) * 512;
- vpd_offset = readw(brd->re_map_membase +
- rom_offset + 0x08);
-
- /* Found the VPD entry */
- if (vpd_offset)
- break;
-
- /* We didn't find a VPD entry, go to next ROM entry. */
- base_offset += image_length;
-
- byte1 = readb(brd->re_map_membase + base_offset);
- byte2 = readb(brd->re_map_membase + base_offset + 1);
-
- /*
- * If the new ROM offset doesn't have 0x55, 0xAA
- * as its header, we have run out of ROM.
- */
- if (byte1 != 0x55 || byte2 != 0xAA)
- break;
- }
-
- /*
- * If we have a VPD offset, then mark the board
- * as having a valid VPD, and copy VPDSIZE (512) bytes of
- * that VPD to the buffer we have in our board structure.
- */
- if (vpd_offset) {
- brd->bd_flags |= BD_HAS_VPD;
- for (i = 0; i < VPDSIZE; i++) {
- brd->vpd[i] = readb(brd->re_map_membase +
- vpd_offset + i);
- }
- }
- }
-
- /*
- * We MUST poke the magic number at the PCI Rom Address location again.
- * This makes the card report the regular board memory back to us,
- * rather than the OTPROM memory.
- */
- magic = FEP5_ROM_MAGIC;
- pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic);
-}
-
-
-static ssize_t dgap_driver_version_show(struct device_driver *ddp, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
-}
-static DRIVER_ATTR(version, S_IRUSR, dgap_driver_version_show, NULL);
-
-
-static ssize_t dgap_driver_boards_show(struct device_driver *ddp, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%d\n", dgap_numboards);
-}
-static DRIVER_ATTR(boards, S_IRUSR, dgap_driver_boards_show, NULL);
-
-
-static ssize_t dgap_driver_maxboards_show(struct device_driver *ddp, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
-}
-static DRIVER_ATTR(maxboards, S_IRUSR, dgap_driver_maxboards_show, NULL);
-
-
-static ssize_t dgap_driver_pollcounter_show(struct device_driver *ddp,
- char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%ld\n", dgap_poll_counter);
-}
-static DRIVER_ATTR(pollcounter, S_IRUSR, dgap_driver_pollcounter_show, NULL);
-
-static ssize_t dgap_driver_pollrate_show(struct device_driver *ddp, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%dms\n", dgap_poll_tick);
-}
-
-static ssize_t dgap_driver_pollrate_store(struct device_driver *ddp,
- const char *buf, size_t count)
-{
- if (sscanf(buf, "%d\n", &dgap_poll_tick) != 1)
- return -EINVAL;
- return count;
-}
-static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgap_driver_pollrate_show,
- dgap_driver_pollrate_store);
-
-
-static int dgap_create_driver_sysfiles(struct pci_driver *dgap_driver)
-{
- int rc = 0;
- struct device_driver *driverfs = &dgap_driver->driver;
-
- rc |= driver_create_file(driverfs, &driver_attr_version);
- rc |= driver_create_file(driverfs, &driver_attr_boards);
- rc |= driver_create_file(driverfs, &driver_attr_maxboards);
- rc |= driver_create_file(driverfs, &driver_attr_pollrate);
- rc |= driver_create_file(driverfs, &driver_attr_pollcounter);
-
- return rc;
-}
-
-static void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver)
-{
- struct device_driver *driverfs = &dgap_driver->driver;
-
- driver_remove_file(driverfs, &driver_attr_version);
- driver_remove_file(driverfs, &driver_attr_boards);
- driver_remove_file(driverfs, &driver_attr_maxboards);
- driver_remove_file(driverfs, &driver_attr_pollrate);
- driver_remove_file(driverfs, &driver_attr_pollcounter);
-}
-
-static struct attribute_group dgap_tty_attribute_group = {
- .name = NULL,
- .attrs = dgap_sysfs_tty_entries,
-};
-
-static void dgap_create_tty_sysfs(struct un_t *un, struct device *c)
-{
- int ret;
-
- ret = sysfs_create_group(&c->kobj, &dgap_tty_attribute_group);
- if (ret)
- return;
-
- dev_set_drvdata(c, un);
-}
-
-static void dgap_remove_tty_sysfs(struct device *c)
-{
- sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
-}
-
-/*
- * Create pr and tty device entries
- */
-static int dgap_tty_register_ports(struct board_t *brd)
-{
- struct channel_t *ch;
- int i;
- int ret;
-
- brd->serial_ports = kcalloc(brd->nasync, sizeof(*brd->serial_ports),
- GFP_KERNEL);
- if (!brd->serial_ports)
- return -ENOMEM;
-
- brd->printer_ports = kcalloc(brd->nasync, sizeof(*brd->printer_ports),
- GFP_KERNEL);
- if (!brd->printer_ports) {
- ret = -ENOMEM;
- goto free_serial_ports;
- }
-
- for (i = 0; i < brd->nasync; i++) {
- tty_port_init(&brd->serial_ports[i]);
- tty_port_init(&brd->printer_ports[i]);
- }
-
- ch = brd->channels[0];
- for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) {
- struct device *classp;
-
- classp = tty_port_register_device(&brd->serial_ports[i],
- brd->serial_driver,
- i, NULL);
-
- if (IS_ERR(classp)) {
- ret = PTR_ERR(classp);
- goto unregister_ttys;
- }
-
- dgap_create_tty_sysfs(&ch->ch_tun, classp);
- ch->ch_tun.un_sysfs = classp;
-
- classp = tty_port_register_device(&brd->printer_ports[i],
- brd->print_driver,
- i, NULL);
-
- if (IS_ERR(classp)) {
- ret = PTR_ERR(classp);
- goto unregister_ttys;
- }
-
- dgap_create_tty_sysfs(&ch->ch_pun, classp);
- ch->ch_pun.un_sysfs = classp;
- }
- dgap_create_ports_sysfiles(brd);
-
- return 0;
-
-unregister_ttys:
- while (i >= 0) {
- ch = brd->channels[i];
- if (ch->ch_tun.un_sysfs) {
- dgap_remove_tty_sysfs(ch->ch_tun.un_sysfs);
- tty_unregister_device(brd->serial_driver, i);
- }
-
- if (ch->ch_pun.un_sysfs) {
- dgap_remove_tty_sysfs(ch->ch_pun.un_sysfs);
- tty_unregister_device(brd->print_driver, i);
- }
- i--;
- }
-
- for (i = 0; i < brd->nasync; i++) {
- tty_port_destroy(&brd->serial_ports[i]);
- tty_port_destroy(&brd->printer_ports[i]);
- }
-
- kfree(brd->printer_ports);
- brd->printer_ports = NULL;
-
-free_serial_ports:
- kfree(brd->serial_ports);
- brd->serial_ports = NULL;
-
- return ret;
-}
-
-/*
- * dgap_cleanup_tty()
- *
- * Uninitialize the TTY portion of this driver. Free all memory and
- * resources.
- */
-static void dgap_cleanup_tty(struct board_t *brd)
-{
- struct device *dev;
- unsigned int i;
-
- for (i = 0; i < brd->nasync; i++) {
- tty_port_destroy(&brd->serial_ports[i]);
- dev = brd->channels[i]->ch_tun.un_sysfs;
- dgap_remove_tty_sysfs(dev);
- tty_unregister_device(brd->serial_driver, i);
- }
- tty_unregister_driver(brd->serial_driver);
- put_tty_driver(brd->serial_driver);
- kfree(brd->serial_ports);
-
- for (i = 0; i < brd->nasync; i++) {
- tty_port_destroy(&brd->printer_ports[i]);
- dev = brd->channels[i]->ch_pun.un_sysfs;
- dgap_remove_tty_sysfs(dev);
- tty_unregister_device(brd->print_driver, i);
- }
- tty_unregister_driver(brd->print_driver);
- put_tty_driver(brd->print_driver);
- kfree(brd->printer_ports);
-}
-
-static int dgap_request_irq(struct board_t *brd)
-{
- int rc;
-
- if (!brd || brd->magic != DGAP_BOARD_MAGIC)
- return -ENODEV;
-
- /*
- * Set up our interrupt handler if we are set to do interrupts.
- */
- if (dgap_config_get_useintr(brd) && brd->irq) {
- rc = request_irq(brd->irq, dgap_intr, IRQF_SHARED, "DGAP", brd);
-
- if (!rc)
- brd->intr_used = 1;
- }
- return 0;
-}
-
-static void dgap_free_irq(struct board_t *brd)
-{
- if (brd->intr_used && brd->irq)
- free_irq(brd->irq, brd);
-}
-
-static int dgap_firmware_load(struct pci_dev *pdev, int card_type,
- struct board_t *brd)
-{
- const struct firmware *fw;
- char *tmp_ptr;
- int ret;
- char *dgap_config_buf;
-
- dgap_get_vpd(brd);
- dgap_do_reset_board(brd);
-
- if (fw_info[card_type].conf_name) {
- ret = request_firmware(&fw, fw_info[card_type].conf_name,
- &pdev->dev);
- if (ret) {
- dev_err(&pdev->dev, "config file %s not found\n",
- fw_info[card_type].conf_name);
- return ret;
- }
-
- dgap_config_buf = kzalloc(fw->size + 1, GFP_KERNEL);
- if (!dgap_config_buf) {
- release_firmware(fw);
- return -ENOMEM;
- }
-
- memcpy(dgap_config_buf, fw->data, fw->size);
- release_firmware(fw);
-
- /*
- * preserve dgap_config_buf
- * as dgap_parsefile would
- * otherwise alter it.
- */
- tmp_ptr = dgap_config_buf;
-
- if (dgap_parsefile(&tmp_ptr) != 0) {
- kfree(dgap_config_buf);
- return -EINVAL;
- }
- kfree(dgap_config_buf);
- }
-
- /*
- * Match this board to a config the user created for us.
- */
- brd->bd_config =
- dgap_find_config(brd->type, brd->pci_bus, brd->pci_slot);
-
- /*
- * Because the 4 port Xr products share the same PCI ID
- * as the 8 port Xr products, if we receive a NULL config
- * back, and this is a PAPORT8 board, retry with a
- * PAPORT4 attempt as well.
- */
- if (brd->type == PAPORT8 && !brd->bd_config)
- brd->bd_config =
- dgap_find_config(PAPORT4, brd->pci_bus, brd->pci_slot);
-
- if (!brd->bd_config) {
- dev_err(&pdev->dev, "No valid configuration found\n");
- return -EINVAL;
- }
-
- if (fw_info[card_type].bios_name) {
- ret = request_firmware(&fw, fw_info[card_type].bios_name,
- &pdev->dev);
- if (ret) {
- dev_err(&pdev->dev, "bios file %s not found\n",
- fw_info[card_type].bios_name);
- return ret;
- }
- dgap_do_bios_load(brd, fw->data, fw->size);
- release_firmware(fw);
-
- /* Wait for BIOS to test board... */
- ret = dgap_test_bios(brd);
- if (ret)
- return ret;
- }
-
- if (fw_info[card_type].fep_name) {
- ret = request_firmware(&fw, fw_info[card_type].fep_name,
- &pdev->dev);
- if (ret) {
- dev_err(&pdev->dev, "dgap: fep file %s not found\n",
- fw_info[card_type].fep_name);
- return ret;
- }
- dgap_do_fep_load(brd, fw->data, fw->size);
- release_firmware(fw);
-
- /* Wait for FEP to load on board... */
- ret = dgap_test_fep(brd);
- if (ret)
- return ret;
- }
-
-#ifdef DIGI_CONCENTRATORS_SUPPORTED
- /*
- * If this is a CX or EPCX, we need to see if the firmware
- * is requesting a concentrator image from us.
- */
- if ((bd->type == PCX) || (bd->type == PEPC)) {
- chk_addr = (u16 *)(vaddr + DOWNREQ);
- /* Nonzero if FEP is requesting concentrator image. */
- check = readw(chk_addr);
- vaddr = brd->re_map_membase;
- }
-
- if (fw_info[card_type].con_name && check && vaddr) {
- ret = request_firmware(&fw, fw_info[card_type].con_name,
- &pdev->dev);
- if (ret) {
- dev_err(&pdev->dev, "conc file %s not found\n",
- fw_info[card_type].con_name);
- return ret;
- }
- /* Put concentrator firmware loading code here */
- offset = readw((u16 *)(vaddr + DOWNREQ));
- memcpy_toio(offset, fw->data, fw->size);
-
- dgap_do_conc_load(brd, (char *)fw->data, fw->size)
- release_firmware(fw);
- }
-#endif
-
- return 0;
-}
-
-/*
- * dgap_tty_init()
- *
- * Init the tty subsystem. Called once per board after board has been
- * downloaded and init'ed.
- */
-static int dgap_tty_init(struct board_t *brd)
-{
- int i;
- int tlw;
- uint true_count;
- u8 __iomem *vaddr;
- u8 modem;
- struct channel_t *ch;
- struct bs_t __iomem *bs;
- struct cm_t __iomem *cm;
- int ret;
-
- /*
- * Initialize board structure elements.
- */
-
- vaddr = brd->re_map_membase;
- true_count = readw((vaddr + NCHAN));
-
- brd->nasync = dgap_config_get_num_prts(brd);
-
- if (!brd->nasync)
- brd->nasync = brd->maxports;
-
- if (brd->nasync > brd->maxports)
- brd->nasync = brd->maxports;
-
- if (true_count != brd->nasync) {
- dev_warn(&brd->pdev->dev,
- "%s configured for %d ports, has %d ports.\n",
- brd->name, brd->nasync, true_count);
-
- if ((brd->type == PPCM) &&
- (true_count == 64 || true_count == 0)) {
- dev_warn(&brd->pdev->dev,
- "Please make SURE the EBI cable running from the card\n");
- dev_warn(&brd->pdev->dev,
- "to each EM module is plugged into EBI IN!\n");
- }
-
- brd->nasync = true_count;
-
- /* If no ports, don't bother going any further */
- if (!brd->nasync) {
- brd->state = BOARD_FAILED;
- brd->dpastatus = BD_NOFEP;
- return -EIO;
- }
- }
-
- /*
- * Allocate channel memory that might not have been allocated
- * when the driver was first loaded.
- */
- for (i = 0; i < brd->nasync; i++) {
- brd->channels[i] =
- kzalloc(sizeof(struct channel_t), GFP_KERNEL);
- if (!brd->channels[i]) {
- ret = -ENOMEM;
- goto free_chan;
- }
- }
-
- ch = brd->channels[0];
- vaddr = brd->re_map_membase;
-
- bs = (struct bs_t __iomem *)((ulong)vaddr + CHANBUF);
- cm = (struct cm_t __iomem *)((ulong)vaddr + CMDBUF);
-
- brd->bd_bs = bs;
-
- /* Set up channel variables */
- for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) {
- spin_lock_init(&ch->ch_lock);
-
- /* Store all our magic numbers */
- ch->magic = DGAP_CHANNEL_MAGIC;
- ch->ch_tun.magic = DGAP_UNIT_MAGIC;
- ch->ch_tun.un_type = DGAP_SERIAL;
- ch->ch_tun.un_ch = ch;
- ch->ch_tun.un_dev = i;
-
- ch->ch_pun.magic = DGAP_UNIT_MAGIC;
- ch->ch_pun.un_type = DGAP_PRINT;
- ch->ch_pun.un_ch = ch;
- ch->ch_pun.un_dev = i;
-
- ch->ch_vaddr = vaddr;
- ch->ch_bs = bs;
- ch->ch_cm = cm;
- ch->ch_bd = brd;
- ch->ch_portnum = i;
- ch->ch_digi = dgap_digi_init;
-
- /*
- * Set up digi dsr and dcd bits based on altpin flag.
- */
- if (dgap_config_get_altpin(brd)) {
- ch->ch_dsr = DM_CD;
- ch->ch_cd = DM_DSR;
- ch->ch_digi.digi_flags |= DIGI_ALTPIN;
- } else {
- ch->ch_cd = DM_CD;
- ch->ch_dsr = DM_DSR;
- }
-
- ch->ch_taddr = vaddr + (ioread16(&ch->ch_bs->tx_seg) << 4);
- ch->ch_raddr = vaddr + (ioread16(&ch->ch_bs->rx_seg) << 4);
- ch->ch_tx_win = 0;
- ch->ch_rx_win = 0;
- ch->ch_tsize = readw(&ch->ch_bs->tx_max) + 1;
- ch->ch_rsize = readw(&ch->ch_bs->rx_max) + 1;
- ch->ch_tstart = 0;
- ch->ch_rstart = 0;
-
- /*
- * Set queue water marks, interrupt mask,
- * and general tty parameters.
- */
- tlw = ch->ch_tsize >= 2000 ? ((ch->ch_tsize * 5) / 8) :
- ch->ch_tsize / 2;
- ch->ch_tlw = tlw;
-
- dgap_cmdw(ch, STLOW, tlw, 0);
-
- dgap_cmdw(ch, SRLOW, ch->ch_rsize / 2, 0);
-
- dgap_cmdw(ch, SRHIGH, 7 * ch->ch_rsize / 8, 0);
-
- ch->ch_mistat = readb(&ch->ch_bs->m_stat);
-
- init_waitqueue_head(&ch->ch_flags_wait);
- init_waitqueue_head(&ch->ch_tun.un_flags_wait);
- init_waitqueue_head(&ch->ch_pun.un_flags_wait);
-
- /* Turn on all modem interrupts for now */
- modem = (DM_CD | DM_DSR | DM_CTS | DM_RI);
- writeb(modem, &ch->ch_bs->m_int);
-
- /*
- * Set edelay to 0 if interrupts are turned on,
- * otherwise set edelay to the usual 100.
- */
- if (brd->intr_used)
- writew(0, &ch->ch_bs->edelay);
- else
- writew(100, &ch->ch_bs->edelay);
-
- writeb(1, &ch->ch_bs->idata);
- }
-
- return 0;
-
-free_chan:
- while (--i >= 0) {
- kfree(brd->channels[i]);
- brd->channels[i] = NULL;
- }
- return ret;
-}
-
-/*
- * dgap_tty_free()
- *
- * Free the channles which are allocated in dgap_tty_init().
- */
-static void dgap_tty_free(struct board_t *brd)
-{
- int i;
-
- for (i = 0; i < brd->nasync; i++)
- kfree(brd->channels[i]);
-}
-
-static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
- int rc;
- struct board_t *brd;
-
- if (dgap_numboards >= MAXBOARDS)
- return -EPERM;
-
- rc = pci_enable_device(pdev);
- if (rc)
- return -EIO;
-
- brd = dgap_found_board(pdev, ent->driver_data, dgap_numboards);
- if (IS_ERR(brd))
- return PTR_ERR(brd);
-
- rc = dgap_firmware_load(pdev, ent->driver_data, brd);
- if (rc)
- goto cleanup_brd;
-
- rc = dgap_alloc_flipbuf(brd);
- if (rc)
- goto cleanup_brd;
-
- rc = dgap_tty_register(brd);
- if (rc)
- goto free_flipbuf;
-
- rc = dgap_request_irq(brd);
- if (rc)
- goto unregister_tty;
-
- /*
- * Do tty device initialization.
- */
- rc = dgap_tty_init(brd);
- if (rc < 0)
- goto free_irq;
-
- rc = dgap_tty_register_ports(brd);
- if (rc)
- goto tty_free;
-
- brd->state = BOARD_READY;
- brd->dpastatus = BD_RUNNING;
-
- dgap_board[dgap_numboards++] = brd;
-
- return 0;
-
-tty_free:
- dgap_tty_free(brd);
-free_irq:
- dgap_free_irq(brd);
-unregister_tty:
- dgap_tty_unregister(brd);
-free_flipbuf:
- dgap_free_flipbuf(brd);
-cleanup_brd:
- dgap_cleanup_nodes();
- dgap_unmap(brd);
- kfree(brd);
-
- return rc;
-}
-
-/*
- * dgap_cleanup_board()
- *
- * Free all the memory associated with a board
- */
-static void dgap_cleanup_board(struct board_t *brd)
-{
- unsigned int i;
-
- if (!brd || brd->magic != DGAP_BOARD_MAGIC)
- return;
-
- dgap_free_irq(brd);
-
- tasklet_kill(&brd->helper_tasklet);
-
- dgap_unmap(brd);
-
- /* Free all allocated channels structs */
- for (i = 0; i < MAXPORTS ; i++)
- kfree(brd->channels[i]);
-
- kfree(brd->flipbuf);
- kfree(brd->flipflagbuf);
-
- dgap_board[brd->boardnum] = NULL;
-
- kfree(brd);
-}
-
-static void dgap_stop(bool removesys, struct pci_driver *drv)
-{
- unsigned long lock_flags;
-
- spin_lock_irqsave(&dgap_poll_lock, lock_flags);
- dgap_poll_stop = 1;
- spin_unlock_irqrestore(&dgap_poll_lock, lock_flags);
-
- del_timer_sync(&dgap_poll_timer);
- if (removesys)
- dgap_remove_driver_sysfiles(drv);
-
- device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
- class_destroy(dgap_class);
- unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
-}
-
-static void dgap_remove_one(struct pci_dev *dev)
-{
- unsigned int i;
- struct pci_driver *drv = to_pci_driver(dev->dev.driver);
-
- dgap_stop(true, drv);
- for (i = 0; i < dgap_numboards; ++i) {
- dgap_remove_ports_sysfiles(dgap_board[i]);
- dgap_cleanup_tty(dgap_board[i]);
- dgap_cleanup_board(dgap_board[i]);
- }
-
- dgap_cleanup_nodes();
-}
-
-static struct pci_driver dgap_driver = {
- .name = "dgap",
- .probe = dgap_init_one,
- .id_table = dgap_pci_tbl,
- .remove = dgap_remove_one,
-};
-
-/*
- * Start of driver.
- */
-static int dgap_start(void)
-{
- int rc;
- unsigned long flags;
- struct device *device;
-
- dgap_numboards = 0;
-
- pr_info("For the tools package please visit http://www.digi.com\n");
-
- /*
- * Register our base character device into the kernel.
- */
-
- /*
- * Register management/dpa devices
- */
- rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &dgap_board_fops);
- if (rc < 0)
- return rc;
-
- dgap_class = class_create(THIS_MODULE, "dgap_mgmt");
- if (IS_ERR(dgap_class)) {
- rc = PTR_ERR(dgap_class);
- goto failed_class;
- }
-
- device = device_create(dgap_class, NULL,
- MKDEV(DIGI_DGAP_MAJOR, 0),
- NULL, "dgap_mgmt");
- if (IS_ERR(device)) {
- rc = PTR_ERR(device);
- goto failed_device;
- }
-
- /* Start the poller */
- spin_lock_irqsave(&dgap_poll_lock, flags);
- setup_timer(&dgap_poll_timer, dgap_poll_handler, 0);
- dgap_poll_timer.data = 0;
- dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick);
- dgap_poll_timer.expires = dgap_poll_time;
- spin_unlock_irqrestore(&dgap_poll_lock, flags);
-
- add_timer(&dgap_poll_timer);
-
- return rc;
-
-failed_device:
- class_destroy(dgap_class);
-failed_class:
- unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
- return rc;
-}
-
-/************************************************************************
- *
- * Driver load/unload functions
- *
- ************************************************************************/
-
-/*
- * init_module()
- *
- * Module load. This is where it all starts.
- */
-static int dgap_init_module(void)
-{
- int rc;
-
- pr_info("%s, Digi International Part Number %s\n", DG_NAME, DG_PART);
-
- rc = dgap_start();
- if (rc)
- return rc;
-
- rc = pci_register_driver(&dgap_driver);
- if (rc) {
- dgap_stop(false, NULL);
- return rc;
- }
-
- rc = dgap_create_driver_sysfiles(&dgap_driver);
- if (rc)
- goto err_unregister;
-
- dgap_driver_state = DRIVER_READY;
-
- return 0;
-
-err_unregister:
- pci_unregister_driver(&dgap_driver);
- return rc;
-}
-
-/*
- * dgap_cleanup_module()
- *
- * Module unload. This is where it all ends.
- */
-static void dgap_cleanup_module(void)
-{
- if (dgap_numboards)
- pci_unregister_driver(&dgap_driver);
-}
-
-module_init(dgap_init_module);
-module_exit(dgap_cleanup_module);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Digi International, http://www.digi.com");
-MODULE_DESCRIPTION("Driver for the Digi International EPCA PCI based product line");
-MODULE_SUPPORTED_DEVICE("dgap");
+++ /dev/null
-/*
- * Copyright 2003 Digi International (www.digi.com)
- * Scott H Kilau <Scott_Kilau at digi dot 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!!
- *
- *************************************************************************
- *
- * Driver includes
- *
- *************************************************************************/
-
-#ifndef __DGAP_DRIVER_H
-#define __DGAP_DRIVER_H
-
-#include <linux/types.h> /* To pick up the varions Linux types */
-#include <linux/tty.h> /* To pick up the various tty structs/defines */
-#include <linux/interrupt.h> /* For irqreturn_t type */
-
-#ifndef TRUE
-# define TRUE 1
-#endif
-
-#ifndef FALSE
-# define FALSE 0
-#endif
-
-#if !defined(TTY_FLIPBUF_SIZE)
-# define TTY_FLIPBUF_SIZE 512
-#endif
-
-/*************************************************************************
- *
- * Driver defines
- *
- *************************************************************************/
-
-/*
- * Driver identification
- */
-#define DG_NAME "dgap-1.3-16"
-#define DG_PART "40002347_C"
-#define DRVSTR "dgap"
-
-/*
- * defines from dgap_pci.h
- */
-#define PCIMAX 32 /* maximum number of PCI boards */
-
-#define DIGI_VID 0x114F
-
-#define PCI_DEV_EPC_DID 0x0002
-#define PCI_DEV_XEM_DID 0x0004
-#define PCI_DEV_XR_DID 0x0005
-#define PCI_DEV_CX_DID 0x0006
-#define PCI_DEV_XRJ_DID 0x0009 /* PLX-based Xr adapter */
-#define PCI_DEV_XR_IBM_DID 0x0011 /* IBM 8-port Async Adapter */
-#define PCI_DEV_XR_BULL_DID 0x0013 /* BULL 8-port Async Adapter */
-#define PCI_DEV_XR_SAIP_DID 0x001c /* SAIP card - Xr adapter */
-#define PCI_DEV_XR_422_DID 0x0012 /* Xr-422 */
-#define PCI_DEV_920_2_DID 0x0034 /* XR-Plus 920 K, 2 port */
-#define PCI_DEV_920_4_DID 0x0026 /* XR-Plus 920 K, 4 port */
-#define PCI_DEV_920_8_DID 0x0027 /* XR-Plus 920 K, 8 port */
-#define PCI_DEV_EPCJ_DID 0x000a /* PLX 9060 chip for PCI */
-#define PCI_DEV_CX_IBM_DID 0x001b /* IBM 128-port Async Adapter */
-#define PCI_DEV_920_8_HP_DID 0x0058 /* HP XR-Plus 920 K, 8 port */
-#define PCI_DEV_XEM_HP_DID 0x0059 /* HP Xem PCI */
-
-#define PCI_DEV_XEM_NAME "AccelePort XEM"
-#define PCI_DEV_CX_NAME "AccelePort CX"
-#define PCI_DEV_XR_NAME "AccelePort Xr"
-#define PCI_DEV_XRJ_NAME "AccelePort Xr (PLX)"
-#define PCI_DEV_XR_SAIP_NAME "AccelePort Xr (SAIP)"
-#define PCI_DEV_920_2_NAME "AccelePort Xr920 2 port"
-#define PCI_DEV_920_4_NAME "AccelePort Xr920 4 port"
-#define PCI_DEV_920_8_NAME "AccelePort Xr920 8 port"
-#define PCI_DEV_XR_422_NAME "AccelePort Xr 422"
-#define PCI_DEV_EPCJ_NAME "AccelePort EPC (PLX)"
-#define PCI_DEV_XR_BULL_NAME "AccelePort Xr (BULL)"
-#define PCI_DEV_XR_IBM_NAME "AccelePort Xr (IBM)"
-#define PCI_DEV_CX_IBM_NAME "AccelePort CX (IBM)"
-#define PCI_DEV_920_8_HP_NAME "AccelePort Xr920 8 port (HP)"
-#define PCI_DEV_XEM_HP_NAME "AccelePort XEM (HP)"
-
-/*
- * On the PCI boards, there is no IO space allocated
- * The I/O registers will be in the first 3 bytes of the
- * upper 2MB of the 4MB memory space. The board memory
- * will be mapped into the low 2MB of the 4MB memory space
- */
-
-/* Potential location of PCI Bios from E0000 to FFFFF*/
-#define PCI_BIOS_SIZE 0x00020000
-
-/* Size of Memory and I/O for PCI (4MB) */
-#define PCI_RAM_SIZE 0x00400000
-
-/* Size of Memory (2MB) */
-#define PCI_MEM_SIZE 0x00200000
-
-/* Max PCI Window Size (2MB) */
-#define PCI_WIN_SIZE 0x00200000
-
-#define PCI_WIN_SHIFT 21 /* 21 bits max */
-
-/* Offset of I/0 in Memory (2MB) */
-#define PCI_IO_OFFSET 0x00200000
-
-/* Size of IO (2MB) */
-#define PCI_IO_SIZE_DGAP 0x00200000
-
-/* Number of boards we support at once. */
-#define MAXBOARDS 32
-#define MAXPORTS 224
-#define MAXTTYNAMELEN 200
-
-/* Our 3 magic numbers for our board, channel and unit structs */
-#define DGAP_BOARD_MAGIC 0x5c6df104
-#define DGAP_CHANNEL_MAGIC 0x6c6df104
-#define DGAP_UNIT_MAGIC 0x7c6df104
-
-/* Serial port types */
-#define DGAP_SERIAL 0
-#define DGAP_PRINT 1
-
-#define SERIAL_TYPE_NORMAL 1
-
-/* 4 extra for alignment play space */
-#define WRITEBUFLEN ((4096) + 4)
-#define MYFLIPLEN N_TTY_BUF_SIZE
-
-#define SBREAK_TIME 0x25
-#define U2BSIZE 0x400
-
-#define dgap_jiffies_from_ms(a) (((a) * HZ) / 1000)
-
-/*
- * Our major for the mgmt devices.
- *
- * We can use 22, because Digi was allocated 22 and 23 for the epca driver.
- * 22 has now become obsolete now that the "cu" devices have
- * been removed from 2.6.
- * Also, this *IS* the epca driver, just PCI only now.
- */
-#ifndef DIGI_DGAP_MAJOR
-# define DIGI_DGAP_MAJOR 22
-#endif
-
-/*
- * The parameters we use to define the periods of the moving averages.
- */
-#define MA_PERIOD (HZ / 10)
-#define SMA_DUR (1 * HZ)
-#define EMA_DUR (1 * HZ)
-#define SMA_NPERIODS (SMA_DUR / MA_PERIOD)
-#define EMA_NPERIODS (EMA_DUR / MA_PERIOD)
-
-/*
- * Define a local default termios struct. All ports will be created
- * with this termios initially. This is the same structure that is defined
- * as the default in tty_io.c with the same settings overridden as in serial.c
- *
- * In short, this should match the internal serial ports' defaults.
- */
-#define DEFAULT_IFLAGS (ICRNL | IXON)
-#define DEFAULT_OFLAGS (OPOST | ONLCR)
-#define DEFAULT_CFLAGS (B9600 | CS8 | CREAD | HUPCL | CLOCAL)
-#define DEFAULT_LFLAGS (ISIG | ICANON | ECHO | ECHOE | ECHOK | \
- ECHOCTL | ECHOKE | IEXTEN)
-
-#ifndef _POSIX_VDISABLE
-#define _POSIX_VDISABLE ('\0')
-#endif
-
-#define SNIFF_MAX 65536 /* Sniff buffer size (2^n) */
-#define SNIFF_MASK (SNIFF_MAX - 1) /* Sniff wrap mask */
-
-#define VPDSIZE (512)
-
-/************************************************************************
- * FEP memory offsets
- ************************************************************************/
-#define START 0x0004L /* Execution start address */
-
-#define CMDBUF 0x0d10L /* Command (cm_t) structure offset */
-#define CMDSTART 0x0400L /* Start of command buffer */
-#define CMDMAX 0x0800L /* End of command buffer */
-
-#define EVBUF 0x0d18L /* Event (ev_t) structure */
-#define EVSTART 0x0800L /* Start of event buffer */
-#define EVMAX 0x0c00L /* End of event buffer */
-#define FEP5_PLUS 0x0E40 /* ASCII '5' and ASCII 'A' is here */
-#define ECS_SEG 0x0E44 /* Segment of the extended */
- /* channel structure */
-#define LINE_SPEED 0x10 /* Offset into ECS_SEG for line */
- /* speed if the fep has extended */
- /* capabilities */
-
-/* BIOS MAGIC SPOTS */
-#define ERROR 0x0C14L /* BIOS error code */
-#define SEQUENCE 0x0C12L /* BIOS sequence indicator */
-#define POSTAREA 0x0C00L /* POST complete message area */
-
-/* FEP MAGIC SPOTS */
-#define FEPSTAT POSTAREA /* OS here when FEP comes up */
-#define NCHAN 0x0C02L /* number of ports FEP sees */
-#define PANIC 0x0C10L /* PANIC area for FEP */
-#define KMEMEM 0x0C30L /* Memory for KME use */
-#define CONFIG 0x0CD0L /* Concentrator configuration info */
-#define CONFIGSIZE 0x0030 /* configuration info size */
-#define DOWNREQ 0x0D00 /* Download request buffer pointer */
-
-#define CHANBUF 0x1000L /* Async channel (bs_t) structs */
-#define FEPOSSIZE 0x1FFF /* 8K FEPOS */
-
-#define XEMPORTS 0xC02 /*
- * Offset in board memory where FEP5 stores
- * how many ports it has detected.
- * NOTE: FEP5 reports 64 ports when the user
- * has the cable in EBI OUT instead of EBI IN.
- */
-
-#define FEPCLR 0x00
-#define FEPMEM 0x02
-#define FEPRST 0x04
-#define FEPINT 0x08
-#define FEPMASK 0x0e
-#define FEPWIN 0x80
-
-#define LOWMEM 0x0100
-#define HIGHMEM 0x7f00
-
-#define FEPTIMEOUT 200000
-
-#define ENABLE_INTR 0x0e04 /* Enable interrupts flag */
-#define FEPPOLL_MIN 1 /* minimum of 1 millisecond */
-#define FEPPOLL_MAX 20 /* maximum of 20 milliseconds */
-#define FEPPOLL 0x0c26 /* Fep event poll interval */
-
-#define IALTPIN 0x0080 /* Input flag to swap DSR <-> DCD */
-
-/************************************************************************
- * FEP supported functions
- ************************************************************************/
-#define SRLOW 0xe0 /* Set receive low water */
-#define SRHIGH 0xe1 /* Set receive high water */
-#define FLUSHTX 0xe2 /* Flush transmit buffer */
-#define PAUSETX 0xe3 /* Pause data transmission */
-#define RESUMETX 0xe4 /* Resume data transmission */
-#define SMINT 0xe5 /* Set Modem Interrupt */
-#define SAFLOWC 0xe6 /* Set Aux. flow control chars */
-#define SBREAK 0xe8 /* Send break */
-#define SMODEM 0xe9 /* Set 8530 modem control lines */
-#define SIFLAG 0xea /* Set UNIX iflags */
-#define SFLOWC 0xeb /* Set flow control characters */
-#define STLOW 0xec /* Set transmit low water mark */
-#define RPAUSE 0xee /* Pause receive */
-#define RRESUME 0xef /* Resume receive */
-#define CHRESET 0xf0 /* Reset Channel */
-#define BUFSETALL 0xf2 /* Set Tx & Rx buffer size avail*/
-#define SOFLAG 0xf3 /* Set UNIX oflags */
-#define SHFLOW 0xf4 /* Set hardware handshake */
-#define SCFLAG 0xf5 /* Set UNIX cflags */
-#define SVNEXT 0xf6 /* Set VNEXT character */
-#define SPINTFC 0xfc /* Reserved */
-#define SCOMMODE 0xfd /* Set RS232/422 mode */
-
-/************************************************************************
- * Modes for SCOMMODE
- ************************************************************************/
-#define MODE_232 0x00
-#define MODE_422 0x01
-
-/************************************************************************
- * Event flags.
- ************************************************************************/
-#define IFBREAK 0x01 /* Break received */
-#define IFTLW 0x02 /* Transmit low water */
-#define IFTEM 0x04 /* Transmitter empty */
-#define IFDATA 0x08 /* Receive data present */
-#define IFMODEM 0x20 /* Modem status change */
-
-/************************************************************************
- * Modem flags
- ************************************************************************/
-# define DM_RTS 0x02 /* Request to send */
-# define DM_CD 0x80 /* Carrier detect */
-# define DM_DSR 0x20 /* Data set ready */
-# define DM_CTS 0x10 /* Clear to send */
-# define DM_RI 0x40 /* Ring indicator */
-# define DM_DTR 0x01 /* Data terminal ready */
-
-/*
- * defines from dgap_conf.h
- */
-#define NULLNODE 0 /* header node, not used */
-#define BNODE 1 /* Board node */
-#define LNODE 2 /* Line node */
-#define CNODE 3 /* Concentrator node */
-#define MNODE 4 /* EBI Module node */
-#define TNODE 5 /* tty name prefix node */
-#define CUNODE 6 /* cu name prefix (non-SCO) */
-#define PNODE 7 /* trans. print prefix node */
-#define JNODE 8 /* maJor number node */
-#define ANODE 9 /* altpin */
-#define TSNODE 10 /* tty structure size */
-#define CSNODE 11 /* channel structure size */
-#define BSNODE 12 /* board structure size */
-#define USNODE 13 /* unit schedule structure size */
-#define FSNODE 14 /* f2200 structure size */
-#define VSNODE 15 /* size of VPIX structures */
-#define INTRNODE 16 /* enable interrupt */
-
-/* Enumeration of tokens */
-#define BEGIN 1
-#define END 2
-#define BOARD 10
-
-#define EPCFS 11 /* start of EPC family definitions */
-#define ICX 11
-#define MCX 13
-#define PCX 14
-#define IEPC 15
-#define EEPC 16
-#define MEPC 17
-#define IPCM 18
-#define EPCM 19
-#define MPCM 20
-#define PEPC 21
-#define PPCM 22
-#ifdef CP
-#define ICP 23
-#define ECP 24
-#define MCP 25
-#endif
-#define EPCFE 25 /* end of EPC family definitions */
-#define PC2E 26
-#define PC4E 27
-#define PC4E8K 28
-#define PC8E 29
-#define PC8E8K 30
-#define PC16E 31
-#define MC2E8K 34
-#define MC4E8K 35
-#define MC8E8K 36
-
-#define AVANFS 42 /* start of Avanstar family definitions */
-#define A8P 42
-#define A16P 43
-#define AVANFE 43 /* end of Avanstar family definitions */
-
-#define DA2000FS 44 /* start of AccelePort 2000 family definitions */
-#define DA22 44 /* AccelePort 2002 */
-#define DA24 45 /* AccelePort 2004 */
-#define DA28 46 /* AccelePort 2008 */
-#define DA216 47 /* AccelePort 2016 */
-#define DAR4 48 /* AccelePort RAS 4 port */
-#define DAR8 49 /* AccelePort RAS 8 port */
-#define DDR24 50 /* DataFire RAS 24 port */
-#define DDR30 51 /* DataFire RAS 30 port */
-#define DDR48 52 /* DataFire RAS 48 port */
-#define DDR60 53 /* DataFire RAS 60 port */
-#define DA2000FE 53 /* end of AccelePort 2000/RAS family definitions */
-
-#define PCXRFS 106 /* start of PCXR family definitions */
-#define APORT4 106
-#define APORT8 107
-#define PAPORT4 108
-#define PAPORT8 109
-#define APORT4_920I 110
-#define APORT8_920I 111
-#define APORT4_920P 112
-#define APORT8_920P 113
-#define APORT2_920P 114
-#define PCXRFE 117 /* end of PCXR family definitions */
-
-#define LINE 82
-#ifdef T1
-#define T1M 83
-#define E1M 84
-#endif
-#define CONC 64
-#define CX 65
-#define EPC 66
-#define MOD 67
-#define PORTS 68
-#define METHOD 69
-#define CUSTOM 70
-#define BASIC 71
-#define STATUS 72
-#define MODEM 73
-/* The following tokens can appear in multiple places */
-#define SPEED 74
-#define NPORTS 75
-#define ID 76
-#define CABLE 77
-#define CONNECT 78
-#define MEM 80
-#define DPSZ 81
-
-#define TTYN 90
-#define CU 91
-#define PRINT 92
-#define XPRINT 93
-#define CMAJOR 94
-#define ALTPIN 95
-#define STARTO 96
-#define USEINTR 97
-#define PCIINFO 98
-
-#define TTSIZ 100
-#define CHSIZ 101
-#define BSSIZ 102
-#define UNTSIZ 103
-#define F2SIZ 104
-#define VPSIZ 105
-
-#define TOTAL_BOARD 2
-#define CURRENT_BRD 4
-#define BOARD_TYPE 6
-#define IO_ADDRESS 8
-#define MEM_ADDRESS 10
-
-#define FIELDS_PER_PAGE 18
-
-#define TB_FIELD 1
-#define CB_FIELD 3
-#define BT_FIELD 5
-#define IO_FIELD 7
-#define ID_FIELD 8
-#define ME_FIELD 9
-#define TTY_FIELD 11
-#define CU_FIELD 13
-#define PR_FIELD 15
-#define MPR_FIELD 17
-
-#define MAX_FIELD 512
-
-#define INIT 0
-#define NITEMS 128
-#define MAX_ITEM 512
-
-#define DSCRINST 1
-#define DSCRNUM 3
-#define ALTPINQ 5
-#define SSAVE 7
-
-#define DSCR "32"
-#define ONETONINE "123456789"
-#define ALL "1234567890"
-
-/*
- * All the possible states the driver can be while being loaded.
- */
-enum {
- DRIVER_INITIALIZED = 0,
- DRIVER_READY
-};
-
-/*
- * All the possible states the board can be while booting up.
- */
-enum {
- BOARD_FAILED = 0,
- BOARD_READY
-};
-
-/*
- * All the possible states that a requested concentrator image can be in.
- */
-enum {
- NO_PENDING_CONCENTRATOR_REQUESTS = 0,
- NEED_CONCENTRATOR,
- REQUESTED_CONCENTRATOR
-};
-
-/*
- * Modem line constants are defined as macros because DSR and
- * DCD are swapable using the ditty altpin option.
- */
-#define D_CD(ch) ch->ch_cd /* Carrier detect */
-#define D_DSR(ch) ch->ch_dsr /* Data set ready */
-#define D_RTS(ch) DM_RTS /* Request to send */
-#define D_CTS(ch) DM_CTS /* Clear to send */
-#define D_RI(ch) DM_RI /* Ring indicator */
-#define D_DTR(ch) DM_DTR /* Data terminal ready */
-
-/*************************************************************************
- *
- * Structures and closely related defines.
- *
- *************************************************************************/
-
-/*
- * A structure to hold a statistics counter. We also
- * compute moving averages for this counter.
- */
-struct macounter {
- u32 cnt; /* Total count */
- ulong accum; /* Acuumulator per period */
- ulong sma; /* Simple moving average */
- ulong ema; /* Exponential moving average */
-};
-
-/************************************************************************
- * Device flag definitions for bd_flags.
- ************************************************************************/
-#define BD_FEP5PLUS 0x0001 /* Supports FEP5 Plus commands */
-#define BD_HAS_VPD 0x0002 /* Board has VPD info available */
-
-/*
- * Per-board information
- */
-struct board_t {
- int magic; /* Board Magic number. */
- int boardnum; /* Board number: 0-3 */
-
- int type; /* Type of board */
- char *name; /* Product Name */
- struct pci_dev *pdev; /* Pointer to the pci_dev struct */
- u16 vendor; /* PCI vendor ID */
- u16 device; /* PCI device ID */
- u16 subvendor; /* PCI subsystem vendor ID */
- u16 subdevice; /* PCI subsystem device ID */
- u8 rev; /* PCI revision ID */
- uint pci_bus; /* PCI bus value */
- uint pci_slot; /* PCI slot value */
- u16 maxports; /* MAX ports this board can handle */
- u8 vpd[VPDSIZE]; /* VPD of board, if found */
- u32 bd_flags; /* Board flags */
-
- spinlock_t bd_lock; /* Used to protect board */
-
- u32 state; /* State of card. */
- wait_queue_head_t state_wait; /* Place to sleep on for state change */
-
- struct tasklet_struct helper_tasklet; /* Poll helper tasklet */
-
- u32 wait_for_bios;
- u32 wait_for_fep;
-
- struct cnode *bd_config; /* Config of board */
-
- u16 nasync; /* Number of ports on card */
-
- ulong irq; /* Interrupt request number */
- ulong intr_count; /* Count of interrupts */
- u32 intr_used; /* Non-zero if using interrupts */
- u32 intr_running; /* Non-zero if FEP knows its doing */
- /* interrupts */
-
- ulong port; /* Start of base io port of the card */
- ulong port_end; /* End of base io port of the card */
- ulong membase; /* Start of base memory of the card */
- ulong membase_end; /* End of base memory of the card */
-
- u8 __iomem *re_map_port; /* Remapped io port of the card */
- u8 __iomem *re_map_membase;/* Remapped memory of the card */
-
- u8 inhibit_poller; /* Tells the poller to leave us alone */
-
- struct channel_t *channels[MAXPORTS]; /* array of pointers to our */
- /* channels. */
-
- struct tty_driver *serial_driver;
- struct tty_port *serial_ports;
- char serial_name[200];
- struct tty_driver *print_driver;
- struct tty_port *printer_ports;
- char print_name[200];
-
- struct bs_t __iomem *bd_bs; /* Base structure pointer */
-
- char *flipbuf; /* Our flip buffer, alloced if */
- /* board is found */
- char *flipflagbuf; /* Our flip flag buffer, alloced */
- /* if board is found */
-
- u16 dpatype; /* The board "type", as defined */
- /* by DPA */
- u16 dpastatus; /* The board "status", as defined */
- /* by DPA */
-
- u32 conc_dl_status; /* Status of any pending conc */
- /* download */
-};
-
-/************************************************************************
- * Unit flag definitions for un_flags.
- ************************************************************************/
-#define UN_ISOPEN 0x0001 /* Device is open */
-#define UN_CLOSING 0x0002 /* Line is being closed */
-#define UN_IMM 0x0004 /* Service immediately */
-#define UN_BUSY 0x0008 /* Some work this channel */
-#define UN_BREAKI 0x0010 /* Input break received */
-#define UN_PWAIT 0x0020 /* Printer waiting for terminal */
-#define UN_TIME 0x0040 /* Waiting on time */
-#define UN_EMPTY 0x0080 /* Waiting output queue empty */
-#define UN_LOW 0x0100 /* Waiting output low water mark*/
-#define UN_EXCL_OPEN 0x0200 /* Open for exclusive use */
-#define UN_WOPEN 0x0400 /* Device waiting for open */
-#define UN_WIOCTL 0x0800 /* Device waiting for open */
-#define UN_HANGUP 0x8000 /* Carrier lost */
-
-struct device;
-
-/************************************************************************
- * Structure for terminal or printer unit.
- ************************************************************************/
-struct un_t {
- int magic; /* Unit Magic Number. */
- struct channel_t *un_ch;
- u32 un_time;
- u32 un_type;
- int un_open_count; /* Counter of opens to port */
- struct tty_struct *un_tty;/* Pointer to unit tty structure */
- u32 un_flags; /* Unit flags */
- wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */
- u32 un_dev; /* Minor device number */
- tcflag_t un_oflag; /* oflags being done on board */
- tcflag_t un_lflag; /* lflags being done on board */
- struct device *un_sysfs;
-};
-
-/************************************************************************
- * Device flag definitions for ch_flags.
- ************************************************************************/
-#define CH_PRON 0x0001 /* Printer on string */
-#define CH_OUT 0x0002 /* Dial-out device open */
-#define CH_STOP 0x0004 /* Output is stopped */
-#define CH_STOPI 0x0008 /* Input is stopped */
-#define CH_CD 0x0010 /* Carrier is present */
-#define CH_FCAR 0x0020 /* Carrier forced on */
-
-#define CH_RXBLOCK 0x0080 /* Enable rx blocked flag */
-#define CH_WLOW 0x0100 /* Term waiting low event */
-#define CH_WEMPTY 0x0200 /* Term waiting empty event */
-#define CH_RENABLE 0x0400 /* Buffer just emptied */
-#define CH_RACTIVE 0x0800 /* Process active in xxread() */
-#define CH_RWAIT 0x1000 /* Process waiting in xxread() */
-#define CH_BAUD0 0x2000 /* Used for checking B0 transitions */
-#define CH_HANGUP 0x8000 /* Hangup received */
-
-/*
- * Definitions for ch_sniff_flags
- */
-#define SNIFF_OPEN 0x1
-#define SNIFF_WAIT_DATA 0x2
-#define SNIFF_WAIT_SPACE 0x4
-
-/************************************************************************
- *** Definitions for Digi ditty(1) command.
- ************************************************************************/
-
-/************************************************************************
- * This module provides application access to special Digi
- * serial line enhancements which are not standard UNIX(tm) features.
- ************************************************************************/
-
-#if !defined(TIOCMODG)
-
-#define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */
-#define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */
-
-#ifndef TIOCM_LE
-#define TIOCM_LE 0x01 /* line enable */
-#define TIOCM_DTR 0x02 /* data terminal ready */
-#define TIOCM_RTS 0x04 /* request to send */
-#define TIOCM_ST 0x08 /* secondary transmit */
-#define TIOCM_SR 0x10 /* secondary receive */
-#define TIOCM_CTS 0x20 /* clear to send */
-#define TIOCM_CAR 0x40 /* carrier detect */
-#define TIOCM_RNG 0x80 /* ring indicator */
-#define TIOCM_DSR 0x100 /* data set ready */
-#define TIOCM_RI TIOCM_RNG /* ring (alternate) */
-#define TIOCM_CD TIOCM_CAR /* carrier detect (alt) */
-#endif
-
-#endif
-
-#if !defined(TIOCMSET)
-#define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */
-#define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */
-#endif
-
-#if !defined(TIOCMBIC)
-#define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */
-#define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */
-#endif
-
-#if !defined(TIOCSDTR)
-#define TIOCSDTR (('e'<<8) | 0) /* set DTR */
-#define TIOCCDTR (('e'<<8) | 1) /* clear DTR */
-#endif
-
-/************************************************************************
- * Ioctl command arguments for DIGI parameters.
- ************************************************************************/
-#define DIGI_GETA (('e'<<8) | 94) /* Read params */
-
-#define DIGI_SETA (('e'<<8) | 95) /* Set params */
-#define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */
-#define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */
-
-#define DIGI_KME (('e'<<8) | 98) /* Read/Write Host */
- /* Adapter Memory */
-
-#define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */
- /* control characters */
-#define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */
- /* control characters */
-#define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */
- /* flow control chars */
-#define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */
- /* flow control chars */
-
-#define DIGI_GEDELAY (('d'<<8) | 246) /* Get edelay */
-#define DIGI_SEDELAY (('d'<<8) | 247) /* Set edelay */
-
-struct digiflow_t {
- unsigned char startc; /* flow cntl start char */
- unsigned char stopc; /* flow cntl stop char */
-};
-
-#ifdef FLOW_2200
-#define F2200_GETA (('e'<<8) | 104) /* Get 2x36 flow cntl flags */
-#define F2200_SETAW (('e'<<8) | 105) /* Set 2x36 flow cntl flags */
-#define F2200_MASK 0x03 /* 2200 flow cntl bit mask */
-#define FCNTL_2200 0x01 /* 2x36 terminal flow cntl */
-#define PCNTL_2200 0x02 /* 2x36 printer flow cntl */
-#define F2200_XON 0xf8
-#define P2200_XON 0xf9
-#define F2200_XOFF 0xfa
-#define P2200_XOFF 0xfb
-
-#define FXOFF_MASK 0x03 /* 2200 flow status mask */
-#define RCVD_FXOFF 0x01 /* 2x36 Terminal XOFF rcvd */
-#define RCVD_PXOFF 0x02 /* 2x36 Printer XOFF rcvd */
-#endif
-
-/************************************************************************
- * Values for digi_flags
- ************************************************************************/
-#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */
-#define DIGI_FAST 0x0002 /* Fast baud rates */
-#define RTSPACE 0x0004 /* RTS input flow control */
-#define CTSPACE 0x0008 /* CTS output flow control */
-#define DSRPACE 0x0010 /* DSR output flow control */
-#define DCDPACE 0x0020 /* DCD output flow control */
-#define DTRPACE 0x0040 /* DTR input flow control */
-#define DIGI_COOK 0x0080 /* Cooked processing done in FEP */
-#define DIGI_FORCEDCD 0x0100 /* Force carrier */
-#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */
-#define DIGI_AIXON 0x0400 /* Aux flow control in fep */
-#define DIGI_PRINTER 0x0800 /* Hold port open for flow cntrl*/
-#define DIGI_PP_INPUT 0x1000 /* Change parallel port to input*/
-#define DIGI_DTR_TOGGLE 0x2000 /* Support DTR Toggle */
-#define DIGI_422 0x4000 /* for 422/232 selectable panel */
-#define DIGI_RTS_TOGGLE 0x8000 /* Support RTS Toggle */
-
-/************************************************************************
- * These options are not supported on the comxi.
- ************************************************************************/
-#define DIGI_COMXI (DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE)
-
-#define DIGI_PLEN 28 /* String length */
-#define DIGI_TSIZ 10 /* Terminal string len */
-
-/************************************************************************
- * Structure used with ioctl commands for DIGI parameters.
- ************************************************************************/
-struct digi_t {
- unsigned short digi_flags; /* Flags (see above) */
- unsigned short digi_maxcps; /* Max printer CPS */
- unsigned short digi_maxchar; /* Max chars in print queue */
- unsigned short digi_bufsize; /* Buffer size */
- unsigned char digi_onlen; /* Length of ON string */
- unsigned char digi_offlen; /* Length of OFF string */
- char digi_onstr[DIGI_PLEN]; /* Printer on string */
- char digi_offstr[DIGI_PLEN]; /* Printer off string */
- char digi_term[DIGI_TSIZ]; /* terminal string */
-};
-
-/************************************************************************
- * KME definitions and structures.
- ************************************************************************/
-#define RW_IDLE 0 /* Operation complete */
-#define RW_READ 1 /* Read Concentrator Memory */
-#define RW_WRITE 2 /* Write Concentrator Memory */
-
-struct rw_t {
- unsigned char rw_req; /* Request type */
- unsigned char rw_board; /* Host Adapter board number */
- unsigned char rw_conc; /* Concentrator number */
- unsigned char rw_reserved; /* Reserved for expansion */
- unsigned long rw_addr; /* Address in concentrator */
- unsigned short rw_size; /* Read/write request length */
- unsigned char rw_data[128]; /* Data to read/write */
-};
-
-/************************************************************************
- * Structure to get driver status information
- ************************************************************************/
-struct digi_dinfo {
- unsigned long dinfo_nboards; /* # boards configured */
- char dinfo_reserved[12]; /* for future expansion */
- char dinfo_version[16]; /* driver version */
-};
-
-#define DIGI_GETDD (('d'<<8) | 248) /* get driver info */
-
-/************************************************************************
- * Structure used with ioctl commands for per-board information
- *
- * physsize and memsize differ when board has "windowed" memory
- ************************************************************************/
-struct digi_info {
- unsigned long info_bdnum; /* Board number (0 based) */
- unsigned long info_ioport; /* io port address */
- unsigned long info_physaddr; /* memory address */
- unsigned long info_physsize; /* Size of host mem window */
- unsigned long info_memsize; /* Amount of dual-port mem */
- /* on board */
- unsigned short info_bdtype; /* Board type */
- unsigned short info_nports; /* number of ports */
- char info_bdstate; /* board state */
- char info_reserved[7]; /* for future expansion */
-};
-
-#define DIGI_GETBD (('d'<<8) | 249) /* get board info */
-
-struct digi_stat {
- unsigned int info_chan; /* Channel number (0 based) */
- unsigned int info_brd; /* Board number (0 based) */
- unsigned long info_cflag; /* cflag for channel */
- unsigned long info_iflag; /* iflag for channel */
- unsigned long info_oflag; /* oflag for channel */
- unsigned long info_mstat; /* mstat for channel */
- unsigned long info_tx_data; /* tx_data for channel */
- unsigned long info_rx_data; /* rx_data for channel */
- unsigned long info_hflow; /* hflow for channel */
- unsigned long info_reserved[8]; /* for future expansion */
-};
-
-#define DIGI_GETSTAT (('d'<<8) | 244) /* get board info */
-/************************************************************************
- *
- * Structure used with ioctl commands for per-channel information
- *
- ************************************************************************/
-struct digi_ch {
- unsigned long info_bdnum; /* Board number (0 based) */
- unsigned long info_channel; /* Channel index number */
- unsigned long info_ch_cflag; /* Channel cflag */
- unsigned long info_ch_iflag; /* Channel iflag */
- unsigned long info_ch_oflag; /* Channel oflag */
- unsigned long info_chsize; /* Channel structure size */
- unsigned long info_sleep_stat; /* sleep status */
- dev_t info_dev; /* device number */
- unsigned char info_initstate; /* Channel init state */
- unsigned char info_running; /* Channel running state */
- long reserved[8]; /* reserved for future use */
-};
-
-/*
-* This structure is used with the DIGI_FEPCMD ioctl to
-* tell the driver which port to send the command for.
-*/
-struct digi_cmd {
- int cmd;
- int word;
- int ncmds;
- int chan; /* channel index (zero based) */
- int bdid; /* board index (zero based) */
-};
-
-/*
-* info_sleep_stat defines
-*/
-#define INFO_RUNWAIT 0x0001
-#define INFO_WOPEN 0x0002
-#define INFO_TTIOW 0x0004
-#define INFO_CH_RWAIT 0x0008
-#define INFO_CH_WEMPTY 0x0010
-#define INFO_CH_WLOW 0x0020
-#define INFO_XXBUF_BUSY 0x0040
-
-#define DIGI_GETCH (('d'<<8) | 245) /* get board info */
-
-/* Board type definitions */
-
-#define SUBTYPE 0007
-#define T_PCXI 0000
-#define T_PCXM 0001
-#define T_PCXE 0002
-#define T_PCXR 0003
-#define T_SP 0004
-#define T_SP_PLUS 0005
-# define T_HERC 0000
-# define T_HOU 0001
-# define T_LON 0002
-# define T_CHA 0003
-#define FAMILY 0070
-#define T_COMXI 0000
-#define T_PCXX 0010
-#define T_CX 0020
-#define T_EPC 0030
-#define T_PCLITE 0040
-#define T_SPXX 0050
-#define T_AVXX 0060
-#define T_DXB 0070
-#define T_A2K_4_8 0070
-#define BUSTYPE 0700
-#define T_ISABUS 0000
-#define T_MCBUS 0100
-#define T_EISABUS 0200
-#define T_PCIBUS 0400
-
-/* Board State Definitions */
-
-#define BD_RUNNING 0x0
-#define BD_REASON 0x7f
-#define BD_NOTFOUND 0x1
-#define BD_NOIOPORT 0x2
-#define BD_NOMEM 0x3
-#define BD_NOBIOS 0x4
-#define BD_NOFEP 0x5
-#define BD_FAILED 0x6
-#define BD_ALLOCATED 0x7
-#define BD_TRIBOOT 0x8
-#define BD_BADKME 0x80
-
-#define DIGI_LOOPBACK (('d'<<8) | 252) /* Enable/disable UART */
- /* internal loopback */
-#define DIGI_SPOLL (('d'<<8) | 254) /* change poller rate */
-
-#define DIGI_SETCUSTOMBAUD _IOW('e', 106, int) /* Set integer baud rate */
-#define DIGI_GETCUSTOMBAUD _IOR('e', 107, int) /* Get integer baud rate */
-#define DIGI_RESET_PORT (('e'<<8) | 93) /* Reset port */
-
-/************************************************************************
- * Channel information structure.
- ************************************************************************/
-struct channel_t {
- int magic; /* Channel Magic Number */
- struct bs_t __iomem *ch_bs; /* Base structure pointer */
- struct cm_t __iomem *ch_cm; /* Command queue pointer */
- struct board_t *ch_bd; /* Board structure pointer */
- u8 __iomem *ch_vaddr; /* FEP memory origin */
- u8 __iomem *ch_taddr; /* Write buffer origin */
- u8 __iomem *ch_raddr; /* Read buffer origin */
- struct digi_t ch_digi; /* Transparent Print structure */
- struct un_t ch_tun; /* Terminal unit info */
- struct un_t ch_pun; /* Printer unit info */
-
- spinlock_t ch_lock; /* provide for serialization */
- wait_queue_head_t ch_flags_wait;
-
- u32 pscan_state;
- u8 pscan_savechar;
-
- u32 ch_portnum; /* Port number, 0 offset. */
- u32 ch_open_count; /* open count */
- u32 ch_flags; /* Channel flags */
-
- u32 ch_cpstime; /* Time for CPS calculations */
-
- tcflag_t ch_c_iflag; /* channel iflags */
- tcflag_t ch_c_cflag; /* channel cflags */
- tcflag_t ch_c_oflag; /* channel oflags */
- tcflag_t ch_c_lflag; /* channel lflags */
-
- u16 ch_fepiflag; /* FEP tty iflags */
- u16 ch_fepcflag; /* FEP tty cflags */
- u16 ch_fepoflag; /* FEP tty oflags */
- u16 ch_wopen; /* Waiting for open process cnt */
- u16 ch_tstart; /* Transmit buffer start */
- u16 ch_tsize; /* Transmit buffer size */
- u16 ch_rstart; /* Receive buffer start */
- u16 ch_rsize; /* Receive buffer size */
- u16 ch_rdelay; /* Receive delay time */
-
- u16 ch_tlw; /* Our currently set low water mark */
-
- u16 ch_cook; /* Output character mask */
-
- u8 ch_card; /* Card channel is on */
- u8 ch_stopc; /* Stop character */
- u8 ch_startc; /* Start character */
-
- u8 ch_mostat; /* FEP output modem status */
- u8 ch_mistat; /* FEP input modem status */
- u8 ch_mforce; /* Modem values to be forced */
- u8 ch_mval; /* Force values */
- u8 ch_fepstopc; /* FEP stop character */
- u8 ch_fepstartc; /* FEP start character */
-
- u8 ch_astopc; /* Auxiliary Stop character */
- u8 ch_astartc; /* Auxiliary Start character */
- u8 ch_fepastopc; /* Auxiliary FEP stop char */
- u8 ch_fepastartc; /* Auxiliary FEP start char */
-
- u8 ch_hflow; /* FEP hardware handshake */
- u8 ch_dsr; /* stores real dsr value */
- u8 ch_cd; /* stores real cd value */
- u8 ch_tx_win; /* channel tx buffer window */
- u8 ch_rx_win; /* channel rx buffer window */
- uint ch_custom_speed; /* Custom baud, if set */
- uint ch_baud_info; /* Current baud info for /proc output */
- ulong ch_rxcount; /* total of data received so far */
- ulong ch_txcount; /* total of data transmitted so far */
- ulong ch_err_parity; /* Count of parity errors on channel */
- ulong ch_err_frame; /* Count of framing errors on channel */
- ulong ch_err_break; /* Count of breaks on channel */
- ulong ch_err_overrun; /* Count of overruns on channel */
-};
-
-/************************************************************************
- * Command structure definition.
- ************************************************************************/
-struct cm_t {
- unsigned short cm_head; /* Command buffer head offset */
- unsigned short cm_tail; /* Command buffer tail offset */
- unsigned short cm_start; /* start offset of buffer */
- unsigned short cm_max; /* last offset of buffer */
-};
-
-/************************************************************************
- * Event structure definition.
- ************************************************************************/
-struct ev_t {
- unsigned short ev_head; /* Command buffer head offset */
- unsigned short ev_tail; /* Command buffer tail offset */
- unsigned short ev_start; /* start offset of buffer */
- unsigned short ev_max; /* last offset of buffer */
-};
-
-/************************************************************************
- * Download buffer structure.
- ************************************************************************/
-struct downld_t {
- u8 dl_type; /* Header */
- u8 dl_seq; /* Download sequence */
- ushort dl_srev; /* Software revision number */
- ushort dl_lrev; /* Low revision number */
- ushort dl_hrev; /* High revision number */
- ushort dl_seg; /* Start segment address */
- ushort dl_size; /* Number of bytes to download */
- u8 dl_data[1024]; /* Download data */
-};
-
-/************************************************************************
- * Per channel buffer structure
- ************************************************************************
- * Base Structure Entries Usage Meanings to Host *
- * *
- * W = read write R = read only *
- * C = changed by commands only *
- * U = unknown (may be changed w/o notice) *
- ************************************************************************/
-struct bs_t {
- unsigned short tp_jmp; /* Transmit poll jump */
- unsigned short tc_jmp; /* Cooked procedure jump */
- unsigned short ri_jmp; /* Not currently used */
- unsigned short rp_jmp; /* Receive poll jump */
-
- unsigned short tx_seg; /* W Tx segment */
- unsigned short tx_head; /* W Tx buffer head offset */
- unsigned short tx_tail; /* R Tx buffer tail offset */
- unsigned short tx_max; /* W Tx buffer size - 1 */
-
- unsigned short rx_seg; /* W Rx segment */
- unsigned short rx_head; /* W Rx buffer head offset */
- unsigned short rx_tail; /* R Rx buffer tail offset */
- unsigned short rx_max; /* W Rx buffer size - 1 */
-
- unsigned short tx_lw; /* W Tx buffer low water mark */
- unsigned short rx_lw; /* W Rx buffer low water mark */
- unsigned short rx_hw; /* W Rx buffer high water mark*/
- unsigned short incr; /* W Increment to next channel*/
-
- unsigned short fepdev; /* U SCC device base address */
- unsigned short edelay; /* W Exception delay */
- unsigned short blen; /* W Break length */
- unsigned short btime; /* U Break complete time */
-
- unsigned short iflag; /* C UNIX input flags */
- unsigned short oflag; /* C UNIX output flags */
- unsigned short cflag; /* C UNIX control flags */
- unsigned short wfill[13]; /* U Reserved for expansion */
-
- unsigned char num; /* U Channel number */
- unsigned char ract; /* U Receiver active counter */
- unsigned char bstat; /* U Break status bits */
- unsigned char tbusy; /* W Transmit busy */
- unsigned char iempty; /* W Transmit empty event */
- /* enable */
- unsigned char ilow; /* W Transmit low-water event */
- /* enable */
- unsigned char idata; /* W Receive data interrupt */
- /* enable */
- unsigned char eflag; /* U Host event flags */
-
- unsigned char tflag; /* U Transmit flags */
- unsigned char rflag; /* U Receive flags */
- unsigned char xmask; /* U Transmit ready flags */
- unsigned char xval; /* U Transmit ready value */
- unsigned char m_stat; /* RC Modem status bits */
- unsigned char m_change; /* U Modem bits which changed */
- unsigned char m_int; /* W Modem interrupt enable */
- /* bits */
- unsigned char m_last; /* U Last modem status */
-
- unsigned char mtran; /* C Unreported modem trans */
- unsigned char orun; /* C Buffer overrun occurred */
- unsigned char astartc; /* W Auxiliary Xon char */
- unsigned char astopc; /* W Auxiliary Xoff char */
- unsigned char startc; /* W Xon character */
- unsigned char stopc; /* W Xoff character */
- unsigned char vnextc; /* W Vnext character */
- unsigned char hflow; /* C Software flow control */
-
- unsigned char fillc; /* U Delay Fill character */
- unsigned char ochar; /* U Saved output character */
- unsigned char omask; /* U Output character mask */
-
- unsigned char bfill[13]; /* U Reserved for expansion */
-
- unsigned char scc[16]; /* U SCC registers */
-};
-
-struct cnode {
- struct cnode *next;
- int type;
- int numbrd;
-
- union {
- struct {
- char type; /* Board Type */
- long addr; /* Memory Address */
- char *addrstr; /* Memory Address in string */
- long pcibus; /* PCI BUS */
- char *pcibusstr; /* PCI BUS in string */
- long pcislot; /* PCI SLOT */
- char *pcislotstr; /* PCI SLOT in string */
- long nport; /* Number of Ports */
- char *id; /* tty id */
- long start; /* start of tty counting */
- char *method; /* Install method */
- char v_addr;
- char v_pcibus;
- char v_pcislot;
- char v_nport;
- char v_id;
- char v_start;
- char v_method;
- char line1;
- char line2;
- char conc1; /* total concs in line1 */
- char conc2; /* total concs in line2 */
- char module1; /* total modules for line1 */
- char module2; /* total modules for line2 */
- char *status; /* config status */
- char *dimstatus; /* Y/N */
- int status_index; /* field pointer */
- } board;
-
- struct {
- char *cable;
- char v_cable;
- long speed;
- char v_speed;
- } line;
-
- struct {
- char type;
- char *connect;
- long speed;
- long nport;
- char *id;
- char *idstr;
- long start;
- char v_connect;
- char v_speed;
- char v_nport;
- char v_id;
- char v_start;
- } conc;
-
- struct {
- char type;
- long nport;
- char *id;
- char *idstr;
- long start;
- char v_nport;
- char v_id;
- char v_start;
- } module;
-
- char *ttyname;
- char *cuname;
- char *printname;
- long majornumber;
- long altpin;
- long ttysize;
- long chsize;
- long bssize;
- long unsize;
- long f2size;
- long vpixsize;
- long useintr;
- } u;
-};
-#endif
recipient = (u8)(p_ctrl->bRequestType & USB_RECIP_MASK);
selector = p_ctrl->wValue;
if ((recipient == USB_RECIP_DEVICE) &&
- (selector == USB_DEVICE_TEST_MODE)) {
+ (selector == USB_DEVICE_TEST_MODE)) {
test_mode = (u32)(p_ctrl->wIndex >> 8);
_nbu2ss_set_test_mode(udc, test_mode);
}
if (req->unaligned) {
if (direct == USB_DIR_OUT)
memcpy(req->req.buf, ep->virt_buf,
- req->req.actual & 0xfffffffc);
+ req->req.actual & 0xfffffffc);
} else
dma_unmap_single(udc->gadget.dev.parent,
- req->req.dma, req->req.length,
+ req->req.dma, req->req.length,
(direct == USB_DIR_IN)
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
} else {
if (!req->unaligned)
dma_sync_single_for_cpu(udc->gadget.dev.parent,
- req->req.dma, req->req.length,
+ req->req.dma, req->req.length,
(direct == USB_DIR_IN)
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
int result = -EOPNOTSUPP;
if ((udc->ctrl.wLength != 0x0000) ||
- (direction != USB_DIR_OUT)) {
+ (direction != USB_DIR_OUT)) {
return -EINVAL;
}
u32 wValue = udc->ctrl.wValue;
if ((udc->ctrl.bRequestType != 0x00) ||
- (udc->ctrl.wIndex != 0x0000) ||
+ (udc->ctrl.wIndex != 0x0000) ||
(udc->ctrl.wLength != 0x0000)) {
return -EINVAL;
}
u32 ConfigValue = (u32)(udc->ctrl.wValue & 0x00ff);
if ((udc->ctrl.wIndex != 0x0000) ||
- (udc->ctrl.wLength != 0x0000) ||
+ (udc->ctrl.wLength != 0x0000) ||
(udc->ctrl.bRequestType != 0x00)) {
return -EINVAL;
}
#ifdef USE_DMA
if ((ep->direct == USB_DIR_OUT) && (ep->epnum > 0) &&
- (req->req.dma != 0))
+ (req->req.dma != 0))
_nbu2ss_dma_unmap_single(udc, ep, req, USB_DIR_OUT);
#endif
_nbu2ss_writel(&udc->p_regs->AHBSCTR, WAIT_MODE);
_nbu2ss_writel(&udc->p_regs->AHBMCTR,
- HBUSREQ_MODE | HTRANS_MODE | WBURST_TYPE);
+ HBUSREQ_MODE | HTRANS_MODE | WBURST_TYPE);
while (!(_nbu2ss_readl(&udc->p_regs->EPCTR) & PLL_LOCK)) {
waitcnt++;
if (unlikely(!udc->driver)) {
dev_err(udc->dev, "%s, bogus device state %p\n", __func__,
- udc->driver);
+ udc->driver);
return -ESHUTDOWN;
}
if (ep->epnum > 0) {
if (ep->direct == USB_DIR_IN)
memcpy(ep->virt_buf, req->req.buf,
- req->req.length);
+ req->req.length);
}
}
if ((ep->epnum > 0) && (ep->direct == USB_DIR_OUT) &&
- (req->req.dma != 0))
+ (req->req.dma != 0))
_nbu2ss_dma_map_single(udc, ep, req, USB_DIR_OUT);
#endif
result = _nbu2ss_start_transfer(udc, ep, req, FALSE);
if (result < 0) {
dev_err(udc->dev, " *** %s, result = %d\n", __func__,
- result);
+ result);
list_del(&req->queue);
} else if ((ep->epnum > 0) && (ep->direct == USB_DIR_OUT)) {
#ifdef USE_DMA
if (req->req.length < 4 &&
- req->req.length == req->req.actual)
+ req->req.length == req->req.actual)
#else
if (req->req.length == req->req.actual)
#endif
/*-------------------------------------------------------------------------*/
static int nbu2ss_gad_set_selfpowered(struct usb_gadget *pgadget,
- int is_selfpowered)
+ int is_selfpowered)
{
struct nbu2ss_udc *udc;
unsigned long flags;
ep->ep.ops = &nbu2ss_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep,
- i == 0 ? EP0_PACKETSIZE : EP_PACKETSIZE);
+ i == 0 ? EP0_PACKETSIZE
+ : EP_PACKETSIZE);
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
INIT_LIST_HEAD(&ep->queue);
/* VBUS Interrupt */
irq_set_irq_type(INT_VBUS, IRQ_TYPE_EDGE_BOTH);
status = request_irq(INT_VBUS,
- _nbu2ss_vbus_irq,
- IRQF_SHARED,
- driver_name,
- udc);
+ _nbu2ss_vbus_irq, IRQF_SHARED, driver_name, udc);
if (status != 0) {
dev_err(udc->dev, "request_irq(INT_VBUS) failed\n");
help
Framebuffer support for SSD1289
+config FB_TFT_SSD1305
+ tristate "FB driver for the SSD1305 OLED Controller"
+ depends on FB_TFT
+ help
+ Framebuffer support for SSD1305
+
config FB_TFT_SSD1306
tristate "FB driver for the SSD1306 OLED Controller"
depends on FB_TFT
help
Framebuffer support for SSD1306
+config FB_TFT_SSD1325
+ tristate "FB driver for the SSD1325 OLED Controller"
+ depends on FB_TFT
+ help
+ Framebuffer support for SSD1305
+
config FB_TFT_SSD1331
tristate "FB driver for the SSD1331 LCD Controller"
depends on FB_TFT
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_SSD1305) += fb_ssd1305.o
obj-$(CONFIG_FB_TFT_SSD1306) += fb_ssd1306.o
+obj-$(CONFIG_FB_TFT_SSD1305) += fb_ssd1325.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
#include <linux/vmalloc.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
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);
+ write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
/* Display on (29h)
This command is used to recover from DISPLAY OFF mode.
Output from the Frame Memory is enabled. */
- write_reg(par, 0x29);
+ write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
mdelay(10);
return 0;
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
- write_reg(par, FBTFT_CASET, 0x00, xs, 0x00, xe);
- write_reg(par, FBTFT_RASET, 0x00, ys, 0x00, ye);
- write_reg(par, FBTFT_RAMWR);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS, 0x00, xs, 0x00, xe);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS, 0x00, ys, 0x00, ye);
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}
static int set_var(struct fbtft_par *par)
#define MV BIT(5)
switch (par->info->var.rotate) {
case 0:
- write_reg(par, 0x36, par->bgr << 3);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, par->bgr << 3);
break;
case 270:
- write_reg(par, 0x36, MX | MV | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MX | MV | (par->bgr << 3));
break;
case 180:
- write_reg(par, 0x36, MX | MY | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MX | MY | (par->bgr << 3));
break;
case 90:
- write_reg(par, 0x36, MY | MV | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MY | MV | (par->bgr << 3));
break;
}
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) */
+ /* Gamma Set (26h) */
+ write_reg(par, MIPI_DCS_SET_GAMMA_CURVE, 1 << CURVE(1, 14));
if (CURVE(1, 14))
return 0; /* only GC0 can be customized */
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
write_reg(par, 0x3A, 0x05);
/* MEM ACCESS */
- write_reg(par, 0x36, 0xC0);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, 0xC0);
/* SLPOUT - Sleep out & booster on */
- write_reg(par, 0x11);
+ write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
mdelay(150);
/* DISPON - Display On */
- write_reg(par, 0x29);
+ write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
/* RGBSET */
- write_reg(par, 0x2D,
+ write_reg(par, MIPI_DCS_WRITE_LUT,
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,
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));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ mx | my | (par->bgr << 3));
break;
case 270:
- write_reg(par, 0x36, my | mv | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ my | mv | (par->bgr << 3));
break;
case 180:
- write_reg(par, 0x36, par->bgr << 3);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ par->bgr << 3);
break;
case 90:
- write_reg(par, 0x36, mx | mv | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ mx | mv | (par->bgr << 3));
break;
}
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
#include "fb_hx8357d.h"
par->fbtftops.reset(par);
/* Reset things like Gamma */
- write_reg(par, HX8357B_SWRESET);
+ write_reg(par, MIPI_DCS_SOFT_RESET);
usleep_range(5000, 7000);
/* setextc */
0x01);
/* 16 bit */
- write_reg(par, HX8357_COLMOD, 0x55);
+ write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
- write_reg(par, HX8357_MADCTL, 0xC0);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, 0xC0);
/* TE off */
- write_reg(par, HX8357_TEON, 0x00);
+ write_reg(par, MIPI_DCS_SET_TEAR_ON, 0x00);
/* tear line */
- write_reg(par, HX8357_TEARLINE, 0x00, 0x02);
+ write_reg(par, MIPI_DCS_SET_TEAR_SCANLINE, 0x00, 0x02);
/* Exit Sleep */
- write_reg(par, HX8357_SLPOUT);
+ write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
msleep(150);
/* display on */
- write_reg(par, HX8357_DISPON);
+ write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
usleep_range(5000, 7000);
return 0;
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
- /* Column addr set */
- write_reg(par, HX8357_CASET,
- xs >> 8, xs & 0xff, /* XSTART */
- xe >> 8, xe & 0xff); /* XEND */
-
- /* Row addr set */
- write_reg(par, HX8357_PASET,
- ys >> 8, ys & 0xff, /* YSTART */
- ye >> 8, ye & 0xff); /* YEND */
-
- /* write to RAM */
- write_reg(par, HX8357_RAMWR);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ xs >> 8, xs & 0xff, /* XSTART */
+ xe >> 8, xe & 0xff); /* XEND */
+
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ ys >> 8, ys & 0xff, /* YSTART */
+ ye >> 8, ye & 0xff); /* YEND */
+
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}
#define HX8357D_MADCTL_MY 0x80
val |= (par->bgr ? HX8357D_MADCTL_RGB : HX8357D_MADCTL_BGR);
/* Memory Access Control */
- write_reg(par, HX8357_MADCTL, val);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, val);
return 0;
}
#define HX8357_TFTWIDTH 320
#define HX8357_TFTHEIGHT 480
-#define HX8357B_NOP 0x00
-#define HX8357B_SWRESET 0x01
-#define HX8357B_RDDID 0x04
-#define HX8357B_RDDST 0x09
-
-#define HX8357B_RDPOWMODE 0x0A
-#define HX8357B_RDMADCTL 0x0B
-#define HX8357B_RDCOLMOD 0x0C
-#define HX8357B_RDDIM 0x0D
-#define HX8357B_RDDSDR 0x0F
-
-#define HX8357_SLPIN 0x10
-#define HX8357_SLPOUT 0x11
-#define HX8357B_PTLON 0x12
-#define HX8357B_NORON 0x13
-
-#define HX8357_INVOFF 0x20
-#define HX8357_INVON 0x21
-#define HX8357_DISPOFF 0x28
-#define HX8357_DISPON 0x29
-
-#define HX8357_CASET 0x2A
-#define HX8357_PASET 0x2B
-#define HX8357_RAMWR 0x2C
-#define HX8357_RAMRD 0x2E
-
-#define HX8357B_PTLAR 0x30
-#define HX8357_TEON 0x35
-#define HX8357_TEARLINE 0x44
-#define HX8357_MADCTL 0x36
-#define HX8357_COLMOD 0x3A
-
#define HX8357_SETOSC 0xB0
#define HX8357_SETPWR1 0xB1
#define HX8357B_SETDISPLAY 0xB2
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/delay.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
#endif
/* ILI9163C commands */
-#define CMD_NOP 0x00 /* Non operation*/
-#define CMD_SWRESET 0x01 /* Soft Reset */
-#define CMD_SLPIN 0x10 /* Sleep ON */
-#define CMD_SLPOUT 0x11 /* Sleep OFF */
-#define CMD_PTLON 0x12 /* Partial Mode ON */
-#define CMD_NORML 0x13 /* Normal Display ON */
-#define CMD_DINVOF 0x20 /* Display Inversion OFF */
-#define CMD_DINVON 0x21 /* Display Inversion ON */
-#define CMD_GAMMASET 0x26 /* Gamma Set (0x01[1],0x02[2],0x04[3],0x08[4]) */
-#define CMD_DISPOFF 0x28 /* Display OFF */
-#define CMD_DISPON 0x29 /* Display ON */
-#define CMD_IDLEON 0x39 /* Idle Mode ON */
-#define CMD_IDLEOF 0x38 /* Idle Mode OFF */
-#define CMD_CLMADRS 0x2A /* Column Address Set */
-#define CMD_PGEADRS 0x2B /* Page Address Set */
-
-#define CMD_RAMWR 0x2C /* Memory Write */
-#define CMD_RAMRD 0x2E /* Memory Read */
-#define CMD_CLRSPACE 0x2D /* Color Space : 4K/65K/262K */
-#define CMD_PARTAREA 0x30 /* Partial Area */
-#define CMD_VSCLLDEF 0x33 /* Vertical Scroll Definition */
-#define CMD_TEFXLON 0x34 /* Tearing Effect Line ON */
-#define CMD_TEFXLOF 0x35 /* Tearing Effect Line OFF */
-#define CMD_MADCTL 0x36 /* Memory Access Control */
-
-#define CMD_PIXFMT 0x3A /* Interface Pixel Format */
#define CMD_FRMCTR1 0xB1 /* Frame Rate Control
(In normal mode/Full colors) */
#define CMD_FRMCTR2 0xB2 /* Frame Rate Control (In Idle mode/8-colors) */
if (par->gpio.cs != -1)
gpio_set_value(par->gpio.cs, 0); /* Activate chip */
- write_reg(par, CMD_SWRESET); /* software reset */
+ write_reg(par, MIPI_DCS_SOFT_RESET); /* software reset */
mdelay(500);
- write_reg(par, CMD_SLPOUT); /* exit sleep */
+ write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE); /* exit sleep */
mdelay(5);
- write_reg(par, CMD_PIXFMT, 0x05); /* Set Color Format 16bit */
- write_reg(par, CMD_GAMMASET, 0x02); /* default gamma curve 3 */
+ write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
+ /* default gamma curve 3 */
+ write_reg(par, MIPI_DCS_SET_GAMMA_CURVE, 0x02);
#ifdef GAMMA_ADJ
write_reg(par, CMD_GAMRSEL, 0x01); /* Enable Gamma adj */
#endif
- write_reg(par, CMD_NORML);
+ write_reg(par, MIPI_DCS_ENTER_NORMAL_MODE);
write_reg(par, CMD_DFUNCTR, 0xff, 0x06);
/* Frame Rate Control (In normal mode/Full colors) */
write_reg(par, CMD_FRMCTR1, 0x08, 0x02);
write_reg(par, CMD_VCOMCTR1, 0x50, 0x63);
write_reg(par, CMD_VCOMOFFS, 0);
- write_reg(par, CMD_CLMADRS, 0, 0, 0, WIDTH); /* Set Column Address */
- write_reg(par, CMD_PGEADRS, 0, 0, 0, HEIGHT); /* Set Page Address */
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS, 0, 0, 0, WIDTH);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS, 0, 0, 0, HEIGHT);
- write_reg(par, CMD_DISPON); /* display ON */
- write_reg(par, CMD_RAMWR); /* Memory Write */
+ write_reg(par, MIPI_DCS_SET_DISPLAY_ON); /* display ON */
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START); /* Memory Write */
return 0;
}
{
switch (par->info->var.rotate) {
case 0:
- write_reg(par, CMD_CLMADRS, xs >> 8, xs & 0xff, xe >> 8,
- xe & 0xff);
- write_reg(par, CMD_PGEADRS,
- (ys + __OFFSET) >> 8, (ys + __OFFSET) & 0xff,
- (ye + __OFFSET) >> 8, (ye + __OFFSET) & 0xff);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ xs >> 8, xs & 0xff, xe >> 8, xe & 0xff);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ (ys + __OFFSET) >> 8, (ys + __OFFSET) & 0xff,
+ (ye + __OFFSET) >> 8, (ye + __OFFSET) & 0xff);
break;
case 90:
- write_reg(par, CMD_CLMADRS,
- (xs + __OFFSET) >> 8, (xs + __OFFSET) & 0xff,
- (xe + __OFFSET) >> 8, (xe + __OFFSET) & 0xff);
- write_reg(par, CMD_PGEADRS, ys >> 8, ys & 0xff, ye >> 8,
- ye & 0xff);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ (xs + __OFFSET) >> 8, (xs + __OFFSET) & 0xff,
+ (xe + __OFFSET) >> 8, (xe + __OFFSET) & 0xff);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ ys >> 8, ys & 0xff, ye >> 8, ye & 0xff);
break;
case 180:
case 270:
- write_reg(par, CMD_CLMADRS, xs >> 8, xs & 0xff, xe >> 8,
- xe & 0xff);
- write_reg(par, CMD_PGEADRS, ys >> 8, ys & 0xff, ye >> 8,
- ye & 0xff);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ xs >> 8, xs & 0xff, xe >> 8, xe & 0xff);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ ys >> 8, ys & 0xff, ye >> 8, ye & 0xff);
break;
default:
- par->info->var.rotate = 0; /* Fix incorrect setting */
+ /* Fix incorrect setting */
+ par->info->var.rotate = 0;
}
- write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}
/*
/* Colorspcae */
if (par->bgr)
mactrl_data |= (1 << 2);
- write_reg(par, CMD_MADCTL, mactrl_data);
- write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, mactrl_data);
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
return 0;
}
CURVE(0, 15)
);
- write_reg(par, CMD_RAMWR); /* Write Data to GRAM mode */
+ /* Write Data to GRAM mode */
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
return 0;
}
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/delay.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
/* COLMOD: Pixel Format Set */
/* 16 bits/pixel */
- write_reg(par, 0x3A, 0x55);
+ write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
/* Frame Rate Control */
/* Division ratio = fosc, Frame Rate = 79Hz */
/* Gamma Function Disable */
write_reg(par, 0xF2, 0x00);
- /* Gamma curve selected */
- write_reg(par, 0x26, 0x01);
+ /* Gamma curve selection */
+ write_reg(par, MIPI_DCS_SET_GAMMA_CURVE, 0x01);
/* Positive Gamma Correction */
write_reg(par, 0xE0,
0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1,
0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F);
- /* Sleep OUT */
- write_reg(par, 0x11);
+ write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
mdelay(120);
- /* Display ON */
- write_reg(par, 0x29);
+ write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
return 0;
}
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
- /* Column address */
- write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
- /* Row address */
- write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
- /* Memory write */
- write_reg(par, 0x2C);
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}
#define ILI9340_MADCTL_MV 0x20
break;
}
/* Memory Access Control */
- write_reg(par, 0x36, val | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, val | (par->bgr << 3));
return 0;
}
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
par->fbtftops.reset(par);
/* startup sequence for MI0283QT-9A */
- write_reg(par, 0x01); /* software reset */
+ write_reg(par, MIPI_DCS_SOFT_RESET);
mdelay(5);
- write_reg(par, 0x28); /* display off */
+ write_reg(par, MIPI_DCS_SET_DISPLAY_OFF);
/* --------------------------------------------------------- */
write_reg(par, 0xCF, 0x00, 0x83, 0x30);
write_reg(par, 0xED, 0x64, 0x03, 0x12, 0x81);
write_reg(par, 0xC5, 0x35, 0x3E);
write_reg(par, 0xC7, 0xBE);
/* ------------memory access control------------------------ */
- write_reg(par, 0x3A, 0x55); /* 16bit pixel */
+ write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 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);
+ write_reg(par, MIPI_DCS_SET_GAMMA_CURVE, 0x01);
/* ------------display-------------------------------------- */
write_reg(par, 0xB7, 0x07); /* entry mode set */
write_reg(par, 0xB6, 0x0A, 0x82, 0x27, 0x00);
- write_reg(par, 0x11); /* sleep out */
+ write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
mdelay(100);
- write_reg(par, 0x29); /* display on */
+ write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
mdelay(20);
return 0;
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
- /* Column address set */
- write_reg(par, 0x2A,
- (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF);
- /* Row address set */
- write_reg(par, 0x2B,
- (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF);
- /* Memory write */
- write_reg(par, 0x2C);
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}
-#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_Y BIT(7) /* MY row address order */
+#define MEM_X BIT(6) /* MX column address order */
+#define MEM_V BIT(5) /* MV row / column exchange */
+#define MEM_L BIT(4) /* ML vertical refresh order */
+#define MEM_H BIT(2) /* MH horizontal refresh order */
#define MEM_BGR (3) /* RGB-BGR Order */
static int set_var(struct fbtft_par *par)
{
switch (par->info->var.rotate) {
case 0:
- write_reg(par, 0x36, (1 << MEM_X) | (par->bgr << MEM_BGR));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MEM_X | (par->bgr << MEM_BGR));
break;
case 270:
- write_reg(par, 0x36,
- (1 << MEM_V) | (1 << MEM_L) | (par->bgr << MEM_BGR));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MEM_V | MEM_L | (par->bgr << MEM_BGR));
break;
case 180:
- write_reg(par, 0x36, (1 << MEM_Y) | (par->bgr << MEM_BGR));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ 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));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MEM_Y | MEM_X | MEM_V | (par->bgr << MEM_BGR));
break;
}
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
static int default_init_sequence[] = {
/* SLP_OUT - Sleep out */
- -1, 0x11,
+ -1, MIPI_DCS_EXIT_SLEEP_MODE,
-2, 50,
/* Power setting */
-1, 0xD0, 0x07, 0x42, 0x18,
/* Frame rate & inv. */
-1, 0xC5, 0x03,
/* Pixel format */
- -1, 0x3A, 0x55,
+ -1, MIPI_DCS_SET_PIXEL_FORMAT, 0x55,
/* Gamma */
-1, 0xC8, 0x00, 0x32, 0x36, 0x45, 0x06, 0x16,
0x37, 0x75, 0x77, 0x54, 0x0C, 0x00,
/* DISP_ON */
- -1, 0x29,
+ -1, MIPI_DCS_SET_DISPLAY_ON,
-3
};
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
- /* column address */
- write_reg(par, 0x2a, xs >> 8, xs & 0xff, xe >> 8, xe & 0xff);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ xs >> 8, xs & 0xff, xe >> 8, xe & 0xff);
- /* Row address */
- write_reg(par, 0x2b, ys >> 8, ys & 0xff, ye >> 8, ye & 0xff);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ ys >> 8, ys & 0xff, ye >> 8, ye & 0xff);
- /* memory write */
- write_reg(par, 0x2c);
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}
#define HFLIP 0x01
{
switch (par->info->var.rotate) {
case 270:
- write_reg(par, 0x36, ROWxCOL | HFLIP | VFLIP | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ ROWxCOL | HFLIP | VFLIP | (par->bgr << 3));
break;
case 180:
- write_reg(par, 0x36, VFLIP | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ VFLIP | (par->bgr << 3));
break;
case 90:
- write_reg(par, 0x36, ROWxCOL | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ ROWxCOL | (par->bgr << 3));
break;
default:
- write_reg(par, 0x36, HFLIP | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ HFLIP | (par->bgr << 3));
break;
}
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
static int default_init_sequence[] = {
/* Interface Mode Control */
-1, 0xb0, 0x0,
- /* Sleep OUT */
- -1, 0x11,
+ -1, MIPI_DCS_EXIT_SLEEP_MODE,
-2, 250,
/* Interface Pixel Format */
- -1, 0x3A, 0x55,
+ -1, MIPI_DCS_SET_PIXEL_FORMAT, 0x55,
/* Power Control 3 */
-1, 0xC2, 0x44,
/* VCOM Control 1 */
/* 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,
+ -1, MIPI_DCS_EXIT_SLEEP_MODE,
+ -1, MIPI_DCS_SET_DISPLAY_ON,
/* end marker */
-3
};
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
- /* Column address */
- write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
- /* Row address */
- write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
- /* Memory write */
- write_reg(par, 0x2C);
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}
static int set_var(struct fbtft_par *par)
{
switch (par->info->var.rotate) {
case 0:
- write_reg(par, 0x36, 0x80 | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ 0x80 | (par->bgr << 3));
break;
case 90:
- write_reg(par, 0x36, 0x20 | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ 0x20 | (par->bgr << 3));
break;
case 180:
- write_reg(par, 0x36, 0x40 | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ 0x40 | (par->bgr << 3));
break;
case 270:
- write_reg(par, 0x36, 0xE0 | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ 0xE0 | (par->bgr << 3));
break;
default:
break;
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
-1, 0xf3, 0x00, 0x00,
- -1, 0x11,
+ -1, MIPI_DCS_EXIT_SLEEP_MODE,
-2, 50,
-1, 0xf3, 0x00, 0x01,
/* initializing sequence */
- -1, 0x36, 0x08,
+ -1, MIPI_DCS_SET_ADDRESS_MODE, 0x08,
- -1, 0x35, 0x00,
+ -1, MIPI_DCS_SET_TEAR_ON, 0x00,
- -1, 0x3a, 0x05,
+ -1, MIPI_DCS_SET_PIXEL_FORMAT, 0x05,
- /* gamma setting sequence */
- -1, 0x26, 0x01, /* preset gamma curves, possible values 0x01, 0x02, 0x04, 0x08 */
+ /* gamma setting - possible values 0x01, 0x02, 0x04, 0x08 */
+ -1, MIPI_DCS_SET_GAMMA_CURVE, 0x01,
-2, 150,
- -1, 0x29,
- -1, 0x2c,
+ -1, MIPI_DCS_SET_DISPLAY_ON,
+ -1, MIPI_DCS_WRITE_MEMORY_START,
/* end marker */
-3
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
- /* Column address */
- write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
- /* Row address */
- write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
- /* Memory write */
- write_reg(par, 0x2C);
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}
#define MY BIT(7)
#define MV BIT(5)
static int set_var(struct fbtft_par *par)
{
- /* MADCTL - Memory data access control
+ /* Memory data access control (0x36h)
RGB/BGR:
1. Mode selection pin SRGB
RGB H/W pin for color filter setting: 0=RGB, 1=BGR
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));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MX | MY | (par->bgr << 3));
break;
case 270:
- write_reg(par, 0x36, MY | MV | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MY | MV | (par->bgr << 3));
break;
case 180:
- write_reg(par, 0x36, par->bgr << 3);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ par->bgr << 3);
break;
case 90:
- write_reg(par, 0x36, MX | MV | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MX | MV | (par->bgr << 3));
break;
}
--- /dev/null
+/*
+ * FB driver for the SSD1305 OLED Controller
+ *
+ * based on SSD1306 driver 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include "fbtft.h"
+
+#define DRVNAME "fb_ssd1305"
+
+#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)
+{
+ 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 | ((par->info->var.rotate == 180) ? 0x0 : 0x1));
+
+ /*
+ * Set COM Output Scan Direction
+ * remapped mode. Scan from COM[N-1] to COM0
+ */
+ write_reg(par, ((par->info->var.rotate == 180) ? 0xC8 : 0xC0));
+
+ /* 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);
+
+ /*
+ * 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)
+{
+ /* Set Lower Column Start Address for Page Addressing Mode */
+ write_reg(par, 0x00 | ((par->info->var.rotate == 180) ? 0x0 : 0x4));
+ /* 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)
+{
+ 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)
+{
+ 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_buffer;
+ u8 *buf = par->txbuf.buf;
+ int x, y, i;
+ int ret;
+
+ 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, "write failed and returned: %d\n",
+ ret);
+ return ret;
+}
+
+static struct fbtft_display display = {
+ .regwidth = 8,
+ .width = WIDTH,
+ .height = HEIGHT,
+ .txbuflen = WIDTH * HEIGHT / 8,
+ .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,ssd1305", &display);
+
+MODULE_ALIAS("spi:" DRVNAME);
+MODULE_ALIAS("platform:" DRVNAME);
+MODULE_ALIAS("spi:ssd1305");
+MODULE_ALIAS("platform:ssd1305");
+
+MODULE_DESCRIPTION("SSD1305 OLED Driver");
+MODULE_AUTHOR("Alexey Mednyy");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * FB driver for the SSD1325 OLED Controller
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+
+#include "fbtft.h"
+
+#define DRVNAME "fb_ssd1325"
+
+#define WIDTH 128
+#define HEIGHT 64
+#define GAMMA_NUM 1
+#define GAMMA_LEN 15
+#define DEFAULT_GAMMA "7 1 1 1 1 2 2 3 3 4 4 5 5 6 6"
+
+/*
+ * 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)
+{
+ par->fbtftops.reset(par);
+
+ gpio_set_value(par->gpio.cs, 0);
+
+ write_reg(par, 0xb3);
+ write_reg(par, 0xf0);
+ write_reg(par, 0xae);
+ write_reg(par, 0xa1);
+ write_reg(par, 0x00);
+ write_reg(par, 0xa8);
+ write_reg(par, 0x3f);
+ write_reg(par, 0xa0);
+ write_reg(par, 0x45);
+ write_reg(par, 0xa2);
+ write_reg(par, 0x40);
+ write_reg(par, 0x75);
+ write_reg(par, 0x00);
+ write_reg(par, 0x3f);
+ write_reg(par, 0x15);
+ write_reg(par, 0x00);
+ write_reg(par, 0x7f);
+ write_reg(par, 0xa4);
+ write_reg(par, 0xaf);
+
+ return 0;
+}
+
+static uint8_t rgb565_to_g16(u16 pixel)
+{
+ 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) / 195;
+ if (pixel > 255)
+ pixel = 255;
+ return (uint8_t)pixel / 16;
+}
+
+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, 0x75);
+ write_reg(par, 0x00);
+ write_reg(par, 0x3f);
+ write_reg(par, 0x15);
+ write_reg(par, 0x00);
+ write_reg(par, 0x7f);
+}
+
+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;
+}
+
+/*
+ * Grayscale Lookup Table
+ * GS1 - GS15
+ * The "Gamma curve" contains the relative values between the entries
+ * in the Lookup table.
+ *
+ * 0 = Setting of GS1 < Setting of GS2 < Setting of GS3.....<
+ * Setting of GS14 < Setting of GS15
+ */
+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 < GAMMA_LEN; i++) {
+ if (i > 0 && curves[i] < 1) {
+ dev_err(par->info->device,
+ "Illegal value in Grayscale Lookup Table at index %d.\n"
+ "Must be greater than 0\n", i);
+ return -EINVAL;
+ }
+ if (curves[i] > 7) {
+ dev_err(par->info->device,
+ "Illegal value(s) in Grayscale Lookup Table.\n"
+ "At index=%d, the accumulated value has exceeded 7\n",
+ i);
+ return -EINVAL;
+ }
+ }
+ write_reg(par, 0xB8);
+ for (i = 0; i < 8; i++)
+ write_reg(par, (curves[i] & 0xFF));
+ return 0;
+}
+
+static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
+{
+ u16 *vmem16 = (u16 *)par->info->screen_buffer;
+ u8 *buf = par->txbuf.buf;
+ u8 n1;
+ u8 n2;
+ int y, x;
+ int ret;
+
+ for (x = 0; x < par->info->var.xres; x++) {
+ if (x % 2)
+ continue;
+ for (y = 0; y < par->info->var.yres; y++) {
+ n1 = rgb565_to_g16(vmem16[y * par->info->var.xres + x]);
+ n2 = rgb565_to_g16(vmem16
+ [y * par->info->var.xres + x + 1]);
+ *buf = (n1 << 4) | n2;
+ buf++;
+ }
+ }
+
+ gpio_set_value(par->gpio.dc, 1);
+
+ /* Write data */
+ ret = par->fbtftops.write(par, par->txbuf.buf,
+ par->info->var.xres * par->info->var.yres / 2);
+ 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,
+ .txbuflen = WIDTH * HEIGHT / 2,
+ .gamma_num = GAMMA_NUM,
+ .gamma_len = GAMMA_LEN,
+ .gamma = DEFAULT_GAMMA,
+ .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,ssd1325", &display);
+
+MODULE_ALIAS("spi:" DRVNAME);
+MODULE_ALIAS("platform:" DRVNAME);
+MODULE_ALIAS("spi:ssd1325");
+MODULE_ALIAS("platform:ssd1325");
+
+MODULE_DESCRIPTION("SSD1325 OLED Driver");
+MODULE_AUTHOR("Alexey Mednyy");
+MODULE_LICENSE("GPL");
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
"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,
+ -1, MIPI_DCS_SOFT_RESET,
-2, 150, /* delay */
- /* SLPOUT - Sleep out & booster on */
- -1, 0x11,
+ -1, MIPI_DCS_EXIT_SLEEP_MODE,
-2, 500, /* delay */
/* FRMCTR1 - frame rate control: normal mode
/* VMCTR1 - Power Control */
-1, 0xC5, 0x0E,
- /* INVOFF - Display inversion off */
- -1, 0x20,
+ -1, MIPI_DCS_EXIT_INVERT_MODE,
- /* COLMOD - Interface pixel format */
- -1, 0x3A, 0x05,
+ -1, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT,
- /* DISPON - Display On */
- -1, 0x29,
+ -1, MIPI_DCS_SET_DISPLAY_ON,
-2, 100, /* delay */
- /* NORON - Partial off (Normal) */
- -1, 0x13,
+ -1, MIPI_DCS_ENTER_NORMAL_MODE,
-2, 10, /* delay */
/* end marker */
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
- /* Column address */
- write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
- /* Row address */
- write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
- /* Memory write */
- write_reg(par, 0x2C);
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}
#define MY BIT(7)
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));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MX | MY | (par->bgr << 3));
break;
case 270:
- write_reg(par, 0x36, MY | MV | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MY | MV | (par->bgr << 3));
break;
case 180:
- write_reg(par, 0x36, par->bgr << 3);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ par->bgr << 3);
break;
case 90:
- write_reg(par, 0x36, MX | MV | (par->bgr << 3));
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE,
+ MX | MV | (par->bgr << 3));
break;
}
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
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, MIPI_DCS_SET_ADDRESS_MODE, 0x58);
write_reg(par, 0xF0, 0x36, 0xA5, 0xD3);
write_reg(par, 0xE5, 0x80);
write_reg(par, 0xE5, 0x01);
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);
+ write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
+ write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
udelay(250);
- write_reg(par, 0x29);
+ write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
return 0;
}
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
- /* Column address */
- write_reg(par, 0x2A, xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
- /* Row address */
- write_reg(par, 0x2B, ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
- /* Memory write */
- write_reg(par, 0x2C);
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}
static int set_var(struct fbtft_par *par)
switch (par->info->var.rotate) {
case 270:
write_reg(par, 0xB6, 0x00, 0x02, 0x3B);
- write_reg(par, 0x36, 0x28);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, 0x28);
break;
case 180:
write_reg(par, 0xB6, 0x00, 0x22, 0x3B);
- write_reg(par, 0x36, 0x58);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, 0x58);
break;
case 90:
write_reg(par, 0xB6, 0x00, 0x22, 0x3B);
- write_reg(par, 0x36, 0x38);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, 0x38);
break;
default:
write_reg(par, 0xB6, 0x00, 0x22, 0x3B);
- write_reg(par, 0x36, 0x08);
+ write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, 0x08);
break;
}
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);
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 */
static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
/* goto address */
- /* LCD_PAGE_ADDRESS | ((page) & 0x1F),
- (((col)+SHIFT_ADDR_NORMAL) & 0x0F),
- LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */
write_reg(par, LCD_PAGE_ADDRESS);
- /* LCD_PAGE_ADDRESS | ((page) & 0x1F),
- (((col)+SHIFT_ADDR_NORMAL) & 0x0F),
- LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */
write_reg(par, 0x00);
- /* LCD_PAGE_ADDRESS | ((page) & 0x1F),
- (((col)+SHIFT_ADDR_NORMAL) & 0x0F),
- LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */
write_reg(par, LCD_COL_ADDRESS);
}
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);
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
+#include <video/mipi_display.h>
#include "fbtft.h"
#include "internal.h"
static void fbtft_set_addr_win(struct fbtft_par *par, int xs, int ys, int xe,
int ye)
{
- /* Column address set */
- write_reg(par, 0x2A,
- (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF);
+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
+ (xs >> 8) & 0xFF, xs & 0xFF, (xe >> 8) & 0xFF, xe & 0xFF);
- /* Row address set */
- write_reg(par, 0x2B,
- (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF);
+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
+ (ys >> 8) & 0xFF, ys & 0xFF, (ye >> 8) & 0xFF, ye & 0xFF);
- /* Memory write */
- write_reg(par, 0x2C);
+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
}
static void fbtft_reset(struct fbtft_par *par)
par->fbtftops.unregister_backlight(par);
if (spi)
spi_set_drvdata(spi, NULL);
- if (par->pdev)
- platform_set_drvdata(par->pdev, NULL);
return 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);
#include <linux/spi/spi.h>
#include <linux/platform_device.h>
-#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
"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, MIPI_DCS_SOFT_RESET,
+ -2, 5,
+ -1, MIPI_DCS_SET_DISPLAY_OFF,
+ -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 };
+ -1, 0xF7, 0x20,
+ -1, 0xEA, 0x00, 0x00,
+ -1, 0xC0, 0x23,
+ -1, 0xC1, 0x10,
+ -1, 0xC5, 0x3E, 0x28,
+ -1, 0xC7, 0x86,
+ -1, MIPI_DCS_SET_PIXEL_FORMAT, 0x55,
+ -1, 0xB1, 0x00, 0x18,
+ -1, 0xB6, 0x08, 0x82, 0x27,
+ -1, 0xF2, 0x00,
+ -1, MIPI_DCS_SET_GAMMA_CURVE, 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, MIPI_DCS_EXIT_SLEEP_MODE,
+ -2, 100,
+ -1, MIPI_DCS_SET_DISPLAY_ON,
+ -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, 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, MIPI_DCS_SET_ADDRESS_MODE, 0x28,
+ -1, MIPI_DCS_SET_PIXEL_FORMAT, 0x55,
+ -1, 0xB1, 0x00, 0x18,
+ -1, 0xB6, 0x08, 0x82, 0x27,
+ -1, 0xF2, 0x00,
+ -1, MIPI_DCS_SET_GAMMA_CURVE, 0x01,
-1, 0xE0, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E,
- 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
+ 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 };
+ 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
+ -1, MIPI_DCS_EXIT_SLEEP_MODE,
+ -2, 120,
+ -1, MIPI_DCS_SET_DISPLAY_ON,
+ -1, MIPI_DCS_WRITE_MEMORY_START,
+ -3
+};
/* Supported displays in alphabetical order */
static struct fbtft_device_display displays[] = {
static int spi_device_found(struct device *dev, void *data)
{
- struct spi_device *spi = container_of(dev, struct spi_device, dev);
+ struct spi_device *spi = to_spi_device(dev);
dev_info(dev, "%s %s %dkHz %d bits mode=0x%02X\n", spi->modalias,
dev_name(dev), spi->max_speed_hz / 1000, spi->bits_per_word,
static int p_device_found(struct device *dev, void *data)
{
struct platform_device
- *pdev = container_of(dev, struct platform_device, dev);
+ *pdev = to_platform_device(dev);
if (strstr(pdev->name, "fb"))
dev_info(dev, "%s id=%d pdata? %s\n", pdev->name, pdev->id,
config FSL_MC_BUS
tristate "Freescale Management Complex (MC) bus driver"
depends on OF && ARM64
+ select GENERIC_MSI_IRQ_DOMAIN
help
Driver to enable the bus infrastructure for the Freescale
QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware
dpmng.o \
dprc-driver.o \
mc-allocator.o \
+ mc-msi.o \
+ irq-gic-v3-its-fsl-mc-msi.o \
dpmcp.o \
dpbp.o
#include "../include/mc-sys.h"
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/msi.h>
#include "dprc-cmd.h"
struct dprc_child_objs {
* dprc_scan_objects - Discover objects in a DPRC
*
* @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
+ * @total_irq_count: total number of IRQs needed by objects in the DPRC.
*
* Detects objects added and removed from a DPRC and synchronizes the
* state of the Linux bus driver, MC by adding and removing
* populated before they can get allocation requests from probe callbacks
* of the device drivers for the non-allocatable devices.
*/
-int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
+int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
+ unsigned int *total_irq_count)
{
int num_child_objects;
int dprc_get_obj_failures;
int error;
+ unsigned int irq_count = mc_bus_dev->obj_desc.irq_count;
struct dprc_obj_desc *child_obj_desc_array = NULL;
error = dprc_get_obj_count(mc_bus_dev->mc_io,
continue;
}
+ irq_count += obj_desc->irq_count;
dev_dbg(&mc_bus_dev->dev,
"Discovered object: type %s, id %d\n",
obj_desc->type, obj_desc->id);
}
}
+ *total_irq_count = irq_count;
dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
num_child_objects);
int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
{
int error;
+ unsigned int irq_count;
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
dprc_init_all_resource_pools(mc_bus_dev);
* Discover objects in the DPRC:
*/
mutex_lock(&mc_bus->scan_mutex);
- error = dprc_scan_objects(mc_bus_dev);
+ error = dprc_scan_objects(mc_bus_dev, &irq_count);
mutex_unlock(&mc_bus->scan_mutex);
if (error < 0)
goto error;
+ if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) {
+ if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
+ dev_warn(&mc_bus_dev->dev,
+ "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
+ irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
+ }
+
+ error = fsl_mc_populate_irq_pool(
+ mc_bus,
+ FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
+ if (error < 0)
+ goto error;
+ }
+
return 0;
error:
dprc_cleanup_all_resource_pools(mc_bus_dev);
}
EXPORT_SYMBOL_GPL(dprc_scan_container);
+/**
+ * dprc_irq0_handler - Regular ISR for DPRC interrupt 0
+ *
+ * @irq: IRQ number of the interrupt being handled
+ * @arg: Pointer to device structure
+ */
+static irqreturn_t dprc_irq0_handler(int irq_num, void *arg)
+{
+ return IRQ_WAKE_THREAD;
+}
+
+/**
+ * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0
+ *
+ * @irq: IRQ number of the interrupt being handled
+ * @arg: Pointer to device structure
+ */
+static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg)
+{
+ int error;
+ u32 status;
+ struct device *dev = (struct device *)arg;
+ struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
+ struct fsl_mc_io *mc_io = mc_dev->mc_io;
+ struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc;
+
+ dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
+ irq_num, smp_processor_id());
+
+ if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC)))
+ return IRQ_HANDLED;
+
+ mutex_lock(&mc_bus->scan_mutex);
+ if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num))
+ goto out;
+
+ error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
+ &status);
+ if (error < 0) {
+ dev_err(dev,
+ "dprc_get_irq_status() failed: %d\n", error);
+ goto out;
+ }
+
+ error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0,
+ status);
+ if (error < 0) {
+ dev_err(dev,
+ "dprc_clear_irq_status() failed: %d\n", error);
+ goto out;
+ }
+
+ if (status & (DPRC_IRQ_EVENT_OBJ_ADDED |
+ DPRC_IRQ_EVENT_OBJ_REMOVED |
+ DPRC_IRQ_EVENT_CONTAINER_DESTROYED |
+ DPRC_IRQ_EVENT_OBJ_DESTROYED |
+ DPRC_IRQ_EVENT_OBJ_CREATED)) {
+ unsigned int irq_count;
+
+ error = dprc_scan_objects(mc_dev, &irq_count);
+ if (error < 0) {
+ /*
+ * If the error is -ENXIO, we ignore it, as it indicates
+ * that the object scan was aborted, as we detected that
+ * an object was removed from the DPRC in the MC, while
+ * we were scanning the DPRC.
+ */
+ if (error != -ENXIO) {
+ dev_err(dev, "dprc_scan_objects() failed: %d\n",
+ error);
+ }
+
+ goto out;
+ }
+
+ if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) {
+ dev_warn(dev,
+ "IRQs needed (%u) exceed IRQs preallocated (%u)\n",
+ irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS);
+ }
+ }
+
+out:
+ mutex_unlock(&mc_bus->scan_mutex);
+ return IRQ_HANDLED;
+}
+
+/*
+ * Disable and clear interrupt for a given DPRC object
+ */
+static int disable_dprc_irq(struct fsl_mc_device *mc_dev)
+{
+ int error;
+ struct fsl_mc_io *mc_io = mc_dev->mc_io;
+
+ WARN_ON(mc_dev->obj_desc.irq_count != 1);
+
+ /*
+ * Disable generation of interrupt, while we configure it:
+ */
+ error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0);
+ if (error < 0) {
+ dev_err(&mc_dev->dev,
+ "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
+ error);
+ return error;
+ }
+
+ /*
+ * Disable all interrupt causes for the interrupt:
+ */
+ error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0);
+ if (error < 0) {
+ dev_err(&mc_dev->dev,
+ "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
+ error);
+ return error;
+ }
+
+ /*
+ * Clear any leftover interrupts:
+ */
+ error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U);
+ if (error < 0) {
+ dev_err(&mc_dev->dev,
+ "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n",
+ error);
+ return error;
+ }
+
+ return 0;
+}
+
+static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev)
+{
+ int error;
+ struct fsl_mc_device_irq *irq = mc_dev->irqs[0];
+
+ WARN_ON(mc_dev->obj_desc.irq_count != 1);
+
+ /*
+ * NOTE: devm_request_threaded_irq() invokes the device-specific
+ * function that programs the MSI physically in the device
+ */
+ error = devm_request_threaded_irq(&mc_dev->dev,
+ irq->msi_desc->irq,
+ dprc_irq0_handler,
+ dprc_irq0_handler_thread,
+ IRQF_NO_SUSPEND | IRQF_ONESHOT,
+ "FSL MC DPRC irq0",
+ &mc_dev->dev);
+ if (error < 0) {
+ dev_err(&mc_dev->dev,
+ "devm_request_threaded_irq() failed: %d\n",
+ error);
+ return error;
+ }
+
+ return 0;
+}
+
+static int enable_dprc_irq(struct fsl_mc_device *mc_dev)
+{
+ int error;
+
+ /*
+ * Enable all interrupt causes for the interrupt:
+ */
+ error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0,
+ ~0x0u);
+ if (error < 0) {
+ dev_err(&mc_dev->dev,
+ "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n",
+ error);
+
+ return error;
+ }
+
+ /*
+ * Enable generation of the interrupt:
+ */
+ error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1);
+ if (error < 0) {
+ dev_err(&mc_dev->dev,
+ "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n",
+ error);
+
+ return error;
+ }
+
+ return 0;
+}
+
+/*
+ * Setup interrupt for a given DPRC device
+ */
+static int dprc_setup_irq(struct fsl_mc_device *mc_dev)
+{
+ int error;
+
+ error = fsl_mc_allocate_irqs(mc_dev);
+ if (error < 0)
+ return error;
+
+ error = disable_dprc_irq(mc_dev);
+ if (error < 0)
+ goto error_free_irqs;
+
+ error = register_dprc_irq_handler(mc_dev);
+ if (error < 0)
+ goto error_free_irqs;
+
+ error = enable_dprc_irq(mc_dev);
+ if (error < 0)
+ goto error_free_irqs;
+
+ return 0;
+
+error_free_irqs:
+ fsl_mc_free_irqs(mc_dev);
+ return error;
+}
+
/**
* dprc_probe - callback invoked when a DPRC is being bound to this driver
*
{
int error;
size_t region_size;
+ struct device *parent_dev = mc_dev->dev.parent;
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
+ bool mc_io_created = false;
+ bool msi_domain_set = false;
if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
return -EINVAL;
+ if (WARN_ON(dev_get_msi_domain(&mc_dev->dev)))
+ return -EINVAL;
+
if (!mc_dev->mc_io) {
/*
* This is a child DPRC:
*/
+ if (WARN_ON(parent_dev->bus != &fsl_mc_bus_type))
+ return -EINVAL;
+
if (WARN_ON(mc_dev->obj_desc.region_count == 0))
return -EINVAL;
error = fsl_create_mc_io(&mc_dev->dev,
mc_dev->regions[0].start,
region_size,
- NULL, 0, &mc_dev->mc_io);
+ NULL,
+ FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
+ &mc_dev->mc_io);
if (error < 0)
return error;
+
+ mc_io_created = true;
+
+ /*
+ * Inherit parent MSI domain:
+ */
+ dev_set_msi_domain(&mc_dev->dev,
+ dev_get_msi_domain(parent_dev));
+ msi_domain_set = true;
+ } else {
+ /*
+ * This is a root DPRC
+ */
+ struct irq_domain *mc_msi_domain;
+
+ if (WARN_ON(parent_dev->bus == &fsl_mc_bus_type))
+ return -EINVAL;
+
+ error = fsl_mc_find_msi_domain(parent_dev,
+ &mc_msi_domain);
+ if (error < 0) {
+ dev_warn(&mc_dev->dev,
+ "WARNING: MC bus without interrupt support\n");
+ } else {
+ dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
+ msi_domain_set = true;
+ }
}
error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
&mc_dev->mc_handle);
if (error < 0) {
dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
- goto error_cleanup_mc_io;
+ goto error_cleanup_msi_domain;
}
mutex_init(&mc_bus->scan_mutex);
if (error < 0)
goto error_cleanup_open;
+ /*
+ * Configure interrupt for the DPRC object associated with this MC bus:
+ */
+ error = dprc_setup_irq(mc_dev);
+ if (error < 0)
+ goto error_cleanup_open;
+
dev_info(&mc_dev->dev, "DPRC device bound to driver");
return 0;
error_cleanup_open:
(void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
-error_cleanup_mc_io:
- fsl_destroy_mc_io(mc_dev->mc_io);
+error_cleanup_msi_domain:
+ if (msi_domain_set)
+ dev_set_msi_domain(&mc_dev->dev, NULL);
+
+ if (mc_io_created) {
+ fsl_destroy_mc_io(mc_dev->mc_io);
+ mc_dev->mc_io = NULL;
+ }
+
return error;
}
+/*
+ * Tear down interrupt for a given DPRC object
+ */
+static void dprc_teardown_irq(struct fsl_mc_device *mc_dev)
+{
+ (void)disable_dprc_irq(mc_dev);
+ fsl_mc_free_irqs(mc_dev);
+}
+
/**
* dprc_remove - callback invoked when a DPRC is being unbound from this driver
*
static int dprc_remove(struct fsl_mc_device *mc_dev)
{
int error;
+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0))
return -EINVAL;
if (WARN_ON(!mc_dev->mc_io))
return -EINVAL;
+ if (WARN_ON(!mc_bus->irq_resources))
+ return -EINVAL;
+
+ if (dev_get_msi_domain(&mc_dev->dev))
+ dprc_teardown_irq(mc_dev);
+
device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
dprc_cleanup_all_resource_pools(mc_dev);
error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
if (error < 0)
dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
+ if (dev_get_msi_domain(&mc_dev->dev)) {
+ fsl_mc_cleanup_irq_pool(mc_bus);
+ dev_set_msi_domain(&mc_dev->dev, NULL);
+ }
+
dev_info(&mc_dev->dev, "DPRC device unbound from driver");
return 0;
}
--- /dev/null
+/*
+ * Freescale Management Complex (MC) bus driver MSI support
+ *
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Author: German Rivera <German.Rivera@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include "../include/mc-private.h"
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/irqchip/arm-gic-v3.h>
+#include <linux/irq.h>
+#include <linux/msi.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include "../include/mc-sys.h"
+#include "dprc-cmd.h"
+
+static struct irq_chip its_msi_irq_chip = {
+ .name = "fsl-mc-bus-msi",
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_set_affinity = msi_domain_set_affinity
+};
+
+static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain,
+ struct device *dev,
+ int nvec, msi_alloc_info_t *info)
+{
+ struct fsl_mc_device *mc_bus_dev;
+ struct msi_domain_info *msi_info;
+
+ if (WARN_ON(dev->bus != &fsl_mc_bus_type))
+ return -EINVAL;
+
+ mc_bus_dev = to_fsl_mc_device(dev);
+ if (WARN_ON(!(mc_bus_dev->flags & FSL_MC_IS_DPRC)))
+ return -EINVAL;
+
+ /*
+ * Set the device Id to be passed to the GIC-ITS:
+ *
+ * NOTE: This device id corresponds to the IOMMU stream ID
+ * associated with the DPRC object (ICID).
+ */
+ info->scratchpad[0].ul = mc_bus_dev->icid;
+ msi_info = msi_get_domain_info(msi_domain->parent);
+ return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info);
+}
+
+static struct msi_domain_ops its_fsl_mc_msi_ops = {
+ .msi_prepare = its_fsl_mc_msi_prepare,
+};
+
+static struct msi_domain_info its_fsl_mc_msi_domain_info = {
+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
+ .ops = &its_fsl_mc_msi_ops,
+ .chip = &its_msi_irq_chip,
+};
+
+static const struct of_device_id its_device_id[] = {
+ { .compatible = "arm,gic-v3-its", },
+ {},
+};
+
+int __init its_fsl_mc_msi_init(void)
+{
+ struct device_node *np;
+ struct irq_domain *parent;
+ struct irq_domain *mc_msi_domain;
+
+ for (np = of_find_matching_node(NULL, its_device_id); np;
+ np = of_find_matching_node(np, its_device_id)) {
+ if (!of_property_read_bool(np, "msi-controller"))
+ continue;
+
+ parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS);
+ if (!parent || !msi_get_domain_info(parent)) {
+ pr_err("%s: unable to locate ITS domain\n",
+ np->full_name);
+ continue;
+ }
+
+ mc_msi_domain = fsl_mc_msi_create_irq_domain(
+ of_node_to_fwnode(np),
+ &its_fsl_mc_msi_domain_info,
+ parent);
+ if (!mc_msi_domain) {
+ pr_err("%s: unable to create fsl-mc domain\n",
+ np->full_name);
+ continue;
+ }
+
+ WARN_ON(mc_msi_domain->
+ host_data != &its_fsl_mc_msi_domain_info);
+
+ pr_info("fsl-mc MSI: %s domain created\n", np->full_name);
+ }
+
+ return 0;
+}
+
+void its_fsl_mc_msi_cleanup(void)
+{
+ struct device_node *np;
+
+ for (np = of_find_matching_node(NULL, its_device_id); np;
+ np = of_find_matching_node(np, its_device_id)) {
+ struct irq_domain *mc_msi_domain = irq_find_matching_host(
+ np,
+ DOMAIN_BUS_FSL_MC_MSI);
+
+ if (!of_property_read_bool(np, "msi-controller"))
+ continue;
+
+ mc_msi_domain = irq_find_matching_host(np,
+ DOMAIN_BUS_FSL_MC_MSI);
+ if (mc_msi_domain &&
+ mc_msi_domain->host_data == &its_fsl_mc_msi_domain_info)
+ irq_domain_remove(mc_msi_domain);
+ }
+}
#include "../include/dpcon-cmd.h"
#include "dpmcp-cmd.h"
#include "dpmcp.h"
+#include <linux/msi.h>
/**
* fsl_mc_resource_pool_add_device - add allocatable device to a resource
[FSL_MC_POOL_DPMCP] = "dpmcp",
[FSL_MC_POOL_DPBP] = "dpbp",
[FSL_MC_POOL_DPCON] = "dpcon",
+ [FSL_MC_POOL_IRQ] = "irq",
};
static int __must_check object_type_to_pool_type(const char *object_type,
}
EXPORT_SYMBOL_GPL(fsl_mc_object_free);
+/*
+ * Initialize the interrupt pool associated with a MC bus.
+ * It allocates a block of IRQs from the GIC-ITS
+ */
+int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
+ unsigned int irq_count)
+{
+ unsigned int i;
+ struct msi_desc *msi_desc;
+ struct fsl_mc_device_irq *irq_resources;
+ struct fsl_mc_device_irq *mc_dev_irq;
+ int error;
+ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
+ struct fsl_mc_resource_pool *res_pool =
+ &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
+
+ if (WARN_ON(irq_count == 0 ||
+ irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS))
+ return -EINVAL;
+
+ error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
+ if (error < 0)
+ return error;
+
+ irq_resources = devm_kzalloc(&mc_bus_dev->dev,
+ sizeof(*irq_resources) * irq_count,
+ GFP_KERNEL);
+ if (!irq_resources) {
+ error = -ENOMEM;
+ goto cleanup_msi_irqs;
+ }
+
+ for (i = 0; i < irq_count; i++) {
+ mc_dev_irq = &irq_resources[i];
+
+ /*
+ * NOTE: This mc_dev_irq's MSI addr/value pair will be set
+ * by the fsl_mc_msi_write_msg() callback
+ */
+ mc_dev_irq->resource.type = res_pool->type;
+ mc_dev_irq->resource.data = mc_dev_irq;
+ mc_dev_irq->resource.parent_pool = res_pool;
+ INIT_LIST_HEAD(&mc_dev_irq->resource.node);
+ list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
+ }
+
+ for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
+ mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
+ mc_dev_irq->msi_desc = msi_desc;
+ mc_dev_irq->resource.id = msi_desc->irq;
+ }
+
+ res_pool->max_count = irq_count;
+ res_pool->free_count = irq_count;
+ mc_bus->irq_resources = irq_resources;
+ return 0;
+
+cleanup_msi_irqs:
+ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
+ return error;
+}
+EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
+
+/**
+ * Teardown the interrupt pool associated with an MC bus.
+ * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
+ */
+void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
+{
+ struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
+ struct fsl_mc_resource_pool *res_pool =
+ &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
+
+ if (WARN_ON(!mc_bus->irq_resources))
+ return;
+
+ if (WARN_ON(res_pool->max_count == 0))
+ return;
+
+ if (WARN_ON(res_pool->free_count != res_pool->max_count))
+ return;
+
+ INIT_LIST_HEAD(&res_pool->free_list);
+ res_pool->max_count = 0;
+ res_pool->free_count = 0;
+ mc_bus->irq_resources = NULL;
+ fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
+}
+EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
+
+/**
+ * It allocates the IRQs required by a given MC object device. The
+ * IRQs are allocated from the interrupt pool associated with the
+ * MC bus that contains the device, if the device is not a DPRC device.
+ * Otherwise, the IRQs are allocated from the interrupt pool associated
+ * with the MC bus that represents the DPRC device itself.
+ */
+int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
+{
+ int i;
+ int irq_count;
+ int res_allocated_count = 0;
+ int error = -EINVAL;
+ struct fsl_mc_device_irq **irqs = NULL;
+ struct fsl_mc_bus *mc_bus;
+ struct fsl_mc_resource_pool *res_pool;
+
+ if (WARN_ON(mc_dev->irqs))
+ return -EINVAL;
+
+ irq_count = mc_dev->obj_desc.irq_count;
+ if (WARN_ON(irq_count == 0))
+ return -EINVAL;
+
+ if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
+ mc_bus = to_fsl_mc_bus(mc_dev);
+ else
+ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
+
+ if (WARN_ON(!mc_bus->irq_resources))
+ return -EINVAL;
+
+ res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
+ if (res_pool->free_count < irq_count) {
+ dev_err(&mc_dev->dev,
+ "Not able to allocate %u irqs for device\n", irq_count);
+ return -ENOSPC;
+ }
+
+ irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
+ GFP_KERNEL);
+ if (!irqs)
+ return -ENOMEM;
+
+ for (i = 0; i < irq_count; i++) {
+ struct fsl_mc_resource *resource;
+
+ error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
+ &resource);
+ if (error < 0)
+ goto error_resource_alloc;
+
+ irqs[i] = to_fsl_mc_irq(resource);
+ res_allocated_count++;
+
+ WARN_ON(irqs[i]->mc_dev);
+ irqs[i]->mc_dev = mc_dev;
+ irqs[i]->dev_irq_index = i;
+ }
+
+ mc_dev->irqs = irqs;
+ return 0;
+
+error_resource_alloc:
+ for (i = 0; i < res_allocated_count; i++) {
+ irqs[i]->mc_dev = NULL;
+ fsl_mc_resource_free(&irqs[i]->resource);
+ }
+
+ return error;
+}
+EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
+
+/*
+ * It frees the IRQs that were allocated for a MC object device, by
+ * returning them to the corresponding interrupt pool.
+ */
+void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
+{
+ int i;
+ int irq_count;
+ struct fsl_mc_bus *mc_bus;
+ struct fsl_mc_device_irq **irqs = mc_dev->irqs;
+
+ if (WARN_ON(!irqs))
+ return;
+
+ irq_count = mc_dev->obj_desc.irq_count;
+
+ if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
+ mc_bus = to_fsl_mc_bus(mc_dev);
+ else
+ mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
+
+ if (WARN_ON(!mc_bus->irq_resources))
+ return;
+
+ for (i = 0; i < irq_count; i++) {
+ WARN_ON(!irqs[i]->mc_dev);
+ irqs[i]->mc_dev = NULL;
+ fsl_mc_resource_free(&irqs[i]->resource);
+ }
+
+ mc_dev->irqs = NULL;
+}
+EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
+
/**
* fsl_mc_allocator_probe - callback invoked when an allocatable device is
* being added to the system
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/limits.h>
+#include <linux/bitops.h>
+#include <linux/msi.h>
#include "../include/dpmng.h"
#include "../include/mc-sys.h"
#include "dprc-cmd.h"
mc_dev->icid = parent_mc_dev->icid;
mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
mc_dev->dev.dma_mask = &mc_dev->dma_mask;
+ dev_set_msi_domain(&mc_dev->dev,
+ dev_get_msi_domain(&parent_mc_dev->dev));
}
/*
mc_portal_phys_addr = res.start;
mc_portal_size = resource_size(&res);
error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
- mc_portal_size, NULL, 0, &mc_io);
+ mc_portal_size, NULL,
+ FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);
if (error < 0)
return error;
if (error < 0)
goto error_cleanup_dprc_driver;
+ error = its_fsl_mc_msi_init();
+ if (error < 0)
+ goto error_cleanup_mc_allocator;
+
return 0;
+error_cleanup_mc_allocator:
+ fsl_mc_allocator_driver_exit();
+
error_cleanup_dprc_driver:
dprc_driver_exit();
if (WARN_ON(!mc_dev_cache))
return;
+ its_fsl_mc_msi_cleanup();
fsl_mc_allocator_driver_exit();
dprc_driver_exit();
platform_driver_unregister(&fsl_mc_bus_driver);
--- /dev/null
+/*
+ * Freescale Management Complex (MC) bus driver MSI support
+ *
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ * Author: German Rivera <German.Rivera@freescale.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include "../include/mc-private.h"
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/irqchip/arm-gic-v3.h>
+#include <linux/of_irq.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/msi.h>
+#include "../include/mc-sys.h"
+#include "dprc-cmd.h"
+
+static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
+ struct msi_desc *desc)
+{
+ arg->desc = desc;
+ arg->hwirq = (irq_hw_number_t)desc->fsl_mc.msi_index;
+}
+
+static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info)
+{
+ struct msi_domain_ops *ops = info->ops;
+
+ if (WARN_ON(!ops))
+ return;
+
+ /*
+ * set_desc should not be set by the caller
+ */
+ if (WARN_ON(ops->set_desc))
+ return;
+
+ ops->set_desc = fsl_mc_msi_set_desc;
+}
+
+static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
+ struct fsl_mc_device_irq *mc_dev_irq)
+{
+ int error;
+ struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev;
+ struct msi_desc *msi_desc = mc_dev_irq->msi_desc;
+ struct dprc_irq_cfg irq_cfg;
+
+ /*
+ * msi_desc->msg.address is 0x0 when this function is invoked in
+ * the free_irq() code path. In this case, for the MC, we don't
+ * really need to "unprogram" the MSI, so we just return.
+ */
+ if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0)
+ return;
+
+ if (WARN_ON(!owner_mc_dev))
+ return;
+
+ irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) |
+ msi_desc->msg.address_lo;
+ irq_cfg.val = msi_desc->msg.data;
+ irq_cfg.user_irq_id = msi_desc->irq;
+
+ if (owner_mc_dev == mc_bus_dev) {
+ /*
+ * IRQ is for the mc_bus_dev's DPRC itself
+ */
+ error = dprc_set_irq(mc_bus_dev->mc_io,
+ MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
+ mc_bus_dev->mc_handle,
+ mc_dev_irq->dev_irq_index,
+ &irq_cfg);
+ if (error < 0) {
+ dev_err(&owner_mc_dev->dev,
+ "dprc_set_irq() failed: %d\n", error);
+ }
+ } else {
+ /*
+ * IRQ is for for a child device of mc_bus_dev
+ */
+ error = dprc_set_obj_irq(mc_bus_dev->mc_io,
+ MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI,
+ mc_bus_dev->mc_handle,
+ owner_mc_dev->obj_desc.type,
+ owner_mc_dev->obj_desc.id,
+ mc_dev_irq->dev_irq_index,
+ &irq_cfg);
+ if (error < 0) {
+ dev_err(&owner_mc_dev->dev,
+ "dprc_obj_set_irq() failed: %d\n", error);
+ }
+ }
+}
+
+/*
+ * NOTE: This function is invoked with interrupts disabled
+ */
+static void fsl_mc_msi_write_msg(struct irq_data *irq_data,
+ struct msi_msg *msg)
+{
+ struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
+ struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev);
+ struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
+ struct fsl_mc_device_irq *mc_dev_irq =
+ &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index];
+
+ WARN_ON(mc_dev_irq->msi_desc != msi_desc);
+ msi_desc->msg = *msg;
+
+ /*
+ * Program the MSI (paddr, value) pair in the device:
+ */
+ __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
+}
+
+static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
+{
+ struct irq_chip *chip = info->chip;
+
+ if (WARN_ON((!chip)))
+ return;
+
+ /*
+ * irq_write_msi_msg should not be set by the caller
+ */
+ if (WARN_ON(chip->irq_write_msi_msg))
+ return;
+
+ chip->irq_write_msi_msg = fsl_mc_msi_write_msg;
+}
+
+/**
+ * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain
+ * @np: Optional device-tree node of the interrupt controller
+ * @info: MSI domain info
+ * @parent: Parent irq domain
+ *
+ * Updates the domain and chip ops and creates a fsl-mc MSI
+ * interrupt domain.
+ *
+ * Returns:
+ * A domain pointer or NULL in case of failure.
+ */
+struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
+ struct msi_domain_info *info,
+ struct irq_domain *parent)
+{
+ struct irq_domain *domain;
+
+ if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
+ fsl_mc_msi_update_dom_ops(info);
+ if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
+ fsl_mc_msi_update_chip_ops(info);
+
+ domain = msi_create_irq_domain(fwnode, info, parent);
+ if (domain)
+ domain->bus_token = DOMAIN_BUS_FSL_MC_MSI;
+
+ return domain;
+}
+
+int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
+ struct irq_domain **mc_msi_domain)
+{
+ struct irq_domain *msi_domain;
+ struct device_node *mc_of_node = mc_platform_dev->of_node;
+
+ msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
+ DOMAIN_BUS_FSL_MC_MSI);
+ if (!msi_domain) {
+ pr_err("Unable to find fsl-mc MSI domain for %s\n",
+ mc_of_node->full_name);
+
+ return -ENOENT;
+ }
+
+ *mc_msi_domain = msi_domain;
+ return 0;
+}
+
+static void fsl_mc_msi_free_descs(struct device *dev)
+{
+ struct msi_desc *desc, *tmp;
+
+ list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
+ list_del(&desc->list);
+ free_msi_entry(desc);
+ }
+}
+
+static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count)
+
+{
+ unsigned int i;
+ int error;
+ struct msi_desc *msi_desc;
+
+ for (i = 0; i < irq_count; i++) {
+ msi_desc = alloc_msi_entry(dev);
+ if (!msi_desc) {
+ dev_err(dev, "Failed to allocate msi entry\n");
+ error = -ENOMEM;
+ goto cleanup_msi_descs;
+ }
+
+ msi_desc->fsl_mc.msi_index = i;
+ msi_desc->nvec_used = 1;
+ INIT_LIST_HEAD(&msi_desc->list);
+ list_add_tail(&msi_desc->list, dev_to_msi_list(dev));
+ }
+
+ return 0;
+
+cleanup_msi_descs:
+ fsl_mc_msi_free_descs(dev);
+ return error;
+}
+
+int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
+ unsigned int irq_count)
+{
+ struct irq_domain *msi_domain;
+ int error;
+
+ if (WARN_ON(!list_empty(dev_to_msi_list(dev))))
+ return -EINVAL;
+
+ error = fsl_mc_msi_alloc_descs(dev, irq_count);
+ if (error < 0)
+ return error;
+
+ msi_domain = dev_get_msi_domain(dev);
+ if (WARN_ON(!msi_domain)) {
+ error = -EINVAL;
+ goto cleanup_msi_descs;
+ }
+
+ /*
+ * NOTE: Calling this function will trigger the invocation of the
+ * its_fsl_mc_msi_prepare() callback
+ */
+ error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
+
+ if (error) {
+ dev_err(dev, "Failed to allocate IRQs\n");
+ goto cleanup_msi_descs;
+ }
+
+ return 0;
+
+cleanup_msi_descs:
+ fsl_mc_msi_free_descs(dev);
+ return error;
+}
+
+void fsl_mc_msi_domain_free_irqs(struct device *dev)
+{
+ struct irq_domain *msi_domain;
+
+ msi_domain = dev_get_msi_domain(dev);
+ if (WARN_ON(!msi_domain))
+ return;
+
+ msi_domain_free_irqs(msi_domain, dev);
+
+ if (WARN_ON(list_empty(dev_to_msi_list(dev))))
+ return;
+
+ fsl_mc_msi_free_descs(dev);
+}
* @user_irq_id: A user defined number associated with this IRQ
*/
struct dprc_irq_cfg {
- u64 paddr;
+ phys_addr_t paddr;
u32 val;
int user_irq_id;
};
strcmp(_obj_type, "dpmcp") == 0 || \
strcmp(_obj_type, "dpcon") == 0)
+struct irq_domain;
+struct msi_domain_info;
+
+/**
+ * Maximum number of total IRQs that can be pre-allocated for an MC bus'
+ * IRQ pool
+ */
+#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256
+
+struct device_node;
+struct irq_domain;
+struct msi_domain_info;
+
/**
* struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
* @root_mc_bus_dev: MC object device representing the root DPRC
* @resource_pools: array of resource pools (one pool per resource type)
* for this MC bus. These resources represent allocatable entities
* from the physical DPRC.
+ * @irq_resources: Pointer to array of IRQ objects for the IRQ pool
* @scan_mutex: Serializes bus scanning
*/
struct fsl_mc_bus {
struct fsl_mc_device mc_dev;
struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES];
+ struct fsl_mc_device_irq *irq_resources;
struct mutex scan_mutex; /* serializes bus scanning */
};
int dprc_scan_container(struct fsl_mc_device *mc_bus_dev);
-int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev);
+int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev,
+ unsigned int *total_irq_count);
int __init dprc_driver_init(void);
void fsl_mc_resource_free(struct fsl_mc_resource *resource);
+struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode,
+ struct msi_domain_info *info,
+ struct irq_domain *parent);
+
+int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
+ struct irq_domain **mc_msi_domain);
+
+int fsl_mc_msi_domain_alloc_irqs(struct device *dev,
+ unsigned int irq_count);
+
+void fsl_mc_msi_domain_free_irqs(struct device *dev);
+
+int __init its_fsl_mc_msi_init(void);
+
+void its_fsl_mc_msi_cleanup(void);
+
+int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
+ unsigned int irq_count);
+
+void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus);
+
#endif /* _FSL_MC_PRIVATE_H_ */
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/list.h>
+#include <linux/interrupt.h>
#include "../include/dprc.h"
#define FSL_MC_VENDOR_FREESCALE 0x1957
struct fsl_mc_device;
struct fsl_mc_io;
+struct fsl_mc_bus;
/**
* struct fsl_mc_driver - MC object device driver object
FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */
FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */
FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */
+ FSL_MC_POOL_IRQ,
/*
* NOTE: New resource pool types must be added before this entry
struct list_head node;
};
+/**
+ * struct fsl_mc_device_irq - MC object device message-based interrupt
+ * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs()
+ * @mc_dev: MC object device that owns this interrupt
+ * @dev_irq_index: device-relative IRQ index
+ * @resource: MC generic resource associated with the interrupt
+ */
+struct fsl_mc_device_irq {
+ struct msi_desc *msi_desc;
+ struct fsl_mc_device *mc_dev;
+ u8 dev_irq_index;
+ struct fsl_mc_resource resource;
+};
+
+#define to_fsl_mc_irq(_mc_resource) \
+ container_of(_mc_resource, struct fsl_mc_device_irq, resource)
+
/**
* Bit masks for a MC object device (struct fsl_mc_device) flags
*/
* NULL if none.
* @obj_desc: MC description of the DPAA device
* @regions: pointer to array of MMIO region entries
+ * @irqs: pointer to array of pointers to interrupts allocated to this device
* @resource: generic resource associated with this MC object device, if any.
*
* Generic device object for MC object devices that are "attached" to a
struct fsl_mc_io *mc_io;
struct dprc_obj_desc obj_desc;
struct resource *regions;
+ struct fsl_mc_device_irq **irqs;
struct fsl_mc_resource *resource;
};
void fsl_mc_object_free(struct fsl_mc_device *mc_adev);
+int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev);
+
+void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
+
extern struct bus_type fsl_mc_bus_type;
#endif /* _FSL_MC_H_ */
{
struct dma_pending *pending, *next;
- if (fifo->data == NULL)
+ if (!fifo->data)
return;
list_for_each_entry_safe(pending, next, &fifo->pending, link)
{
struct dma_pending *pending, *next;
- if (fifo->data == NULL)
+ if (!fifo->data)
return;
list_for_each_entry_safe(pending, next, &fifo->pending, link)
{
int ofs, l;
- if (fifo->data == NULL)
+ if (!fifo->data)
return -ENOENT;
if (fifo->corrupt)
return -ENXIO;
{
unsigned len, n, ofs, l, limit;
- if (fifo->data == NULL)
+ if (!fifo->data)
return -ENOENT;
if (fifo->corrupt)
return -ENXIO;
{
struct dma_pending *pending, *next, *tmp;
- if (fifo->data == NULL)
+ if (!fifo->data)
return -ENOENT;
if (fifo->corrupt)
return -ENXIO;
rcu_read_unlock();
}
-struct fwtty_port *fwtty_port_get(unsigned index)
+static struct fwtty_port *fwtty_port_get(unsigned index)
{
struct fwtty_port *port;
mutex_unlock(&port_table_lock);
return port;
}
-EXPORT_SYMBOL(fwtty_port_get);
static int fwtty_ports_add(struct fw_serial *serial)
{
seq_printf(m, " %s:", dev_name(&peer->unit->device));
seq_printf(m, " node:%04x gen:%d", peer->node_id, generation);
seq_printf(m, " sp:%d max:%d guid:%016llx", peer->speed,
- peer->max_payload, (unsigned long long) peer->guid);
- seq_printf(m, " mgmt:%012llx", (unsigned long long) peer->mgmt_addr);
- seq_printf(m, " addr:%012llx", (unsigned long long) peer->status_addr);
+ peer->max_payload, (unsigned long long)peer->guid);
+ seq_printf(m, " mgmt:%012llx", (unsigned long long)peer->mgmt_addr);
+ seq_printf(m, " addr:%012llx", (unsigned long long)peer->status_addr);
seq_putc(m, '\n');
}
rcu_read_lock();
seq_printf(m, "card: %s guid: %016llx\n",
dev_name(serial->card->device),
- (unsigned long long) serial->card->guid);
+ (unsigned long long)serial->card->guid);
list_for_each_entry_rcu(peer, &serial->peer_list, list)
fwtty_debugfs_show_peer(m, peer);
rcu_read_unlock();
* been probed for any unit devices...
*/
fwtty_err(card, "unknown card (guid %016llx)\n",
- (unsigned long long) card->guid);
+ (unsigned long long)card->guid);
return NULL;
}
smp_rmb();
fwtty_dbg(card, "peer(%d:%x) guid: %016llx\n",
- g, peer->node_id, (unsigned long long) peer->guid);
+ g, peer->node_id, (unsigned long long)peer->guid);
}
}
#else
list_add_rcu(&serial->list, &fwserial_list);
fwtty_notice(&unit, "TTY over FireWire on device %s (guid %016llx)\n",
- dev_name(card->device), (unsigned long long) card->guid);
+ dev_name(card->device), (unsigned long long)card->guid);
err = fwserial_add_peer(serial, unit);
if (!err)
extern struct tty_driver *fwtty_driver;
-struct fwtty_port *fwtty_port_get(unsigned index);
/*
* Returns the max send async payload size in bytes based on the unit device
* link speed. Self-limiting asynchronous bandwidth (via reducing the payload)
static struct {
struct list_head head;
int cnt;
- spinlock_t lock;
+ spinlock_t lock; /* protect structure fields */
} qos_free_list;
static void init_qos_entry_list(void)
int qos_list_cnt;
int qos_null_idx;
struct gdm_wimax_csr_s csr[QOS_MAX];
- spinlock_t qos_lock;
+ spinlock_t qos_lock; /* Protect structure fields */
int qos_limit_size;
};
struct list_head hci_list;
ktime_t sdu_stamp;
u8 *sdu_buf;
- spinlock_t lock;
+ spinlock_t lock; /* protect structure fields */
int can_send;
int stop_sdu_tx;
};
struct list_head free_list;
struct list_head req_list;
u8 *rx_buf;
- spinlock_t lock;
+ spinlock_t lock; /* protect structure fields */
};
struct sdiowm_dev {
idVendor, idProduct);
dev_info(&intf->dev, "GCT WiMax driver version %s\n", DRIVER_VERSION);
-
if (idProduct == EMERGENCY_PID) {
ret = usb_emergency(usbdev);
goto out;
#include <linux/usb.h>
#include <linux/list.h>
-#define B_DIFF_DL_DRV (1 << 4)
-#define B_DOWNLOAD (1 << 5)
+#define B_DIFF_DL_DRV BIT(4)
+#define B_DOWNLOAD BIT(5)
#define MAX_NR_SDU_BUF 64
struct usb_tx {
#if defined(CONFIG_WIMAX_GDM72XX_USB_PM) || defined(CONFIG_WIMAX_GDM72XX_K_MODE)
struct list_head pending_list;
#endif
- spinlock_t lock;
+ spinlock_t lock; /* Protect structure fields */
};
struct usb_rx {
struct rx_cxt {
struct list_head free_list;
struct list_head used_list;
- spinlock_t lock;
+ spinlock_t lock; /* Protect structure fields */
};
struct usbwm_dev {
int ref_cnt;
struct sock *sock;
struct list_head evtq;
- spinlock_t evt_lock;
+ spinlock_t evt_lock; /*protect structure fields */
struct list_head freeq;
struct work_struct ws;
} wm_event;
#define T_TX_POWER (0x6a | (1 << 16))
#define T_CUR_FREQ (0x7f | (4 << 16))
-
/* WIMAX */
#define T_MAX_SUBSCRIPTION (0xa1 | (1 << 16))
#define T_MAX_SF (0xa2 | (1 << 16))
#define T_DUPLEX_MODE (0xdb | (4 << 16))
/* T_CAPABILITY */
-#define T_CAPABILITY_MULTI_CS (1 << 0)
-#define T_CAPABILITY_WIMAX (1 << 1)
-#define T_CAPABILITY_QOS (1 << 2)
-#define T_CAPABILITY_AGGREGATION (1 << 3)
+#define T_CAPABILITY_MULTI_CS BIT(0)
+#define T_CAPABILITY_WIMAX BIT(1)
+#define T_CAPABILITY_QOS BIT(2)
+#define T_CAPABILITY_AGGREGATION BIT(3)
struct hci_s {
__be16 cmd_evt;
#include "netlink_k.h"
#if !defined(NLMSG_HDRLEN)
-#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
+#define NLMSG_HDRLEN ((int)NLMSG_ALIGN(sizeof(struct nlmsghdr)))
#endif
#define ND_MAX_GROUP 30
#define BL_PID_MASK 0xffc0
#define USB_DEVICE_BOOTLOADER(vid, pid) \
- {USB_DEVICE((vid), ((pid)&BL_PID_MASK)|B_DOWNLOAD)}
+ {USB_DEVICE((vid), ((pid) & BL_PID_MASK) | B_DOWNLOAD)}
#define USB_DEVICE_BOOTLOADER_DRV(vid, pid) \
- {USB_DEVICE((vid), ((pid)&BL_PID_MASK)|B_DOWNLOAD|B_DIFF_DL_DRV)}
+ {USB_DEVICE((vid), ((pid) & BL_PID_MASK) | B_DOWNLOAD | B_DIFF_DL_DRV)}
#define USB_DEVICE_CDC_DATA(vid, pid) \
{USB_DEVICE_INTF((vid), (pid), USB_CLASS_CDC_DATA)}
USB_DEVICE_BOOTLOADER(GCT_VID, GCT_PID1),
USB_DEVICE_BOOTLOADER_DRV(GCT_VID, GCT_PID1),
USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x1),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x2),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x3),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x4),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x5),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x6),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x7),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x8),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0x9),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xa),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xb),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xc),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xd),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xe),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1+0xf),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0x1),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0x2),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0x3),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0x4),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0x5),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0x6),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0x7),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0x8),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0x9),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0xa),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0xb),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0xc),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0xd),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0xe),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID1 + 0xf),
USB_DEVICE_BOOTLOADER(GCT_VID, GCT_PID2),
USB_DEVICE_BOOTLOADER_DRV(GCT_VID, GCT_PID2),
USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x1),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x2),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x3),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x4),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x5),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x6),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x7),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x8),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0x9),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xa),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xb),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xc),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xd),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xe),
- USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2+0xf),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0x1),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0x2),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0x3),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0x4),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0x5),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0x6),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0x7),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0x8),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0x9),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0xa),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0xb),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0xc),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0xd),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0xe),
+ USB_DEVICE_CDC_DATA(GCT_VID, GCT_PID2 + 0xf),
{USB_DEVICE(GCT_VID, EMERGENCY_PID)},
{ }
platform_set_drvdata(pdev, data);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (r == NULL) {
+ if (!r) {
dev_err(&pdev->dev, "platform_get_resource failed\n");
return -ENODEV;
}
data->reg_base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE);
- if (data->reg_base == NULL)
+ if (!data->reg_base)
return -ENOMEM;
data->irq = platform_get_irq(pdev, 0);
}
data->buffer_virt = dmam_alloc_coherent(&pdev->dev,
COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL);
- if (data->buffer_virt == NULL) {
+ if (!data->buffer_virt) {
dev_err(&pdev->dev, "allocate buffer failed\n");
return -ENOMEM;
}
#define DEVICE_NAME "device"
#define CLASS_NAME "fpgaboot"
-static uint8_t bits_magic[] = {
+static u8 bits_magic[] = {
0x0, 0x9, 0xf, 0xf0, 0xf, 0xf0,
0xf, 0xf0, 0xf, 0xf0, 0x0, 0x0, 0x1};
static void readinfo_bitstream(char *bitdata, char *buf, int *offset)
{
char tbuf[64];
- int32_t len;
+ s32 len;
/* read section char */
read_bitstream(bitdata, tbuf, offset, 1);
int err;
struct fpgaimage *fimage;
- fimage = kmalloc(sizeof(struct fpgaimage), GFP_KERNEL);
+ fimage = kmalloc(sizeof(*fimage), GFP_KERNEL);
if (!fimage)
return -ENOMEM;
-
-What: /sys/bus/iio/devices/device[n]/range
-KernelVersion: 2.6.37
-Contact: linux-iio@vger.kernel.org
-Description:
- Hardware dependent ADC Full Scale Range used for some ambient
- light sensors in calculating lux.
-
-What: /sys/bus/iio/devices/device[n]/range_available
-KernelVersion: 2.6.37
-Contact: linux-iio@vger.kernel.org
-Description:
- Hardware dependent supported vales for ADC Full Scale Range.
-
-What: /sys/bus/iio/devices/device[n]/adc_resolution
-KernelVersion: 2.6.37
-Contact: linux-iio@vger.kernel.org
-Description:
- Hardware dependent ADC resolution of the ambient light sensor
- used in calculating the lux.
-
-What: /sys/bus/iio/devices/device[n]/adc_resolution_available
-KernelVersion: 2.6.37
-Contact: linux-iio@vger.kernel.org
-Description:
- Hardware dependent list of possible values supported for the
- adc_resolution of the given sensor.
-
What: /sys/bus/iio/devices/device[n]/in_illuminance0[_input|_raw]
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
st->mclk = pdata->ext_clk_hz;
else
st->mclk = AD7192_INT_FREQ_MHZ;
- break;
+ break;
default:
ret = -EINVAL;
goto out;
static int ad7280_write(struct ad7280_state *st, unsigned devaddr,
unsigned addr, bool all, unsigned val)
{
- unsigned reg = (devaddr << 27 | addr << 21 |
- (val & 0xFF) << 13 | all << 12);
+ unsigned reg = devaddr << 27 | addr << 21 |
+ (val & 0xFF) << 13 | all << 12;
reg |= ad7280_calc_crc8(st->crc_tab, reg >> 11) << 3 | 0x2;
st->buf[0] = cpu_to_be32(reg);
*/
#define AD7150_STATUS 0
-#define AD7150_STATUS_OUT1 (1 << 3)
-#define AD7150_STATUS_OUT2 (1 << 5)
+#define AD7150_STATUS_OUT1 BIT(3)
+#define AD7150_STATUS_OUT2 BIT(5)
#define AD7150_CH1_DATA_HIGH 1
#define AD7150_CH2_DATA_HIGH 3
#define AD7150_CH1_AVG_HIGH 5
#define AD7150_CH2_TIMEOUT 13
#define AD7150_CH2_SETUP 14
#define AD7150_CFG 15
-#define AD7150_CFG_FIX (1 << 7)
+#define AD7150_CFG_FIX BIT(7)
#define AD7150_PD_TIMER 16
#define AD7150_CH1_CAPDAC 17
#define AD7150_CH2_CAPDAC 18
/* lock should be held */
static int ad7150_write_event_params(struct iio_dev *indio_dev,
- unsigned int chan, enum iio_event_type type,
- enum iio_event_direction dir)
+ unsigned int chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
{
int ret;
u16 value;
}
static int ad7150_write_event_config(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir, int state)
{
u8 thresh_type, cfg, adaptive;
int ret;
}
static int ad7150_write_event_value(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir,
- enum iio_event_info info,
- int val, int val2)
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
{
int ret;
struct ad7150_chip_info *chip = iio_priv(indio_dev);
}
static ssize_t ad7150_store_timeout(struct device *dev,
- struct device_attribute *attr,
- const char *buf,
- size_t len)
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7150_chip_info *chip = iio_priv(indio_dev);
*/
static int ad7150_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
int ret;
struct ad7150_chip_info *chip;
/* Set the gain based on tsl2x7x_settings struct */
chip->tsl2x7x_config[TSL2X7X_GAIN] =
- (chip->tsl2x7x_settings.als_gain |
+ chip->tsl2x7x_settings.als_gain |
(TSL2X7X_mA100 | TSL2X7X_DIODE1)
- | ((chip->tsl2x7x_settings.prox_gain) << 2));
+ | ((chip->tsl2x7x_settings.prox_gain) << 2);
/* set chip struct re scaling and saturation */
chip->als_saturation = als_count * 922; /* 90% of full scale */
result.fract /= 3;
chip->tsl2x7x_settings.als_time =
- (TSL2X7X_MAX_TIMER_CNT - (u8)result.fract);
+ TSL2X7X_MAX_TIMER_CNT - (u8)result.fract;
dev_info(&chip->client->dev, "%s: als time = %d",
__func__, chip->tsl2x7x_settings.als_time);
int (*p_close)(unsigned long, void *);
int (*p_read)(struct cfs_psdev_file *, char *, unsigned long);
int (*p_write)(struct cfs_psdev_file *, char *, unsigned long);
- int (*p_ioctl)(struct cfs_psdev_file *, unsigned long, void *);
+ int (*p_ioctl)(struct cfs_psdev_file *, unsigned long, void __user *);
};
/*
* Defined by platform
*/
int unshare_fs_struct(void);
-sigset_t cfs_get_blocked_sigs(void);
sigset_t cfs_block_allsigs(void);
sigset_t cfs_block_sigs(unsigned long sigs);
sigset_t cfs_block_sigsinv(unsigned long sigs);
#include "libcfs_prim.h"
#include "libcfs_time.h"
#include "libcfs_string.h"
-#include "libcfs_kernelcomm.h"
#include "libcfs_workitem.h"
#include "libcfs_hash.h"
#include "libcfs_fail.h"
#define S_LOV 0x00020000
#define S_LQUOTA 0x00040000
#define S_OSD 0x00080000
-/* unused */
+#define S_LFSCK 0x00100000
/* unused */
/* unused */
#define S_LMV 0x00800000 /* b_new_cmd */
char *ioc_inlbuf2;
__u32 ioc_plen1; /* buffers in userspace */
- char *ioc_pbuf1;
+ void __user *ioc_pbuf1;
__u32 ioc_plen2; /* buffers in userspace */
- char *ioc_pbuf2;
+ void __user *ioc_pbuf2;
char ioc_bulk[0];
};
/* FIXME check conflict with lustre_lib.h */
#define LIBCFS_IOC_DEBUG_MASK _IOWR('f', 250, long)
-/* ioctls for manipulating snapshots 30- */
#define IOC_LIBCFS_TYPE 'e'
#define IOC_LIBCFS_MIN_NR 30
/* libcfs ioctls */
#define IOC_LIBCFS_GET_ROUTE _IOWR('e', 54, long)
#define IOC_LIBCFS_NOTIFY_ROUTER _IOWR('e', 55, long)
#define IOC_LIBCFS_UNCONFIGURE _IOWR('e', 56, long)
-#define IOC_LIBCFS_PORTALS_COMPATIBILITY _IOWR('e', 57, long)
+/* #define IOC_LIBCFS_PORTALS_COMPATIBILITY _IOWR('e', 57, long) */
#define IOC_LIBCFS_LNET_DIST _IOWR('e', 58, long)
#define IOC_LIBCFS_CONFIGURE _IOWR('e', 59, long)
#define IOC_LIBCFS_TESTPROTOCOMPAT _IOWR('e', 60, long)
#define IOC_LIBCFS_PING _IOWR('e', 61, long)
-#define IOC_LIBCFS_DEBUG_PEER _IOWR('e', 62, long)
+/* #define IOC_LIBCFS_DEBUG_PEER _IOWR('e', 62, long) */
#define IOC_LIBCFS_LNETST _IOWR('e', 63, long)
/* lnd ioctls */
#define IOC_LIBCFS_REGISTER_MYNID _IOWR('e', 70, long)
int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand);
int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand);
-int libcfs_ioctl_getdata(char *buf, char *end, void *arg);
-int libcfs_ioctl_popdata(void *arg, void *buf, int size);
+int libcfs_ioctl_getdata(char *buf, char *end, void __user *arg);
+int libcfs_ioctl_popdata(void __user *arg, void *buf, int size);
#endif /* __LIBCFS_IOCTL_H__ */
* Support for temporary event tracing with minimal Heisenberg effect.
* -------------------------------------------------------------------- */
-struct libcfs_device_userstate {
- int ldu_memhog_pages;
- struct page *ldu_memhog_root_page;
-};
-
#define MKSTR(ptr) ((ptr)) ? (ptr) : ""
static inline int cfs_size_round4(int val)
#define __LIBCFS_STRING_H__
/* libcfs_string.c */
-/* string comparison ignoring case */
-int cfs_strncasecmp(const char *s1, const char *s2, size_t n);
/* Convert a text string to a bitmask */
int cfs_str2mask(const char *str, const char *(*bit2str)(int bit),
int *oldmask, int minmask, int allmask);
int LNetSetLazyPortal(int portal);
int LNetClearLazyPortal(int portal);
int LNetCtl(unsigned int cmd, void *arg);
+void LNetDebugPeer(lnet_process_id_t id);
/** @} lnet_misc */
int lnet_ping_target_init(void);
void lnet_ping_target_fini(void);
-int lnet_ping(lnet_process_id_t id, int timeout_ms,
- lnet_process_id_t *ids, int n_ids);
int lnet_parse_ip2nets(char **networksp, char *ip2nets);
int lnet_parse_routes(char *route_str, int *im_a_router);
int lstio_ses_force; /* IN: force create ? */
/** IN: session features */
unsigned lstio_ses_feats;
- lst_sid_t *lstio_ses_idp; /* OUT: session id */
+ lst_sid_t __user *lstio_ses_idp; /* OUT: session id */
int lstio_ses_nmlen; /* IN: name length */
- char *lstio_ses_namep; /* IN: session name */
+ char __user *lstio_ses_namep; /* IN: session name */
} lstio_session_new_args_t;
/* query current session */
typedef struct {
- lst_sid_t *lstio_ses_idp; /* OUT: session id */
- int *lstio_ses_keyp; /* OUT: local key */
+ lst_sid_t __user *lstio_ses_idp; /* OUT: session id */
+ int __user *lstio_ses_keyp; /* OUT: local key */
/** OUT: session features */
- unsigned *lstio_ses_featp;
- lstcon_ndlist_ent_t *lstio_ses_ndinfo; /* OUT: */
+ unsigned __user *lstio_ses_featp;
+ lstcon_ndlist_ent_t __user *lstio_ses_ndinfo; /* OUT: */
int lstio_ses_nmlen; /* IN: name length */
- char *lstio_ses_namep; /* OUT: session name */
+ char __user *lstio_ses_namep; /* OUT: session name */
} lstio_session_info_args_t;
/* delete a session */
int lstio_dbg_timeout; /* IN: timeout of
debug */
int lstio_dbg_nmlen; /* IN: len of name */
- char *lstio_dbg_namep; /* IN: name of
+ char __user *lstio_dbg_namep; /* IN: name of
group|batch */
int lstio_dbg_count; /* IN: # of test nodes
to debug */
- lnet_process_id_t *lstio_dbg_idsp; /* IN: id of test
+ lnet_process_id_t __user *lstio_dbg_idsp; /* IN: id of test
nodes */
- struct list_head *lstio_dbg_resultp; /* OUT: list head of
+ struct list_head __user *lstio_dbg_resultp; /* OUT: list head of
result buffer */
} lstio_debug_args_t;
typedef struct {
- int lstio_grp_key; /* IN: session key */
- int lstio_grp_nmlen; /* IN: name length */
- char *lstio_grp_namep; /* IN: group name */
+ int lstio_grp_key; /* IN: session key */
+ int lstio_grp_nmlen; /* IN: name length */
+ char __user *lstio_grp_namep; /* IN: group name */
} lstio_group_add_args_t;
typedef struct {
- int lstio_grp_key; /* IN: session key */
- int lstio_grp_nmlen; /* IN: name length */
- char *lstio_grp_namep; /* IN: group name */
+ int lstio_grp_key; /* IN: session key */
+ int lstio_grp_nmlen; /* IN: name length */
+ char __user *lstio_grp_namep; /* IN: group name */
} lstio_group_del_args_t;
#define LST_GROUP_CLEAN 1 /* remove inactive nodes in the group */
int lstio_grp_opc; /* IN: OPC */
int lstio_grp_args; /* IN: arguments */
int lstio_grp_nmlen; /* IN: name length */
- char *lstio_grp_namep; /* IN: group name */
+ char __user *lstio_grp_namep; /* IN: group name */
int lstio_grp_count; /* IN: # of nodes id */
- lnet_process_id_t *lstio_grp_idsp; /* IN: array of nodes */
- struct list_head *lstio_grp_resultp; /* OUT: list head of
+ lnet_process_id_t __user *lstio_grp_idsp; /* IN: array of nodes */
+ struct list_head __user *lstio_grp_resultp; /* OUT: list head of
result buffer */
} lstio_group_update_args_t;
typedef struct {
int lstio_grp_key; /* IN: session key */
int lstio_grp_nmlen; /* IN: name length */
- char *lstio_grp_namep; /* IN: group name */
+ char __user *lstio_grp_namep; /* IN: group name */
int lstio_grp_count; /* IN: # of nodes */
/** OUT: session features */
- unsigned *lstio_grp_featp;
- lnet_process_id_t *lstio_grp_idsp; /* IN: nodes */
- struct list_head *lstio_grp_resultp; /* OUT: list head of
+ unsigned __user *lstio_grp_featp;
+ lnet_process_id_t __user *lstio_grp_idsp; /* IN: nodes */
+ struct list_head __user *lstio_grp_resultp; /* OUT: list head of
result buffer */
} lstio_group_nodes_args_t;
int lstio_grp_key; /* IN: session key */
int lstio_grp_idx; /* IN: group idx */
int lstio_grp_nmlen; /* IN: name len */
- char *lstio_grp_namep; /* OUT: name */
+ char __user *lstio_grp_namep; /* OUT: name */
} lstio_group_list_args_t;
typedef struct {
int lstio_grp_key; /* IN: session key */
int lstio_grp_nmlen; /* IN: name len */
- char *lstio_grp_namep; /* IN: name */
- lstcon_ndlist_ent_t *lstio_grp_entp; /* OUT: description of
+ char __user *lstio_grp_namep; /* IN: name */
+ lstcon_ndlist_ent_t __user *lstio_grp_entp; /* OUT: description of
group */
- int *lstio_grp_idxp; /* IN/OUT: node index */
- int *lstio_grp_ndentp; /* IN/OUT: # of nodent */
- lstcon_node_ent_t *lstio_grp_dentsp; /* OUT: nodent array */
+ int __user *lstio_grp_idxp; /* IN/OUT: node index */
+ int __user *lstio_grp_ndentp; /* IN/OUT: # of nodent */
+ lstcon_node_ent_t __user *lstio_grp_dentsp; /* OUT: nodent array */
} lstio_group_info_args_t;
#define LST_DEFAULT_BATCH "batch" /* default batch name */
typedef struct {
int lstio_bat_key; /* IN: session key */
int lstio_bat_nmlen; /* IN: name length */
- char *lstio_bat_namep; /* IN: batch name */
+ char __user *lstio_bat_namep; /* IN: batch name */
} lstio_batch_add_args_t;
typedef struct {
int lstio_bat_key; /* IN: session key */
int lstio_bat_nmlen; /* IN: name length */
- char *lstio_bat_namep; /* IN: batch name */
+ char __user *lstio_bat_namep; /* IN: batch name */
} lstio_batch_del_args_t;
typedef struct {
int lstio_bat_timeout; /* IN: timeout for
the batch */
int lstio_bat_nmlen; /* IN: name length */
- char *lstio_bat_namep; /* IN: batch name */
- struct list_head *lstio_bat_resultp; /* OUT: list head of
+ char __user *lstio_bat_namep; /* IN: batch name */
+ struct list_head __user *lstio_bat_resultp; /* OUT: list head of
result buffer */
} lstio_batch_run_args_t;
int lstio_bat_force; /* IN: abort unfinished
test RPC */
int lstio_bat_nmlen; /* IN: name length */
- char *lstio_bat_namep; /* IN: batch name */
- struct list_head *lstio_bat_resultp; /* OUT: list head of
+ char __user *lstio_bat_namep; /* IN: batch name */
+ struct list_head __user *lstio_bat_resultp; /* OUT: list head of
result buffer */
} lstio_batch_stop_args_t;
int lstio_bat_timeout; /* IN: timeout for
waiting */
int lstio_bat_nmlen; /* IN: name length */
- char *lstio_bat_namep; /* IN: batch name */
- struct list_head *lstio_bat_resultp; /* OUT: list head of
+ char __user *lstio_bat_namep; /* IN: batch name */
+ struct list_head __user *lstio_bat_resultp; /* OUT: list head of
result buffer */
} lstio_batch_query_args_t;
int lstio_bat_key; /* IN: session key */
int lstio_bat_idx; /* IN: index */
int lstio_bat_nmlen; /* IN: name length */
- char *lstio_bat_namep; /* IN: batch name */
+ char __user *lstio_bat_namep; /* IN: batch name */
} lstio_batch_list_args_t;
typedef struct {
int lstio_bat_key; /* IN: session key */
int lstio_bat_nmlen; /* IN: name length */
- char *lstio_bat_namep; /* IN: name */
+ char __user *lstio_bat_namep; /* IN: name */
int lstio_bat_server; /* IN: query server
or not */
int lstio_bat_testidx; /* IN: test index */
- lstcon_test_batch_ent_t *lstio_bat_entp; /* OUT: batch ent */
+ lstcon_test_batch_ent_t __user *lstio_bat_entp; /* OUT: batch ent */
- int *lstio_bat_idxp; /* IN/OUT: index of node */
- int *lstio_bat_ndentp; /* IN/OUT: # of nodent */
- lstcon_node_ent_t *lstio_bat_dentsp; /* array of nodent */
+ int __user *lstio_bat_idxp; /* IN/OUT: index of node */
+ int __user *lstio_bat_ndentp; /* IN/OUT: # of nodent */
+ lstcon_node_ent_t __user *lstio_bat_dentsp; /* array of nodent */
} lstio_batch_info_args_t;
/* add stat in session */
stat request */
int lstio_sta_nmlen; /* IN: group name
length */
- char *lstio_sta_namep; /* IN: group name */
+ char __user *lstio_sta_namep; /* IN: group name */
int lstio_sta_count; /* IN: # of pid */
- lnet_process_id_t *lstio_sta_idsp; /* IN: pid */
- struct list_head *lstio_sta_resultp; /* OUT: list head of
+ lnet_process_id_t __user *lstio_sta_idsp; /* IN: pid */
+ struct list_head __user *lstio_sta_resultp; /* OUT: list head of
result buffer */
} lstio_stat_args_t;
typedef struct {
int lstio_tes_key; /* IN: session key */
int lstio_tes_bat_nmlen; /* IN: batch name len */
- char *lstio_tes_bat_name; /* IN: batch name */
+ char __user *lstio_tes_bat_name; /* IN: batch name */
int lstio_tes_type; /* IN: test type */
int lstio_tes_oneside; /* IN: one sided test */
int lstio_tes_loop; /* IN: loop count */
destination groups */
int lstio_tes_sgrp_nmlen; /* IN: source group
name length */
- char *lstio_tes_sgrp_name; /* IN: group name */
+ char __user *lstio_tes_sgrp_name; /* IN: group name */
int lstio_tes_dgrp_nmlen; /* IN: destination group
name length */
- char *lstio_tes_dgrp_name; /* IN: group name */
+ char __user *lstio_tes_dgrp_name; /* IN: group name */
int lstio_tes_param_len; /* IN: param buffer len */
- void *lstio_tes_param; /* IN: parameter for specified
+ void __user *lstio_tes_param; /* IN: parameter for specified
test:
lstio_bulk_param_t,
lstio_ping_param_t,
... more */
- int *lstio_tes_retp; /* OUT: private returned
+ int __user *lstio_tes_retp; /* OUT: private returned
value */
- struct list_head *lstio_tes_resultp; /* OUT: list head of
+ struct list_head __user *lstio_tes_resultp;/* OUT: list head of
result buffer */
} lstio_test_args_t;
static int
kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit)
- __releases(conn->ibc_lock)
- __acquires(conn->ibc_lock)
+ __must_hold(&conn->ibc_lock)
{
kib_msg_t *msg = tx->tx_msg;
kib_peer_t *peer = conn->ibc_peer;
static int
ksocknal_send_keepalive_locked(ksock_peer_t *peer)
+ __must_hold(&ksocknal_data.ksnd_global_lock)
{
ksock_sched_t *sched;
ksock_conn_t *conn;
module_param(rnet_htable_size, int, 0444);
MODULE_PARM_DESC(rnet_htable_size, "size of remote network hash table");
+static int lnet_ping(lnet_process_id_t id, int timeout_ms,
+ lnet_process_id_t __user *ids, int n_ids);
+
static char *
lnet_get_routes(void)
{
EXPORT_SYMBOL(LNetNIFini);
/**
- * This is an ugly hack to export IOC_LIBCFS_DEBUG_PEER and
- * IOC_LIBCFS_PORTALS_COMPATIBILITY commands to users, by tweaking the LNet
- * internal ioctl handler.
- *
- * IOC_LIBCFS_PORTALS_COMPATIBILITY is now deprecated, don't use it.
+ * LNet ioctl handler.
*
- * \param cmd IOC_LIBCFS_DEBUG_PEER to print debugging data about a peer.
- * The data will be printed to system console. Don't use it excessively.
- * \param arg A pointer to lnet_process_id_t, process ID of the peer.
- *
- * \return Always return 0 when called by users directly (i.e., not via ioctl).
*/
int
LNetCtl(unsigned int cmd, void *arg)
return lnet_notify(NULL, data->ioc_nid, data->ioc_flags,
jiffies - secs_passed * HZ);
- case IOC_LIBCFS_PORTALS_COMPATIBILITY:
- /* This can be removed once lustre stops calling it */
- return 0;
-
case IOC_LIBCFS_LNET_DIST:
rc = LNetDist(data->ioc_nid, &data->ioc_nid, &data->ioc_u32[1]);
if (rc < 0 && rc != -EHOSTUNREACH)
id.nid = data->ioc_nid;
id.pid = data->ioc_u32[0];
rc = lnet_ping(id, data->ioc_u32[1], /* timeout */
- (lnet_process_id_t *)data->ioc_pbuf1,
+ data->ioc_pbuf1,
data->ioc_plen1/sizeof(lnet_process_id_t));
if (rc < 0)
return rc;
data->ioc_count = rc;
return 0;
- case IOC_LIBCFS_DEBUG_PEER: {
- /* CAVEAT EMPTOR: this one designed for calling directly; not
- * via an ioctl */
- id = *((lnet_process_id_t *) arg);
-
- lnet_debug_peer(id.nid);
-
- ni = lnet_net2ni(LNET_NIDNET(id.nid));
- if (ni == NULL) {
- CDEBUG(D_WARNING, "No NI for %s\n", libcfs_id2str(id));
- } else {
- if (ni->ni_lnd->lnd_ctl == NULL) {
- CDEBUG(D_WARNING, "No ctl for %s\n",
- libcfs_id2str(id));
- } else {
- (void)ni->ni_lnd->lnd_ctl(ni, cmd, arg);
- }
-
- lnet_ni_decref(ni);
- }
- return 0;
- }
-
default:
ni = lnet_net2ni(data->ioc_net);
if (ni == NULL)
}
EXPORT_SYMBOL(LNetCtl);
+void LNetDebugPeer(lnet_process_id_t id)
+{
+ lnet_debug_peer(id.nid);
+}
+EXPORT_SYMBOL(LNetDebugPeer);
+
/**
* Retrieve the lnet_process_id_t ID of LNet interface at \a index. Note that
* all interfaces share a same PID, as requested by LNetNIInit().
cfs_restore_sigs(blocked);
}
-int
-lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_ids)
+static int lnet_ping(lnet_process_id_t id, int timeout_ms,
+ lnet_process_id_t __user *ids, int n_ids)
{
lnet_handle_eq_t eqh;
lnet_handle_md_t mdh;
int niface;
int rc;
- /* NB we don't check interface conflicts here; it's the LNDs
- * responsibility (if it cares at all) */
+ /*
+ * NB we don't check interface conflicts here; it's the LNDs
+ * responsibility (if it cares at all)
+ */
if (square != NULL && (comma == NULL || square < comma)) {
- /* i.e: o2ib0(ib0)[1,2], number between square
- * brackets are CPTs this NI needs to be bond */
+ /*
+ * i.e: o2ib0(ib0)[1,2], number between square
+ * brackets are CPTs this NI needs to be bond
+ */
if (bracket != NULL && bracket > square) {
tmp = square;
goto failed_syntax;
len = strlen(sep + 1);
if ((sscanf((sep+1), "%u%n", priority, &nob) < 1) || (len != nob)) {
- /* Update the caller's token pointer so it treats the found
- priority as the token to report in the error message. */
+ /*
+ * Update the caller's token pointer so it treats the found
+ * priority as the token to report in the error message.
+ */
*token += sep - str + 1;
return -1;
}
* overflow, they don't skip entries, so the queue has the same
* apparent capacity at all times */
- count = roundup_pow_of_two(count);
+ if (count)
+ count = roundup_pow_of_two(count);
if (callback != LNET_EQ_HANDLER_NONE && count != 0)
CWARN("EQ callback is guaranteed to get every event, do you still want to set eqcount %d for polling event which will have locking overhead? Please contact with developer to confirm\n", count);
int
lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans,
- struct list_head *head_up,
+ struct list_head __user *head_up,
lstcon_rpc_readent_func_t readent)
{
struct list_head tmp;
- struct list_head *next;
+ struct list_head __user *next;
lstcon_rpc_ent_t *ent;
srpc_generic_reply_t *rep;
lstcon_rpc_t *crpc;
#define LST_TRANS_STATQRY 0x21
typedef int (*lstcon_rpc_cond_func_t)(int, struct lstcon_node *, void *);
-typedef int (*lstcon_rpc_readent_func_t)(int, srpc_msg_t *, lstcon_rpc_ent_t *);
+typedef int (*lstcon_rpc_readent_func_t)(int, srpc_msg_t *,
+ lstcon_rpc_ent_t __user *);
int lstcon_sesrpc_prep(struct lstcon_node *nd, int transop,
unsigned version, lstcon_rpc_t **crpc);
void lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans,
lstcon_trans_stat_t *stat);
int lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans,
- struct list_head *head_up,
+ struct list_head __user *head_up,
lstcon_rpc_readent_func_t readent);
void lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error);
void lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans);
static int
lstcon_sesrpc_readent(int transop, srpc_msg_t *msg,
- lstcon_rpc_ent_t *ent_up)
+ lstcon_rpc_ent_t __user *ent_up)
{
srpc_debug_reply_t *rep;
static int
lstcon_group_nodes_add(lstcon_group_t *grp,
- int count, lnet_process_id_t *ids_up,
- unsigned *featp, struct list_head *result_up)
+ int count, lnet_process_id_t __user *ids_up,
+ unsigned *featp, struct list_head __user *result_up)
{
lstcon_rpc_trans_t *trans;
lstcon_ndlink_t *ndl;
static int
lstcon_group_nodes_remove(lstcon_group_t *grp,
- int count, lnet_process_id_t *ids_up,
- struct list_head *result_up)
+ int count, lnet_process_id_t __user *ids_up,
+ struct list_head __user *result_up)
{
lstcon_rpc_trans_t *trans;
lstcon_ndlink_t *ndl;
}
int
-lstcon_nodes_add(char *name, int count, lnet_process_id_t *ids_up,
- unsigned *featp, struct list_head *result_up)
+lstcon_nodes_add(char *name, int count, lnet_process_id_t __user *ids_up,
+ unsigned *featp, struct list_head __user *result_up)
{
lstcon_group_t *grp;
int rc;
}
int
-lstcon_nodes_remove(char *name, int count,
- lnet_process_id_t *ids_up, struct list_head *result_up)
+lstcon_nodes_remove(char *name, int count, lnet_process_id_t __user *ids_up,
+ struct list_head __user *result_up)
{
lstcon_group_t *grp = NULL;
int rc;
}
int
-lstcon_group_refresh(char *name, struct list_head *result_up)
+lstcon_group_refresh(char *name, struct list_head __user *result_up)
{
lstcon_rpc_trans_t *trans;
lstcon_group_t *grp;
}
int
-lstcon_group_list(int index, int len, char *name_up)
+lstcon_group_list(int index, int len, char __user *name_up)
{
lstcon_group_t *grp;
static int
lstcon_nodes_getent(struct list_head *head, int *index_p,
- int *count_p, lstcon_node_ent_t *dents_up)
+ int *count_p, lstcon_node_ent_t __user *dents_up)
{
lstcon_ndlink_t *ndl;
lstcon_node_t *nd;
}
int
-lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p,
- int *index_p, int *count_p, lstcon_node_ent_t *dents_up)
+lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gents_p,
+ int *index_p, int *count_p,
+ lstcon_node_ent_t __user *dents_up)
{
lstcon_ndlist_ent_t *gentp;
lstcon_group_t *grp;
}
int
-lstcon_batch_list(int index, int len, char *name_up)
+lstcon_batch_list(int index, int len, char __user *name_up)
{
lstcon_batch_t *bat;
}
int
-lstcon_batch_info(char *name, lstcon_test_batch_ent_t *ent_up, int server,
- int testidx, int *index_p, int *ndent_p,
- lstcon_node_ent_t *dents_up)
+lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up,
+ int server, int testidx, int *index_p, int *ndent_p,
+ lstcon_node_ent_t __user *dents_up)
{
lstcon_test_batch_ent_t *entp;
struct list_head *clilst;
static int
lstcon_batch_op(lstcon_batch_t *bat, int transop,
- struct list_head *result_up)
+ struct list_head __user *result_up)
{
lstcon_rpc_trans_t *trans;
int rc;
}
int
-lstcon_batch_run(char *name, int timeout, struct list_head *result_up)
+lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up)
{
lstcon_batch_t *bat;
int rc;
}
int
-lstcon_batch_stop(char *name, int force, struct list_head *result_up)
+lstcon_batch_stop(char *name, int force, struct list_head __user *result_up)
{
lstcon_batch_t *bat;
int rc;
}
static int
-lstcon_test_nodes_add(lstcon_test_t *test, struct list_head *result_up)
+lstcon_test_nodes_add(lstcon_test_t *test, struct list_head __user *result_up)
{
lstcon_rpc_trans_t *trans;
lstcon_group_t *grp;
int concur, int dist, int span,
char *src_name, char *dst_name,
void *param, int paramlen, int *retp,
- struct list_head *result_up)
+ struct list_head __user *result_up)
{
lstcon_test_t *test = NULL;
int rc;
static int
lstcon_tsbrpc_readent(int transop, srpc_msg_t *msg,
- lstcon_rpc_ent_t *ent_up)
+ lstcon_rpc_ent_t __user *ent_up)
{
srpc_batch_reply_t *rep = &msg->msg_body.bat_reply;
int
lstcon_test_batch_query(char *name, int testidx, int client,
- int timeout, struct list_head *result_up)
+ int timeout, struct list_head __user *result_up)
{
lstcon_rpc_trans_t *trans;
struct list_head *translist;
static int
lstcon_statrpc_readent(int transop, srpc_msg_t *msg,
- lstcon_rpc_ent_t *ent_up)
+ lstcon_rpc_ent_t __user *ent_up)
{
srpc_stat_reply_t *rep = &msg->msg_body.stat_reply;
- sfw_counters_t *sfwk_stat;
- srpc_counters_t *srpc_stat;
- lnet_counters_t *lnet_stat;
+ sfw_counters_t __user *sfwk_stat;
+ srpc_counters_t __user *srpc_stat;
+ lnet_counters_t __user *lnet_stat;
if (rep->str_status != 0)
return 0;
- sfwk_stat = (sfw_counters_t *)&ent_up->rpe_payload[0];
- srpc_stat = (srpc_counters_t *)((char *)sfwk_stat + sizeof(*sfwk_stat));
- lnet_stat = (lnet_counters_t *)((char *)srpc_stat + sizeof(*srpc_stat));
+ sfwk_stat = (sfw_counters_t __user *)&ent_up->rpe_payload[0];
+ srpc_stat = (srpc_counters_t __user *)
+ ((char *)sfwk_stat + sizeof(*sfwk_stat));
+ lnet_stat = (lnet_counters_t __user *)
+ ((char *)srpc_stat + sizeof(*srpc_stat));
if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) ||
copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) ||
static int
lstcon_ndlist_stat(struct list_head *ndlist,
- int timeout, struct list_head *result_up)
+ int timeout, struct list_head __user *result_up)
{
struct list_head head;
lstcon_rpc_trans_t *trans;
}
int
-lstcon_group_stat(char *grp_name, int timeout, struct list_head *result_up)
+lstcon_group_stat(char *grp_name, int timeout,
+ struct list_head __user *result_up)
{
lstcon_group_t *grp;
int rc;
}
int
-lstcon_nodes_stat(int count, lnet_process_id_t *ids_up,
- int timeout, struct list_head *result_up)
+lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up,
+ int timeout, struct list_head __user *result_up)
{
lstcon_ndlink_t *ndl;
lstcon_group_t *tmp;
static int
lstcon_debug_ndlist(struct list_head *ndlist,
struct list_head *translist,
- int timeout, struct list_head *result_up)
+ int timeout, struct list_head __user *result_up)
{
lstcon_rpc_trans_t *trans;
int rc;
}
int
-lstcon_session_debug(int timeout, struct list_head *result_up)
+lstcon_session_debug(int timeout, struct list_head __user *result_up)
{
return lstcon_debug_ndlist(&console_session.ses_ndl_list,
NULL, timeout, result_up);
int
lstcon_batch_debug(int timeout, char *name,
- int client, struct list_head *result_up)
+ int client, struct list_head __user *result_up)
{
lstcon_batch_t *bat;
int rc;
int
lstcon_group_debug(int timeout, char *name,
- struct list_head *result_up)
+ struct list_head __user *result_up)
{
lstcon_group_t *grp;
int rc;
int
lstcon_nodes_debug(int timeout,
- int count, lnet_process_id_t *ids_up,
- struct list_head *result_up)
+ int count, lnet_process_id_t __user *ids_up,
+ struct list_head __user *result_up)
{
lnet_process_id_t id;
lstcon_ndlink_t *ndl;
int
lstcon_session_new(char *name, int key, unsigned feats,
- int timeout, int force, lst_sid_t *sid_up)
+ int timeout, int force, lst_sid_t __user *sid_up)
{
int rc = 0;
int i;
}
int
-lstcon_session_info(lst_sid_t *sid_up, int *key_up, unsigned *featp,
- lstcon_ndlist_ent_t *ndinfo_up, char *name_up, int len)
+lstcon_session_info(lst_sid_t __user *sid_up, int __user *key_up,
+ unsigned __user *featp,
+ lstcon_ndlist_ent_t __user *ndinfo_up,
+ char __user *name_up, int len)
{
lstcon_ndlist_ent_t *entp;
lstcon_ndlink_t *ndl;
int lstcon_console_fini(void);
int lstcon_session_match(lst_sid_t sid);
int lstcon_session_new(char *name, int key, unsigned version,
- int timeout, int flags, lst_sid_t *sid_up);
-int lstcon_session_info(lst_sid_t *sid_up, int *key, unsigned *verp,
- lstcon_ndlist_ent_t *entp, char *name_up, int len);
+ int timeout, int flags, lst_sid_t __user *sid_up);
+int lstcon_session_info(lst_sid_t __user *sid_up, int __user *key,
+ unsigned __user *verp, lstcon_ndlist_ent_t __user *entp,
+ char __user *name_up, int len);
int lstcon_session_end(void);
-int lstcon_session_debug(int timeout, struct list_head *result_up);
+int lstcon_session_debug(int timeout, struct list_head __user *result_up);
int lstcon_session_feats_check(unsigned feats);
int lstcon_batch_debug(int timeout, char *name,
- int client, struct list_head *result_up);
+ int client, struct list_head __user *result_up);
int lstcon_group_debug(int timeout, char *name,
- struct list_head *result_up);
-int lstcon_nodes_debug(int timeout, int nnd, lnet_process_id_t *nds_up,
- struct list_head *result_up);
+ struct list_head __user *result_up);
+int lstcon_nodes_debug(int timeout, int nnd, lnet_process_id_t __user *nds_up,
+ struct list_head __user *result_up);
int lstcon_group_add(char *name);
int lstcon_group_del(char *name);
int lstcon_group_clean(char *name, int args);
-int lstcon_group_refresh(char *name, struct list_head *result_up);
-int lstcon_nodes_add(char *name, int nnd, lnet_process_id_t *nds_up,
- unsigned *featp, struct list_head *result_up);
-int lstcon_nodes_remove(char *name, int nnd, lnet_process_id_t *nds_up,
- struct list_head *result_up);
-int lstcon_group_info(char *name, lstcon_ndlist_ent_t *gent_up,
- int *index_p, int *ndent_p, lstcon_node_ent_t *ndents_up);
-int lstcon_group_list(int idx, int len, char *name_up);
+int lstcon_group_refresh(char *name, struct list_head __user *result_up);
+int lstcon_nodes_add(char *name, int nnd, lnet_process_id_t __user *nds_up,
+ unsigned *featp, struct list_head __user *result_up);
+int lstcon_nodes_remove(char *name, int nnd, lnet_process_id_t __user *nds_up,
+ struct list_head __user *result_up);
+int lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gent_up,
+ int *index_p, int *ndent_p,
+ lstcon_node_ent_t __user *ndents_up);
+int lstcon_group_list(int idx, int len, char __user *name_up);
int lstcon_batch_add(char *name);
-int lstcon_batch_run(char *name, int timeout, struct list_head *result_up);
-int lstcon_batch_stop(char *name, int force, struct list_head *result_up);
+int lstcon_batch_run(char *name, int timeout,
+ struct list_head __user *result_up);
+int lstcon_batch_stop(char *name, int force,
+ struct list_head __user *result_up);
int lstcon_test_batch_query(char *name, int testidx,
int client, int timeout,
- struct list_head *result_up);
+ struct list_head __user *result_up);
int lstcon_batch_del(char *name);
-int lstcon_batch_list(int idx, int namelen, char *name_up);
-int lstcon_batch_info(char *name, lstcon_test_batch_ent_t *ent_up,
+int lstcon_batch_list(int idx, int namelen, char __user *name_up);
+int lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up,
int server, int testidx, int *index_p,
- int *ndent_p, lstcon_node_ent_t *dents_up);
+ int *ndent_p, lstcon_node_ent_t __user *dents_up);
int lstcon_group_stat(char *grp_name, int timeout,
- struct list_head *result_up);
-int lstcon_nodes_stat(int count, lnet_process_id_t *ids_up,
- int timeout, struct list_head *result_up);
+ struct list_head __user *result_up);
+int lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up,
+ int timeout, struct list_head __user *result_up);
int lstcon_test_add(char *batch_name, int type, int loop,
int concur, int dist, int span,
char *src_name, char *dst_name,
void *param, int paramlen, int *retp,
- struct list_head *result_up);
+ struct list_head __user *result_up);
#endif
rc = sscanf(kernbuf, "[%llx - %llx]\n",
(unsigned long long *)&tmp.lsr_start,
(unsigned long long *)&tmp.lsr_end);
+ if (rc != 2)
+ return -EINVAL;
if (!range_is_sane(&tmp) || range_is_zero(&tmp) ||
tmp.lsr_start < range->lsr_start || tmp.lsr_end > range->lsr_end)
return -EINVAL;
int *val);
int lprocfs_write_u64_helper(const char __user *buffer,
unsigned long count, __u64 *val);
-int lprocfs_write_frac_u64_helper(const char *buffer,
+int lprocfs_write_frac_u64_helper(const char __user *buffer,
unsigned long count,
__u64 *val, int mult);
char *lprocfs_find_named_value(const char *buffer, const char *name,
/**
* Mark this object has already been taken out of cache.
*/
- LU_OBJECT_UNHASHED = 1
+ LU_OBJECT_UNHASHED = 1,
};
enum lu_object_header_attr {
/**
* return device operations vector for this object
*/
-static const inline struct lu_device_operations *
+static inline const struct lu_device_operations *
lu_object_ops(const struct lu_object *o)
{
return o->lo_dev->ld_ops;
static inline void lustre_cfg_free(struct lustre_cfg *lcfg)
{
- int len;
-
- len = lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens);
-
kfree(lcfg);
return;
}
struct obd_export *class_conn2export(struct lustre_handle *conn);
+#define KKUC_CT_DATA_MAGIC 0x092013cea
+struct kkuc_ct_data {
+ __u32 kcd_magic;
+ struct obd_uuid kcd_uuid;
+ __u32 kcd_archive;
+};
+
/** @} export */
#endif /* __EXPORT_H */
--- /dev/null
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright (c) 2013 Intel Corporation.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ *
+ * Author: Nathan Rutman <nathan.rutman@sun.com>
+ *
+ * Kernel <-> userspace communication routines.
+ * The definitions below are used in the kernel and userspace.
+ */
+
+#ifndef __LUSTRE_KERNELCOMM_H__
+#define __LUSTRE_KERNELCOMM_H__
+
+/* For declarations shared with userspace */
+#include "uapi_kernelcomm.h"
+
+/* prototype for callback function on kuc groups */
+typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg);
+
+/* Kernel methods */
+int libcfs_kkuc_msg_put(struct file *fp, void *payload);
+int libcfs_kkuc_group_put(unsigned int group, void *payload);
+int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group,
+ void *data, size_t data_len);
+int libcfs_kkuc_group_rem(int uid, unsigned int group);
+int libcfs_kkuc_group_foreach(unsigned int group, libcfs_kkuc_cb_t cb_func,
+ void *cb_arg);
+
+#endif /* __LUSTRE_KERNELCOMM_H__ */
/* buffers the kernel will treat as user pointers */
__u32 ioc_plen1;
- char *ioc_pbuf1;
+ void __user *ioc_pbuf1;
__u32 ioc_plen2;
- char *ioc_pbuf2;
+ void __user *ioc_pbuf2;
/* inline buffers for various arguments */
__u32 ioc_inllen1;
#include "obd_support.h"
/* function defined in lustre/obdclass/<platform>/<platform>-module.c */
-int obd_ioctl_getdata(char **buf, int *len, void *arg);
-int obd_ioctl_popdata(void *arg, void *data, int len);
+int obd_ioctl_getdata(char **buf, int *len, void __user *arg);
+int obd_ioctl_popdata(void __user *arg, void *data, int len);
static inline void obd_ioctl_freedata(char *buf, int len)
{
/* OBD_IOC_LLOG_CATINFO is deprecated */
#define OBD_IOC_LLOG_CATINFO _IOWR('f', 196, OBD_IOC_DATA_TYPE)
-#define ECHO_IOC_GET_STRIPE _IOWR('f', 200, OBD_IOC_DATA_TYPE)
-#define ECHO_IOC_SET_STRIPE _IOWR('f', 201, OBD_IOC_DATA_TYPE)
-#define ECHO_IOC_ENQUEUE _IOWR('f', 202, OBD_IOC_DATA_TYPE)
-#define ECHO_IOC_CANCEL _IOWR('f', 203, OBD_IOC_DATA_TYPE)
+/* #define ECHO_IOC_GET_STRIPE _IOWR('f', 200, OBD_IOC_DATA_TYPE) */
+/* #define ECHO_IOC_SET_STRIPE _IOWR('f', 201, OBD_IOC_DATA_TYPE) */
+/* #define ECHO_IOC_ENQUEUE _IOWR('f', 202, OBD_IOC_DATA_TYPE) */
+/* #define ECHO_IOC_CANCEL _IOWR('f', 203, OBD_IOC_DATA_TYPE) */
#define OBD_IOC_GET_OBJ_VERSION _IOR('f', 210, OBD_IOC_DATA_TYPE)
spinlock_t ec_lock;
struct list_head ec_objects;
struct list_head ec_locks;
- int ec_nstripes;
__u64 ec_unique;
};
struct obd_ops {
struct module *owner;
int (*iocontrol)(unsigned int cmd, struct obd_export *exp, int len,
- void *karg, void *uarg);
+ void *karg, void __user *uarg);
int (*get_info)(const struct lu_env *env, struct obd_export *,
__u32 keylen, void *key, __u32 *vallen, void *val,
struct lov_stripe_md *lsm);
}
static inline int obd_iocontrol(unsigned int cmd, struct obd_export *exp,
- int len, void *karg, void *uarg)
+ int len, void *karg, void __user *uarg)
{
int rc;
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
*
* GPL HEADER END
*/
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2013, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
*
* Author: Nathan Rutman <nathan.rutman@sun.com>
*
- * libcfs/include/libcfs/libcfs_kernelcomm.h
- *
* Kernel <-> userspace communication routines.
* The definitions below are used in the kernel and userspace.
- *
*/
-#ifndef __LIBCFS_KERNELCOMM_H__
-#define __LIBCFS_KERNELCOMM_H__
+#ifndef __UAPI_KERNELCOMM_H__
+#define __UAPI_KERNELCOMM_H__
-#ifndef __LIBCFS_LIBCFS_H__
-#error Do not #include this file directly. #include <linux/libcfs/libcfs.h> instead
-#endif
+#include <linux/types.h>
/* KUC message header.
* All current and future KUC messages should use this header.
*/
struct kuc_hdr {
__u16 kuc_magic;
- __u8 kuc_transport; /* Each new Lustre feature should use a different
- transport */
+ /* Each new Lustre feature should use a different transport */
+ __u8 kuc_transport;
__u8 kuc_flags;
- __u16 kuc_msgtype; /* Message type or opcode, transport-specific */
- __u16 kuc_msglen; /* Including header */
+ /* Message type or opcode, transport-specific */
+ __u16 kuc_msgtype;
+ /* Including header */
+ __u16 kuc_msglen;
} __aligned(sizeof(__u64));
-#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE)
+#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr) + CR_MAXSIZE)
-#define KUC_MAGIC 0x191C /*Lustre9etLinC */
-#define KUC_FL_BLOCK 0x01 /* Wait for send */
+#define KUC_MAGIC 0x191C /*Lustre9etLinC */
/* kuc_msgtype values are defined in each transport */
enum kuc_transport_type {
- KUC_TRANSPORT_GENERIC = 1,
- KUC_TRANSPORT_HSM = 2,
- KUC_TRANSPORT_CHANGELOG = 3,
+ KUC_TRANSPORT_GENERIC = 1,
+ KUC_TRANSPORT_HSM = 2,
+ KUC_TRANSPORT_CHANGELOG = 3,
};
enum kuc_generic_message_type {
- KUC_MSG_SHUTDOWN = 1,
+ KUC_MSG_SHUTDOWN = 1,
};
-/* prototype for callback function on kuc groups */
-typedef int (*libcfs_kkuc_cb_t)(__u32 data, void *cb_arg);
-
/* KUC Broadcast Groups. This determines which userspace process hears which
* messages. Mutliple transports may be used within a group, or multiple
* groups may use the same transport. Broadcast
* groups need not be used if e.g. a UID is specified instead;
* use group 0 to signify unicast.
*/
-#define KUC_GRP_HSM 0x02
-#define KUC_GRP_MAX KUC_GRP_HSM
-
-/* Kernel methods */
-int libcfs_kkuc_msg_put(struct file *fp, void *payload);
-int libcfs_kkuc_group_put(int group, void *payload);
-int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group,
- __u32 data);
-int libcfs_kkuc_group_rem(int uid, int group);
-int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func,
- void *cb_arg);
+#define KUC_GRP_HSM 0x02
+#define KUC_GRP_MAX KUC_GRP_HSM
#define LK_FLG_STOP 0x01
+#define LK_NOFD -1U
/* kernelcomm control structure, passed from userspace to kernel */
-typedef struct lustre_kernelcomm {
+struct lustre_kernelcomm {
__u32 lk_wfd;
__u32 lk_rfd;
__u32 lk_uid;
__u32 lk_group;
__u32 lk_data;
__u32 lk_flags;
-} __packed lustre_kernelcomm;
-
-/* Userspace methods */
-int libcfs_ukuc_start(lustre_kernelcomm *l, int groups);
-int libcfs_ukuc_stop(lustre_kernelcomm *l);
-int libcfs_ukuc_msg_get(lustre_kernelcomm *l, char *buf, int maxsize,
- int transport);
+} __packed;
-#endif /* __LIBCFS_KERNELCOMM_H__ */
+#endif /* __UAPI_KERNELCOMM_H__ */
return cl2ccc(obj)->cob_inode;
}
-/**
- * Returns a pointer to cl_page associated with \a vmpage, without acquiring
- * additional reference to the resulting page. This is an unsafe version of
- * cl_vmpage_page() that can only be used under vmpage lock.
- */
-struct cl_page *ccc_vmpage_page_transient(struct page *vmpage)
-{
- KLASSERT(PageLocked(vmpage));
- return (struct cl_page *)vmpage->private;
-}
-
/**
* Initialize or update CLIO structures for regular files when new
* meta-data arrives from the server.
libcfs-linux-objs := $(addprefix linux/,$(libcfs-linux-objs))
libcfs-all-objs := debug.o fail.o module.o tracefile.o \
- libcfs_string.o hash.o kernel_user_comm.o \
- prng.o workitem.o libcfs_cpu.o \
- libcfs_mem.o libcfs_lock.o
+ libcfs_string.o hash.o prng.o workitem.o \
+ libcfs_cpu.o libcfs_mem.o libcfs_lock.o
libcfs-objs := $(libcfs-linux-objs) $(libcfs-all-objs)
return "lquota";
case S_OSD:
return "osd";
+ case S_LFSCK:
+ return "lfsck";
case S_LMV:
return "lmv";
case S_SEC:
LIBCFS_ALLOC(cptab, sizeof(*cptab));
if (cptab != NULL) {
cptab->ctb_version = CFS_CPU_VERSION_MAGIC;
+ node_set(0, cptab->ctb_nodemask);
cptab->ctb_nparts = ncpt;
}
}
EXPORT_SYMBOL(cfs_cpt_online);
+nodemask_t *
+cfs_cpt_nodemask(struct cfs_cpt_table *cptab, int cpt)
+{
+ return &cptab->ctb_nodemask;
+}
+EXPORT_SYMBOL(cfs_cpt_cpumask);
+
int
cfs_cpt_set_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu)
{
*/
void
cfs_percpt_lock(struct cfs_percpt_lock *pcl, int index)
+ __acquires(pcl->pcl_locks)
{
int ncpt = cfs_cpt_number(pcl->pcl_cptab);
int i;
/** unlock a CPU partition */
void
cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index)
+ __releases(pcl->pcl_locks)
{
int ncpt = cfs_cpt_number(pcl->pcl_cptab);
int i;
#define LNET_MINOR 240
-int libcfs_ioctl_getdata(char *buf, char *end, void *arg)
+int libcfs_ioctl_getdata(char *buf, char *end, void __user *arg)
{
struct libcfs_ioctl_hdr *hdr;
struct libcfs_ioctl_data *data;
return 0;
}
-int libcfs_ioctl_popdata(void *arg, void *data, int size)
+int libcfs_ioctl_popdata(void __user *arg, void *data, int size)
{
- if (copy_to_user((char *)arg, data, size))
+ if (copy_to_user(arg, data, size))
return -EFAULT;
return 0;
}
static int
libcfs_psdev_open(struct inode *inode, struct file *file)
{
- struct libcfs_device_userstate **pdu = NULL;
int rc = 0;
if (!inode)
return -EINVAL;
- pdu = (struct libcfs_device_userstate **)&file->private_data;
if (libcfs_psdev_ops.p_open != NULL)
- rc = libcfs_psdev_ops.p_open(0, (void *)pdu);
+ rc = libcfs_psdev_ops.p_open(0, NULL);
else
return -EPERM;
return rc;
static int
libcfs_psdev_release(struct inode *inode, struct file *file)
{
- struct libcfs_device_userstate *pdu;
int rc = 0;
if (!inode)
return -EINVAL;
- pdu = file->private_data;
if (libcfs_psdev_ops.p_close != NULL)
- rc = libcfs_psdev_ops.p_close(0, (void *)pdu);
+ rc = libcfs_psdev_ops.p_close(0, NULL);
else
rc = -EPERM;
return rc;
return -EPERM;
panic("debugctl-invoked panic");
return 0;
- case IOC_LIBCFS_MEMHOG:
- if (!capable(CFS_CAP_SYS_ADMIN))
- return -EPERM;
- /* go thought */
}
- pfile.off = 0;
- pfile.private_data = file->private_data;
if (libcfs_psdev_ops.p_ioctl != NULL)
- rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void *)arg);
+ rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void __user *)arg);
else
rc = -EPERM;
return rc;
static struct dentry *lnet_debugfs_root;
-static void kportal_memhog_free(struct libcfs_device_userstate *ldu)
-{
- struct page **level0p = &ldu->ldu_memhog_root_page;
- struct page **level1p;
- struct page **level2p;
- int count1;
- int count2;
-
- if (*level0p != NULL) {
-
- level1p = (struct page **)page_address(*level0p);
- count1 = 0;
-
- while (count1 < PAGE_CACHE_SIZE/sizeof(struct page *) &&
- *level1p != NULL) {
-
- level2p = (struct page **)page_address(*level1p);
- count2 = 0;
-
- while (count2 < PAGE_CACHE_SIZE/sizeof(struct page *) &&
- *level2p != NULL) {
-
- __free_page(*level2p);
- ldu->ldu_memhog_pages--;
- level2p++;
- count2++;
- }
-
- __free_page(*level1p);
- ldu->ldu_memhog_pages--;
- level1p++;
- count1++;
- }
-
- __free_page(*level0p);
- ldu->ldu_memhog_pages--;
-
- *level0p = NULL;
- }
-
- LASSERT(ldu->ldu_memhog_pages == 0);
-}
-
-static int kportal_memhog_alloc(struct libcfs_device_userstate *ldu, int npages,
- gfp_t flags)
-{
- struct page **level0p;
- struct page **level1p;
- struct page **level2p;
- int count1;
- int count2;
-
- LASSERT(ldu->ldu_memhog_pages == 0);
- LASSERT(ldu->ldu_memhog_root_page == NULL);
-
- if (npages < 0)
- return -EINVAL;
-
- if (npages == 0)
- return 0;
-
- level0p = &ldu->ldu_memhog_root_page;
- *level0p = alloc_page(flags);
- if (*level0p == NULL)
- return -ENOMEM;
- ldu->ldu_memhog_pages++;
-
- level1p = (struct page **)page_address(*level0p);
- count1 = 0;
- memset(level1p, 0, PAGE_CACHE_SIZE);
-
- while (ldu->ldu_memhog_pages < npages &&
- count1 < PAGE_CACHE_SIZE/sizeof(struct page *)) {
-
- if (cfs_signal_pending())
- return -EINTR;
-
- *level1p = alloc_page(flags);
- if (*level1p == NULL)
- return -ENOMEM;
- ldu->ldu_memhog_pages++;
-
- level2p = (struct page **)page_address(*level1p);
- count2 = 0;
- memset(level2p, 0, PAGE_CACHE_SIZE);
-
- while (ldu->ldu_memhog_pages < npages &&
- count2 < PAGE_CACHE_SIZE/sizeof(struct page *)) {
-
- if (cfs_signal_pending())
- return -EINTR;
-
- *level2p = alloc_page(flags);
- if (*level2p == NULL)
- return -ENOMEM;
- ldu->ldu_memhog_pages++;
-
- level2p++;
- count2++;
- }
-
- level1p++;
- count1++;
- }
-
- return 0;
-}
-
/* called when opening /dev/device */
static int libcfs_psdev_open(unsigned long flags, void *args)
{
- struct libcfs_device_userstate *ldu;
-
try_module_get(THIS_MODULE);
-
- LIBCFS_ALLOC(ldu, sizeof(*ldu));
- if (ldu != NULL) {
- ldu->ldu_memhog_pages = 0;
- ldu->ldu_memhog_root_page = NULL;
- }
- *(struct libcfs_device_userstate **)args = ldu;
-
return 0;
}
/* called when closing /dev/device */
static int libcfs_psdev_release(unsigned long flags, void *args)
{
- struct libcfs_device_userstate *ldu;
-
- ldu = (struct libcfs_device_userstate *)args;
- if (ldu != NULL) {
- kportal_memhog_free(ldu);
- LIBCFS_FREE(ldu, sizeof(*ldu));
- }
-
module_put(THIS_MODULE);
return 0;
}
EXPORT_SYMBOL(libcfs_deregister_ioctl);
static int libcfs_ioctl_int(struct cfs_psdev_file *pfile, unsigned long cmd,
- void *arg, struct libcfs_ioctl_data *data)
+ void __user *arg, struct libcfs_ioctl_data *data)
{
int err = -EINVAL;
return -EINVAL;
libcfs_debug_mark_buffer(data->ioc_inlbuf1);
return 0;
- case IOC_LIBCFS_MEMHOG:
- if (pfile->private_data == NULL) {
- err = -EINVAL;
- } else {
- kportal_memhog_free(pfile->private_data);
- /* XXX The ioc_flags is not GFP flags now, need to be fixed */
- err = kportal_memhog_alloc(pfile->private_data,
- data->ioc_count,
- data->ioc_flags);
- if (err != 0)
- kportal_memhog_free(pfile->private_data);
- }
- break;
default: {
struct libcfs_ioctl_handler *hand;
return err;
}
-static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *arg)
+static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd,
+ void __user *arg)
{
char *buf;
struct libcfs_ioctl_data *data;
return error;
}
-static const struct file_operations lnet_debugfs_file_operations = {
+static const struct file_operations lnet_debugfs_file_operations_rw = {
.open = simple_open,
.read = lnet_debugfs_read,
.write = lnet_debugfs_write,
.llseek = default_llseek,
};
+static const struct file_operations lnet_debugfs_file_operations_ro = {
+ .open = simple_open,
+ .read = lnet_debugfs_read,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations lnet_debugfs_file_operations_wo = {
+ .open = simple_open,
+ .write = lnet_debugfs_write,
+ .llseek = default_llseek,
+};
+
+static const struct file_operations *lnet_debugfs_fops_select(umode_t mode)
+{
+ if (!(mode & S_IWUGO))
+ return &lnet_debugfs_file_operations_ro;
+
+ if (!(mode & S_IRUGO))
+ return &lnet_debugfs_file_operations_wo;
+
+ return &lnet_debugfs_file_operations_rw;
+}
+
void lustre_insert_debugfs(struct ctl_table *table,
const struct lnet_debugfs_symlink_def *symlinks)
{
- struct dentry *entry;
-
if (lnet_debugfs_root == NULL)
lnet_debugfs_root = debugfs_create_dir("lnet", NULL);
if (IS_ERR_OR_NULL(lnet_debugfs_root))
return;
+ /* We don't save the dentry returned in next two calls, because
+ * we don't call debugfs_remove() but rather remove_recursive()
+ */
for (; table->procname; table++)
- entry = debugfs_create_file(table->procname, table->mode,
- lnet_debugfs_root, table,
- &lnet_debugfs_file_operations);
+ debugfs_create_file(table->procname, table->mode,
+ lnet_debugfs_root, table,
+ lnet_debugfs_fops_select(table->mode));
for (; symlinks && symlinks->name; symlinks++)
- entry = debugfs_create_symlink(symlinks->name,
- lnet_debugfs_root,
- symlinks->target);
+ debugfs_create_symlink(symlinks->name, lnet_debugfs_root,
+ symlinks->target);
}
EXPORT_SYMBOL_GPL(lustre_insert_debugfs);
LASSERT(de != NULL);
lld = ll_d2d(de);
- if (lld == NULL) /* NFS copies the de->d_op methods (bug 4655) */
+ if (!lld) /* NFS copies the de->d_op methods (bug 4655) */
return;
if (lld->lld_it) {
return rc;
lsm = ccc_inode_lsm_get(inode);
- if (lsm == NULL)
+ if (!lsm)
return rc;
rc = obd_find_cbdata(sbi->ll_dt_exp, lsm, return_if_equal, NULL);
de, de, de->d_parent, d_inode(de),
d_count(de));
- if (de->d_fsdata == NULL) {
+ if (!de->d_fsdata) {
struct ll_dentry_data *lld;
lld = kzalloc(sizeof(*lld), GFP_NOFS);
if (likely(lld)) {
spin_lock(&de->d_lock);
- if (likely(de->d_fsdata == NULL)) {
+ if (likely(!de->d_fsdata)) {
de->d_fsdata = lld;
__d_lustre_invalidate(de);
} else {
if (lookup_flags & LOOKUP_RCU)
return -ECHILD;
- do_statahead_enter(dir, &dentry, d_inode(dentry) == NULL);
+ do_statahead_enter(dir, &dentry, !d_inode(dentry));
ll_statahead_mark(dir, dentry);
return 1;
}
#include "../include/lustre_lite.h"
#include "../include/lustre_dlm.h"
#include "../include/lustre_fid.h"
+#include "../include/lustre_kernelcomm.h"
#include "llite_internal.h"
/*
return ll_iocontrol(inode, file, cmd, arg);
case FSFILT_IOC_GETVERSION_OLD:
case FSFILT_IOC_GETVERSION:
- return put_user(inode->i_generation, (int *)arg);
+ return put_user(inode->i_generation, (int __user *)arg);
/* We need to special case any other ioctls we want to handle,
* to send them to the MDS/OST as appropriate and to properly
* network encode the arg field.
if (mdtidx < 0)
return mdtidx;
- if (put_user((int)mdtidx, (int *)arg))
+ if (put_user((int)mdtidx, (int __user *)arg))
return -EFAULT;
return 0;
char *filename;
struct md_op_data *op_data;
- rc = obd_ioctl_getdata(&buf, &len, (void *)arg);
+ rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg);
if (rc)
return rc;
data = (void *)buf;
int len;
int rc;
- rc = obd_ioctl_getdata(&buf, &len, (void *)arg);
+ rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg);
if (rc)
return rc;
case LL_IOC_LOV_SETSTRIPE: {
struct lov_user_md_v3 lumv3;
struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3;
- struct lov_user_md_v1 *lumv1p = (struct lov_user_md_v1 *)arg;
- struct lov_user_md_v3 *lumv3p = (struct lov_user_md_v3 *)arg;
+ struct lov_user_md_v1 __user *lumv1p = (void __user *)arg;
+ struct lov_user_md_v3 __user *lumv3p = (void __user *)arg;
int set_default = 0;
return rc;
}
case LL_IOC_LMV_GETSTRIPE: {
- struct lmv_user_md *lump = (struct lmv_user_md *)arg;
+ struct lmv_user_md __user *lump = (void __user *)arg;
struct lmv_user_md lum;
struct lmv_user_md *tmp;
int lum_size;
tmp->lum_objects[0].lum_mds = mdtindex;
memcpy(&tmp->lum_objects[0].lum_fid, ll_inode2fid(inode),
sizeof(struct lu_fid));
- if (copy_to_user((void *)arg, tmp, lum_size)) {
+ if (copy_to_user((void __user *)arg, tmp, lum_size)) {
rc = -EFAULT;
goto free_lmv;
}
case LL_IOC_LOV_SWAP_LAYOUTS:
return -EPERM;
case LL_IOC_OBD_STATFS:
- return ll_obd_statfs(inode, (void *)arg);
+ return ll_obd_statfs(inode, (void __user *)arg);
case LL_IOC_LOV_GETSTRIPE:
case LL_IOC_MDC_GETINFO:
case IOC_MDC_GETFILEINFO:
case IOC_MDC_GETFILESTRIPE: {
struct ptlrpc_request *request = NULL;
- struct lov_user_md *lump;
+ struct lov_user_md __user *lump;
struct lov_mds_md *lmm = NULL;
struct mdt_body *body;
char *filename = NULL;
if (cmd == IOC_MDC_GETFILEINFO ||
cmd == IOC_MDC_GETFILESTRIPE) {
- filename = ll_getname((const char *)arg);
+ filename = ll_getname((const char __user *)arg);
if (IS_ERR(filename))
return PTR_ERR(filename);
if (cmd == IOC_MDC_GETFILESTRIPE ||
cmd == LL_IOC_LOV_GETSTRIPE) {
- lump = (struct lov_user_md *)arg;
+ lump = (struct lov_user_md __user *)arg;
} else {
- struct lov_user_mds_data *lmdp;
+ struct lov_user_mds_data __user *lmdp;
- lmdp = (struct lov_user_mds_data *)arg;
+ lmdp = (struct lov_user_mds_data __user *)arg;
lump = &lmdp->lmd_lmm;
}
if (copy_to_user(lump, lmm, lmmsize)) {
}
skip_lmm:
if (cmd == IOC_MDC_GETFILEINFO || cmd == LL_IOC_MDC_GETINFO) {
- struct lov_user_mds_data *lmdp;
+ struct lov_user_mds_data __user *lmdp;
lstat_t st = { 0 };
st.st_dev = inode->i_sb->s_dev;
st.st_ctime = body->ctime;
st.st_ino = inode->i_ino;
- lmdp = (struct lov_user_mds_data *)arg;
+ lmdp = (struct lov_user_mds_data __user *)arg;
if (copy_to_user(&lmdp->lmd_st, &st, sizeof(st))) {
rc = -EFAULT;
goto out_req;
return rc;
}
case IOC_LOV_GETINFO: {
- struct lov_user_mds_data *lumd;
+ struct lov_user_mds_data __user *lumd;
struct lov_stripe_md *lsm;
- struct lov_user_md *lum;
+ struct lov_user_md __user *lum;
struct lov_mds_md *lmm;
int lmmsize;
lstat_t st;
- lumd = (struct lov_user_mds_data *)arg;
+ lumd = (struct lov_user_mds_data __user *)arg;
lum = &lumd->lmd_lmm;
rc = ll_get_max_mdsize(sbi, &lmmsize);
NULL);
if (rc) {
CDEBUG(D_QUOTA, "mdc ioctl %d failed: %d\n", cmd, rc);
- if (copy_to_user((void *)arg, check,
- sizeof(*check)))
+ if (copy_to_user((void __user *)arg, check,
+ sizeof(*check)))
CDEBUG(D_QUOTA, "copy_to_user failed\n");
goto out_poll;
}
NULL);
if (rc) {
CDEBUG(D_QUOTA, "osc ioctl %d failed: %d\n", cmd, rc);
- if (copy_to_user((void *)arg, check,
- sizeof(*check)))
+ if (copy_to_user((void __user *)arg, check,
+ sizeof(*check)))
CDEBUG(D_QUOTA, "copy_to_user failed\n");
goto out_poll;
}
if (!qctl)
return -ENOMEM;
- if (copy_from_user(qctl, (void *)arg, sizeof(*qctl))) {
+ if (copy_from_user(qctl, (void __user *)arg, sizeof(*qctl))) {
rc = -EFAULT;
goto out_quotactl;
}
rc = quotactl_ioctl(sbi, qctl);
- if (rc == 0 && copy_to_user((void *)arg, qctl, sizeof(*qctl)))
+ if (rc == 0 && copy_to_user((void __user *)arg, qctl,
+ sizeof(*qctl)))
rc = -EFAULT;
out_quotactl:
int count, vallen;
struct obd_export *exp;
- if (copy_from_user(&count, (int *)arg, sizeof(int)))
+ if (copy_from_user(&count, (int __user *)arg, sizeof(int)))
return -EFAULT;
/* get ost count when count is zero, get mdt count otherwise */
return rc;
}
- if (copy_to_user((int *)arg, &count, sizeof(int)))
+ if (copy_to_user((int __user *)arg, &count, sizeof(int)))
return -EFAULT;
return 0;
}
case LL_IOC_PATH2FID:
- if (copy_to_user((void *)arg, ll_inode2fid(inode),
- sizeof(struct lu_fid)))
+ if (copy_to_user((void __user *)arg, ll_inode2fid(inode),
+ sizeof(struct lu_fid)))
return -EFAULT;
return 0;
case LL_IOC_GET_CONNECT_FLAGS: {
- return obd_iocontrol(cmd, sbi->ll_md_exp, 0, NULL, (void *)arg);
+ return obd_iocontrol(cmd, sbi->ll_md_exp, 0, NULL,
+ (void __user *)arg);
}
case OBD_IOC_CHANGELOG_SEND:
case OBD_IOC_CHANGELOG_CLEAR:
if (!capable(CFS_CAP_SYS_ADMIN))
return -EPERM;
- rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void *)arg,
+ rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void __user *)arg,
sizeof(struct ioc_changelog));
return rc;
case OBD_IOC_FID2PATH:
- return ll_fid2path(inode, (void *)arg);
+ return ll_fid2path(inode, (void __user *)arg);
case LL_IOC_HSM_REQUEST: {
struct hsm_user_request *hur;
ssize_t totalsize;
- hur = memdup_user((void *)arg, sizeof(*hur));
+ hur = memdup_user((void __user *)arg, sizeof(*hur));
if (IS_ERR(hur))
return PTR_ERR(hur);
return -ENOMEM;
/* Copy the whole struct */
- if (copy_from_user(hur, (void *)arg, totalsize)) {
+ if (copy_from_user(hur, (void __user *)arg, totalsize)) {
kvfree(hur);
return -EFAULT;
}
struct hsm_progress_kernel hpk;
struct hsm_progress hp;
- if (copy_from_user(&hp, (void *)arg, sizeof(hp)))
+ if (copy_from_user(&hp, (void __user *)arg, sizeof(hp)))
return -EFAULT;
hpk.hpk_fid = hp.hp_fid;
return rc;
}
case LL_IOC_HSM_CT_START:
- rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void *)arg,
+ rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void __user *)arg,
sizeof(struct lustre_kernelcomm));
return rc;
struct hsm_copy *copy;
int rc;
- copy = memdup_user((char *)arg, sizeof(*copy));
+ copy = memdup_user((char __user *)arg, sizeof(*copy));
if (IS_ERR(copy))
return PTR_ERR(copy);
rc = ll_ioc_copy_start(inode->i_sb, copy);
- if (copy_to_user((char *)arg, copy, sizeof(*copy)))
+ if (copy_to_user((char __user *)arg, copy, sizeof(*copy)))
rc = -EFAULT;
kfree(copy);
struct hsm_copy *copy;
int rc;
- copy = memdup_user((char *)arg, sizeof(*copy));
+ copy = memdup_user((char __user *)arg, sizeof(*copy));
if (IS_ERR(copy))
return PTR_ERR(copy);
rc = ll_ioc_copy_end(inode->i_sb, copy);
- if (copy_to_user((char *)arg, copy, sizeof(*copy)))
+ if (copy_to_user((char __user *)arg, copy, sizeof(*copy)))
rc = -EFAULT;
kfree(copy);
return rc;
}
default:
- return obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL, (void *)arg);
+ return obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL,
+ (void __user *)arg);
}
}
if (!capable(CFS_CAP_SYS_ADMIN))
return -EPERM;
- if (copy_from_user(&ucreat, (struct ll_recreate_obj *)arg,
+ if (copy_from_user(&ucreat, (struct ll_recreate_obj __user *)arg,
sizeof(ucreat)))
return -EFAULT;
if (!capable(CFS_CAP_SYS_ADMIN))
return -EPERM;
- if (copy_from_user(&fid, (struct lu_fid *)arg, sizeof(fid)))
+ if (copy_from_user(&fid, (struct lu_fid __user *)arg, sizeof(fid)))
return -EFAULT;
fid_to_ostid(&fid, &oi);
if (lump == NULL)
return -ENOMEM;
- if (copy_from_user(lump, (struct lov_user_md *)arg, lum_size)) {
+ if (copy_from_user(lump, (struct lov_user_md __user *)arg, lum_size)) {
kvfree(lump);
return -EFAULT;
}
static int ll_lov_setstripe(struct inode *inode, struct file *file,
unsigned long arg)
{
- struct lov_user_md_v3 lumv3;
- struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3;
- struct lov_user_md_v1 *lumv1p = (struct lov_user_md_v1 *)arg;
- struct lov_user_md_v3 *lumv3p = (struct lov_user_md_v3 *)arg;
- int lum_size, rc;
- int flags = FMODE_WRITE;
+ struct lov_user_md_v3 lumv3;
+ struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3;
+ struct lov_user_md_v1 __user *lumv1p = (void __user *)arg;
+ struct lov_user_md_v3 __user *lumv3p = (void __user *)arg;
+ int lum_size, rc;
+ int flags = FMODE_WRITE;
/* first try with v1 which is smaller than v3 */
lum_size = sizeof(struct lov_user_md_v1);
ll_layout_refresh(inode, &gen);
lsm = ccc_inode_lsm_get(inode);
rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode),
- 0, lsm, (void *)arg);
+ 0, lsm, (void __user *)arg);
ccc_inode_lsm_put(inode, lsm);
}
return rc;
lsm = ccc_inode_lsm_get(inode);
if (lsm != NULL)
rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), 0,
- lsm, (void *)arg);
+ lsm, (void __user *)arg);
ccc_inode_lsm_put(inode, lsm);
return rc;
}
ret_bytes += (fiemap_s->fm_mapped_extents *
sizeof(struct ll_fiemap_extent));
- if (copy_to_user((void *)arg, fiemap_s, ret_bytes))
+ if (copy_to_user((void __user *)arg, fiemap_s, ret_bytes))
rc = -EFAULT;
error:
switch (cmd) {
case LL_IOC_GETFLAGS:
/* Get the current value of the file flags */
- return put_user(fd->fd_flags, (int *)arg);
+ return put_user(fd->fd_flags, (int __user *)arg);
case LL_IOC_SETFLAGS:
case LL_IOC_CLRFLAGS:
/* Set or clear specific file flags */
/* XXX This probably needs checks to ensure the flags are
* not abused, and to handle any flag side effects.
*/
- if (get_user(flags, (int *) arg))
+ if (get_user(flags, (int __user *)arg))
return -EFAULT;
if (cmd == LL_IOC_SETFLAGS) {
struct file *file2;
struct lustre_swap_layouts lsl;
- if (copy_from_user(&lsl, (char *)arg,
- sizeof(struct lustre_swap_layouts)))
+ if (copy_from_user(&lsl, (char __user *)arg,
+ sizeof(struct lustre_swap_layouts)))
return -EFAULT;
if ((file->f_flags & O_ACCMODE) == 0) /* O_RDONLY */
return ll_iocontrol(inode, file, cmd, arg);
case FSFILT_IOC_GETVERSION_OLD:
case FSFILT_IOC_GETVERSION:
- return put_user(inode->i_generation, (int *)arg);
+ return put_user(inode->i_generation, (int __user *)arg);
case LL_IOC_GROUP_LOCK:
return ll_get_grouplock(inode, file, arg);
case LL_IOC_GROUP_UNLOCK:
return ll_put_grouplock(inode, file, arg);
case IOC_OBD_STATFS:
- return ll_obd_statfs(inode, (void *)arg);
+ return ll_obd_statfs(inode, (void __user *)arg);
/* We need to special case any other ioctls we want to handle,
* to send them to the MDS/OST as appropriate and to properly
case LL_IOC_FLUSHCTX:
return ll_flush_ctx(inode);
case LL_IOC_PATH2FID: {
- if (copy_to_user((void *)arg, ll_inode2fid(inode),
+ if (copy_to_user((void __user *)arg, ll_inode2fid(inode),
sizeof(struct lu_fid)))
return -EFAULT;
return 0;
}
case OBD_IOC_FID2PATH:
- return ll_fid2path(inode, (void *)arg);
+ return ll_fid2path(inode, (void __user *)arg);
case LL_IOC_DATA_VERSION: {
struct ioc_data_version idv;
int rc;
- if (copy_from_user(&idv, (char *)arg, sizeof(idv)))
+ if (copy_from_user(&idv, (char __user *)arg, sizeof(idv)))
return -EFAULT;
rc = ll_data_version(inode, &idv.idv_version,
!(idv.idv_flags & LL_DV_NOFLUSH));
- if (rc == 0 && copy_to_user((char *) arg, &idv, sizeof(idv)))
+ if (rc == 0 && copy_to_user((char __user *)arg, &idv,
+ sizeof(idv)))
return -EFAULT;
return rc;
if (mdtidx < 0)
return mdtidx;
- if (put_user((int)mdtidx, (int *)arg))
+ if (put_user(mdtidx, (int __user *)arg))
return -EFAULT;
return 0;
rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data),
op_data, NULL);
- if (copy_to_user((void *)arg, hus, sizeof(*hus)))
+ if (copy_to_user((void __user *)arg, hus, sizeof(*hus)))
rc = -EFAULT;
ll_finish_md_op_data(op_data);
struct hsm_state_set *hss;
int rc;
- hss = memdup_user((char *)arg, sizeof(*hss));
+ hss = memdup_user((char __user *)arg, sizeof(*hss));
if (IS_ERR(hss))
return PTR_ERR(hss);
rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data),
op_data, NULL);
- if (copy_to_user((char *)arg, hca, sizeof(*hca)))
+ if (copy_to_user((char __user *)arg, hca, sizeof(*hca)))
rc = -EFAULT;
ll_finish_md_op_data(op_data);
case LL_IOC_HSM_IMPORT: {
struct hsm_user_import *hui;
- hui = memdup_user((void *)arg, sizeof(*hui));
+ hui = memdup_user((void __user *)arg, sizeof(*hui));
if (IS_ERR(hui))
return PTR_ERR(hui);
return err;
return obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL,
- (void *)arg);
+ (void __user *)arg);
}
}
}
fiemap->fm_extent_count = fieinfo->fi_extents_max;
fiemap->fm_start = start;
fiemap->fm_length = len;
- if (extent_count > 0)
- memcpy(&fiemap->fm_extents[0], fieinfo->fi_extents_start,
- sizeof(struct ll_fiemap_extent));
+ if (extent_count > 0 &&
+ copy_from_user(&fiemap->fm_extents[0], fieinfo->fi_extents_start,
+ sizeof(struct ll_fiemap_extent)) != 0) {
+ rc = -EFAULT;
+ goto out;
+ }
rc = ll_do_fiemap(inode, fiemap, num_bytes);
fieinfo->fi_flags = fiemap->fm_flags;
fieinfo->fi_extents_mapped = fiemap->fm_mapped_extents;
- if (extent_count > 0)
- memcpy(fieinfo->fi_extents_start, &fiemap->fm_extents[0],
- fiemap->fm_mapped_extents *
- sizeof(struct ll_fiemap_extent));
+ if (extent_count > 0 &&
+ copy_to_user(fieinfo->fi_extents_start, &fiemap->fm_extents[0],
+ fiemap->fm_mapped_extents *
+ sizeof(struct ll_fiemap_extent)) != 0) {
+ rc = -EFAULT;
+ goto out;
+ }
+out:
kvfree(fiemap);
return rc;
}
void ll_dirty_page_discard_warn(struct page *page, int ioret);
int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req,
struct super_block *, struct lookup_intent *);
-int ll_obd_statfs(struct inode *inode, void *arg);
+int ll_obd_statfs(struct inode *inode, void __user *arg);
int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize);
int ll_get_default_mdsize(struct ll_sb_info *sbi, int *default_mdsize);
int ll_process_config(struct lustre_cfg *lcfg);
void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req);
/* llite/llite_nfs.c */
-extern struct export_operations lustre_export_operations;
+extern const struct export_operations lustre_export_operations;
__u32 get_uuid2int(const char *name, int len);
void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid);
struct inode *search_inode_for_lustre(struct super_block *sb,
ptlrpc_req_finished(req);
- return put_user(flags, (int *)arg);
+ return put_user(flags, (int __user *)arg);
}
case FSFILT_IOC_SETFLAGS: {
struct lov_stripe_md *lsm;
struct obd_info oinfo = { };
struct md_op_data *op_data;
- if (get_user(flags, (int *)arg))
+ if (get_user(flags, (int __user *)arg))
return -EFAULT;
op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
return rc;
}
-int ll_obd_statfs(struct inode *inode, void *arg)
+int ll_obd_statfs(struct inode *inode, void __user *arg)
{
struct ll_sb_info *sbi = NULL;
struct obd_export *exp;
char *buf = NULL;
struct obd_ioctl_data *data = NULL;
__u32 type;
- __u32 flags;
int len = 0, rc;
if (!inode) {
goto out_statfs;
}
- flags = (type & LL_STATFS_NODELAY) ? OBD_STATFS_NODELAY : 0;
- rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, buf, &flags);
+ rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, buf, NULL);
if (rc)
goto out_statfs;
out_statfs:
if (!obd)
return -ENOENT;
- if (copy_to_user((void *)arg, obd->obd_name,
- strlen(obd->obd_name) + 1))
+ if (copy_to_user((void __user *)arg, obd->obd_name,
+ strlen(obd->obd_name) + 1))
return -EFAULT;
return 0;
return result;
}
-struct export_operations lustre_export_operations = {
+const struct export_operations lustre_export_operations = {
.get_parent = ll_get_parent,
.encode_fh = ll_encode_fh,
.get_name = ll_get_name,
else
fid_zero(&fid);
- if (copy_to_user((struct lu_fid *)arg, &fid, sizeof(fid)))
+ if (copy_to_user((void __user *)arg, &fid, sizeof(fid)))
err = -EFAULT;
break;
}
dev = MKDEV(lloop_major, lo->lo_number);
/* quit if the used pointer is writable */
- if (put_user((long)old_encode_dev(dev), (long *)arg)) {
+ if (put_user((long)old_encode_dev(dev), (long __user *)arg)) {
err = -EFAULT;
goto out;
}
ret = ll_read_ahead_pages(env, io, queue,
ria, &reserved, mapping, &ra_end);
- LASSERTF(reserved >= 0, "reserved %lu\n", reserved);
if (reserved != 0)
ll_ra_count_put(ll_i2sbi(inode), reserved);
#include "../include/lprocfs_status.h"
#include "../include/lustre_lite.h"
#include "../include/lustre_fid.h"
+#include "../include/lustre_kernelcomm.h"
#include "lmv_internal.h"
static void lmv_activate_target(struct lmv_obd *lmv,
return rc;
}
-static int lmv_fid2path(struct obd_export *exp, int len, void *karg, void *uarg)
+static int lmv_fid2path(struct obd_export *exp, int len, void *karg,
+ void __user *uarg)
{
struct obd_device *obddev = class_exp2obd(exp);
struct lmv_obd *lmv = &obddev->u.lmv;
}
static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len,
- struct lustre_kernelcomm *lk, void *uarg)
+ struct lustre_kernelcomm *lk,
+ void __user *uarg)
{
- int i, rc = 0;
+ int rc = 0;
+ __u32 i;
/* unregister request (call from llapi_hsm_copytool_fini) */
for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
* and will unregister automatically.
*/
rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group);
+
return rc;
}
static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len,
- struct lustre_kernelcomm *lk, void *uarg)
+ struct lustre_kernelcomm *lk, void __user *uarg)
{
- struct file *filp;
- int i, j, err;
- int rc = 0;
- bool any_set = false;
+ struct file *filp;
+ __u32 i, j;
+ int err, rc = 0;
+ bool any_set = false;
+ struct kkuc_ct_data kcd = { 0 };
/* All or nothing: try to register to all MDS.
* In case of failure, unregister from previous MDS,
/* at least one registration done, with no failure */
filp = fget(lk->lk_wfd);
- if (filp == NULL) {
+ if (!filp)
return -EBADF;
+
+ kcd.kcd_magic = KKUC_CT_DATA_MAGIC;
+ kcd.kcd_uuid = lmv->cluuid;
+ kcd.kcd_archive = lk->lk_data;
+
+ rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group,
+ &kcd, sizeof(kcd));
+ if (rc) {
+ if (filp)
+ fput(filp);
}
- rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, lk->lk_data);
- if (rc != 0 && filp != NULL)
- fput(filp);
+
return rc;
}
static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp,
- int len, void *karg, void *uarg)
+ int len, void *karg, void __user *uarg)
{
struct obd_device *obddev = class_exp2obd(exp);
struct lmv_obd *lmv = &obddev->u.lmv;
emerg[i] = em;
cl_page_list_init(&em->emrg_page_list);
em->emrg_env = cl_env_alloc(&em->emrg_refcheck,
- LCT_REMEMBER|LCT_NOREF);
+ LCT_REMEMBER | LCT_NOREF);
if (!IS_ERR(em->emrg_env))
em->emrg_env->le_ctx.lc_cookie = 0x2;
else {
int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
struct lov_mds_md *lmm, int lmm_bytes);
int lov_getstripe(struct obd_export *exp,
- struct lov_stripe_md *lsm, struct lov_user_md *lump);
+ struct lov_stripe_md *lsm, struct lov_user_md __user *lump);
int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count,
int pattern, int magic);
int lov_free_memmd(struct lov_stripe_md **lsmp);
}
static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
- void *karg, void *uarg)
+ void *karg, void __user *uarg)
{
struct obd_device *obddev = class_exp2obd(exp);
struct lov_obd *lov = &obddev->u.lov;
(int) sizeof(struct obd_uuid))))
return -EFAULT;
- flags = uarg ? *(__u32 *)uarg : 0;
+ memcpy(&flags, data->ioc_inlbuf1, sizeof(__u32));
+ flags = flags & LL_STATFS_NODELAY ? OBD_STATFS_NODELAY : 0;
+
/* got statfs data */
rc = obd_statfs(NULL, lov->lov_tgts[index]->ltd_exp, &stat_buf,
cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
* lmm_magic must be LOV_USER_MAGIC.
*/
int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm,
- struct lov_user_md *lump)
+ struct lov_user_md __user *lump)
{
/*
* XXX huge struct allocated on stack.
#include "../include/lprocfs_status.h"
#include "../include/lustre_param.h"
#include "../include/lustre_log.h"
+#include "../include/lustre_kernelcomm.h"
#include "mdc_internal.h"
}
static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
- void *karg, void *uarg)
+ void *karg, void __user *uarg)
{
struct obd_device *obd = exp->exp_obd;
struct obd_ioctl_data *data = karg;
/**
* callback function passed to kuc for re-registering each HSM copytool
* running on MDC, after MDT shutdown/recovery.
- * @param data archive id served by the copytool
+ * @param data copytool registration data
* @param cb_arg callback argument (obd_import)
*/
-static int mdc_hsm_ct_reregister(__u32 data, void *cb_arg)
+static int mdc_hsm_ct_reregister(void *data, void *cb_arg)
{
+ struct kkuc_ct_data *kcd = data;
struct obd_import *imp = (struct obd_import *)cb_arg;
- __u32 archive = data;
int rc;
- CDEBUG(D_HA, "recover copytool registration to MDT (archive=%#x)\n",
- archive);
- rc = mdc_ioc_hsm_ct_register(imp, archive);
+ if (!kcd || kcd->kcd_magic != KKUC_CT_DATA_MAGIC)
+ return -EPROTO;
+
+ if (!obd_uuid_equals(&kcd->kcd_uuid, &imp->imp_obd->obd_uuid))
+ return 0;
+
+ CDEBUG(D_HA, "%s: recover copytool registration to MDT (archive=%#x)\n",
+ imp->imp_obd->obd_name, kcd->kcd_archive);
+ rc = mdc_ioc_hsm_ct_register(imp, kcd->kcd_archive);
/* ignore error if the copytool is already registered */
- return ((rc != 0) && (rc != -EEXIST)) ? rc : 0;
+ return (rc == -EEXIST) ? 0 : rc;
}
static int mdc_set_info_async(const struct lu_env *env,
obdclass-y := linux/linux-module.o linux/linux-obdo.o linux/linux-sysctl.o \
llog.o llog_cat.o llog_obd.o llog_swab.o class_obd.o debug.o \
- genops.o uuid.o lprocfs_status.o \
- lustre_handles.o lustre_peer.o \
- statfs_pack.o obdo.o obd_config.o obd_mount.o \
- lu_object.o cl_object.o \
- cl_page.o cl_lock.o cl_io.o lu_ref.o acl.o lprocfs_counters.o
+ genops.o uuid.o lprocfs_status.o lprocfs_counters.o \
+ lustre_handles.o lustre_peer.o statfs_pack.o \
+ obdo.o obd_config.o obd_mount.o lu_object.o lu_ref.o \
+ cl_object.o cl_page.o cl_lock.o cl_io.o \
+ acl.o kernelcomm.o
}
CDEBUG(D_IOCTL, "cmd = %x\n", cmd);
- if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
+ if (obd_ioctl_getdata(&buf, &len, (void __user *)arg)) {
CERROR("OBD ioctl: data error\n");
return -EINVAL;
}
memcpy(data->ioc_bulk, BUILD_VERSION,
strlen(BUILD_VERSION) + 1);
- err = obd_ioctl_popdata((void *)arg, data, len);
+ err = obd_ioctl_popdata((void __user *)arg, data, len);
if (err)
err = -EFAULT;
goto out;
goto out;
}
- err = obd_ioctl_popdata((void *)arg, data, sizeof(*data));
+ err = obd_ioctl_popdata((void __user *)arg, data,
+ sizeof(*data));
if (err)
err = -EFAULT;
goto out;
CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
dev);
- err = obd_ioctl_popdata((void *)arg, data, sizeof(*data));
+ err = obd_ioctl_popdata((void __user *)arg, data,
+ sizeof(*data));
if (err)
err = -EFAULT;
goto out;
(int)index, status, obd->obd_type->typ_name,
obd->obd_name, obd->obd_uuid.uuid,
atomic_read(&obd->obd_refcount));
- err = obd_ioctl_popdata((void *)arg, data, len);
+ err = obd_ioctl_popdata((void __user *)arg, data, len);
err = 0;
goto out;
if (err)
goto out;
- err = obd_ioctl_popdata((void *)arg, data, len);
+ err = obd_ioctl_popdata((void __user *)arg, data, len);
if (err)
err = -EFAULT;
goto out;
#define DEBUG_SUBSYSTEM S_CLASS
#include "../include/obd_class.h"
#include "../include/lprocfs_status.h"
+#include "../include/lustre_kernelcomm.h"
spinlock_t obd_types_lock;
#define DEBUG_SUBSYSTEM S_CLASS
#define D_KUC D_OTHER
-#include "../../include/linux/libcfs/libcfs.h"
-
-/* This is the kernel side (liblustre as well). */
+#include "../include/obd_support.h"
+#include "../include/lustre_kernelcomm.h"
/**
* libcfs_kkuc_msg_put - send an message from kernel to userspace
ssize_t count = kuch->kuc_msglen;
loff_t offset = 0;
mm_segment_t fs;
- int rc = -ENOSYS;
+ int rc = -ENXIO;
- if (filp == NULL || IS_ERR(filp))
+ if (!filp || IS_ERR(filp))
return -EBADF;
if (kuch->kuc_magic != KUC_MAGIC) {
CERROR("KernelComm: bad magic %x\n", kuch->kuc_magic);
- return -ENOSYS;
+ return rc;
}
fs = get_fs();
}
EXPORT_SYMBOL(libcfs_kkuc_msg_put);
-/* Broadcast groups are global across all mounted filesystems;
+/*
+ * Broadcast groups are global across all mounted filesystems;
* i.e. registering for a group on 1 fs will get messages for that
- * group from any fs */
+ * group from any fs
+ */
/** A single group registration has a uid and a file pointer */
struct kkuc_reg {
- struct list_head kr_chain;
- int kr_uid;
+ struct list_head kr_chain;
+ int kr_uid;
struct file *kr_fp;
- __u32 kr_data;
+ char kr_data[0];
};
-static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {};
+static struct list_head kkuc_groups[KUC_GRP_MAX + 1] = {};
/* Protect message sending against remove and adds */
static DECLARE_RWSEM(kg_sem);
* @param filp pipe to write into
* @param uid identifier for this receiver
* @param group group number
+ * @param data user data
*/
int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group,
- __u32 data)
+ void *data, size_t data_len)
{
struct kkuc_reg *reg;
}
/* fput in group_rem */
- if (filp == NULL)
+ if (!filp)
return -EBADF;
/* freed in group_rem */
- reg = kmalloc(sizeof(*reg), 0);
- if (reg == NULL)
+ reg = kmalloc(sizeof(*reg) + data_len, 0);
+ if (!reg)
return -ENOMEM;
reg->kr_fp = filp;
reg->kr_uid = uid;
- reg->kr_data = data;
+ memcpy(reg->kr_data, data, data_len);
down_write(&kg_sem);
- if (kkuc_groups[group].next == NULL)
+ if (!kkuc_groups[group].next)
INIT_LIST_HEAD(&kkuc_groups[group]);
list_add(®->kr_chain, &kkuc_groups[group]);
up_write(&kg_sem);
}
EXPORT_SYMBOL(libcfs_kkuc_group_add);
-int libcfs_kkuc_group_rem(int uid, int group)
+int libcfs_kkuc_group_rem(int uid, unsigned int group)
{
struct kkuc_reg *reg, *next;
- if (kkuc_groups[group].next == NULL)
+ if (!kkuc_groups[group].next)
return 0;
- if (uid == 0) {
+ if (!uid) {
/* Broadcast a shutdown message */
struct kuc_hdr lh;
down_write(&kg_sem);
list_for_each_entry_safe(reg, next, &kkuc_groups[group], kr_chain) {
- if ((uid == 0) || (uid == reg->kr_uid)) {
+ if (!uid || (uid == reg->kr_uid)) {
list_del(®->kr_chain);
CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n",
reg->kr_uid, reg->kr_fp, group);
- if (reg->kr_fp != NULL)
+ if (reg->kr_fp)
fput(reg->kr_fp);
kfree(reg);
}
}
EXPORT_SYMBOL(libcfs_kkuc_group_rem);
-int libcfs_kkuc_group_put(int group, void *payload)
+int libcfs_kkuc_group_put(unsigned int group, void *payload)
{
struct kkuc_reg *reg;
- int rc = 0;
+ int rc = 0;
int one_success = 0;
- down_read(&kg_sem);
+ down_write(&kg_sem);
list_for_each_entry(reg, &kkuc_groups[group], kr_chain) {
- if (reg->kr_fp != NULL) {
+ if (reg->kr_fp) {
rc = libcfs_kkuc_msg_put(reg->kr_fp, payload);
- if (rc == 0)
+ if (!rc) {
one_success = 1;
- else if (rc == -EPIPE) {
+ } else if (rc == -EPIPE) {
fput(reg->kr_fp);
reg->kr_fp = NULL;
}
}
}
- up_read(&kg_sem);
+ up_write(&kg_sem);
- /* don't return an error if the message has been delivered
- * at least to one agent */
+ /*
+ * don't return an error if the message has been delivered
+ * at least to one agent
+ */
if (one_success)
rc = 0;
* Calls a callback function for each link of the given kuc group.
* @param group the group to call the function on.
* @param cb_func the function to be called.
- * @param cb_arg iextra argument to be passed to the callback function.
+ * @param cb_arg extra argument to be passed to the callback function.
*/
-int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func,
+int libcfs_kkuc_group_foreach(unsigned int group, libcfs_kkuc_cb_t cb_func,
void *cb_arg)
{
struct kkuc_reg *reg;
}
/* no link for this group */
- if (kkuc_groups[group].next == NULL)
+ if (!kkuc_groups[group].next)
return 0;
- down_write(&kg_sem);
+ down_read(&kg_sem);
list_for_each_entry(reg, &kkuc_groups[group], kr_chain) {
- if (reg->kr_fp != NULL)
+ if (reg->kr_fp)
rc = cb_func(reg->kr_data, cb_arg);
}
- up_write(&kg_sem);
+ up_read(&kg_sem);
return rc;
}
#include "../../include/lustre/lustre_build_version.h"
/* buffer MUST be at least the size of obd_ioctl_hdr */
-int obd_ioctl_getdata(char **buf, int *len, void *arg)
+int obd_ioctl_getdata(char **buf, int *len, void __user *arg)
{
struct obd_ioctl_hdr hdr;
struct obd_ioctl_data *data;
int err;
int offset = 0;
- if (copy_from_user(&hdr, (void *)arg, sizeof(hdr)))
+ if (copy_from_user(&hdr, arg, sizeof(hdr)))
return -EFAULT;
if (hdr.ioc_version != OBD_IOCTL_VERSION) {
*len = hdr.ioc_len;
data = (struct obd_ioctl_data *)*buf;
- if (copy_from_user(*buf, (void *)arg, hdr.ioc_len)) {
+ if (copy_from_user(*buf, arg, hdr.ioc_len)) {
err = -EFAULT;
goto free_buf;
}
offset += cfs_size_round(data->ioc_inllen3);
}
- if (data->ioc_inllen4) {
+ if (data->ioc_inllen4)
data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset;
- }
return 0;
}
EXPORT_SYMBOL(obd_ioctl_getdata);
-int obd_ioctl_popdata(void *arg, void *data, int len)
+int obd_ioctl_popdata(void __user *arg, void *data, int len)
{
int err;
struct obd_device *obd;
obd = class_num2obd(i);
- if (obd == NULL || !obd->obd_attached || !obd->obd_set_up)
+ if (!obd || !obd->obd_attached || !obd->obd_set_up)
continue;
LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
class_incref(obd, __func__, current);
read_unlock(&obd_dev_lock);
- if (obd_health_check(NULL, obd)) {
+ if (obd_health_check(NULL, obd))
healthy = false;
- }
class_decref(obd, __func__, current);
read_lock(&obd_dev_lock);
}
struct obd_device *obd = class_num2obd((int)index);
char *status;
- if (obd == NULL)
+ if (!obd)
return 0;
LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
struct dentry *file;
lustre_kobj = kobject_create_and_add("lustre", fs_kobj);
- if (lustre_kobj == NULL)
+ if (!lustre_kobj)
goto out;
/* Create the files associated with this kobject */
__swab32s(&lcfg->lcfg_buflens[i]);
print_lustre_cfg(lcfg);
- return;
}
EXPORT_SYMBOL(lustre_swab_lustre_cfg);
__swab64s(&marker->cm_createtime);
__swab64s(&marker->cm_canceltime);
}
-
- return;
}
EXPORT_SYMBOL(lustre_swab_cfg_marker);
}
return entry;
}
-EXPORT_SYMBOL(ldebugfs_add_simple);
+EXPORT_SYMBOL_GPL(ldebugfs_add_simple);
static struct file_operations lprocfs_generic_fops = { };
}
return 0;
}
-EXPORT_SYMBOL(ldebugfs_add_vars);
+EXPORT_SYMBOL_GPL(ldebugfs_add_vars);
void ldebugfs_remove(struct dentry **entryp)
{
debugfs_remove_recursive(*entryp);
*entryp = NULL;
}
-EXPORT_SYMBOL(ldebugfs_remove);
+EXPORT_SYMBOL_GPL(ldebugfs_remove);
struct dentry *ldebugfs_register(const char *name,
struct dentry *parent,
out:
return entry;
}
-EXPORT_SYMBOL(ldebugfs_register);
+EXPORT_SYMBOL_GPL(ldebugfs_register);
/* Generic callbacks */
int lprocfs_rd_uint(struct seq_file *m, void *data)
return rc;
}
-EXPORT_SYMBOL(lprocfs_obd_setup);
+EXPORT_SYMBOL_GPL(lprocfs_obd_setup);
int lprocfs_obd_cleanup(struct obd_device *obd)
{
return 0;
}
-EXPORT_SYMBOL(lprocfs_obd_cleanup);
+EXPORT_SYMBOL_GPL(lprocfs_obd_cleanup);
int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid)
{
return 0;
}
-EXPORT_SYMBOL(ldebugfs_register_stats);
+EXPORT_SYMBOL_GPL(ldebugfs_register_stats);
void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
unsigned conf, const char *name, const char *units)
}
EXPORT_SYMBOL(lprocfs_write_u64_helper);
-int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count,
- __u64 *val, int mult)
+int lprocfs_write_frac_u64_helper(const char __user *buffer,
+ unsigned long count, __u64 *val, int mult)
{
char kernbuf[22], *end, *pbuf;
__u64 whole, frac = 0, units;
return 0;
}
-EXPORT_SYMBOL(ldebugfs_seq_create);
+EXPORT_SYMBOL_GPL(ldebugfs_seq_create);
int ldebugfs_obd_seq_create(struct obd_device *dev,
const char *name,
return ldebugfs_seq_create(dev->obd_debugfs_entry, name,
mode, seq_fops, data);
}
-EXPORT_SYMBOL(ldebugfs_obd_seq_create);
+EXPORT_SYMBOL_GPL(ldebugfs_obd_seq_create);
void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value)
{
struct cl_site ed_site_myself;
struct cl_site *ed_site;
struct lu_device *ed_next;
- int ed_next_islov;
};
struct echo_object {
static struct echo_object *cl_echo_object_find(struct echo_device *d,
struct lov_stripe_md **lsm);
static int cl_echo_object_put(struct echo_object *eco);
-static int cl_echo_enqueue(struct echo_object *eco, u64 start,
- u64 end, int mode, __u64 *cookie);
-static int cl_echo_cancel(struct echo_device *d, __u64 cookie);
static int cl_echo_object_brw(struct echo_object *eco, int rw, u64 offset,
struct page **pages, int npages, int async);
return obj;
}
-static struct lu_device_operations echo_device_lu_ops = {
+static const struct lu_device_operations echo_device_lu_ops = {
.ldo_object_alloc = echo_object_alloc,
};
/** @} echo_lu_dev_ops */
-static struct cl_device_operations echo_device_cl_ops = {
+static const struct cl_device_operations echo_device_cl_ops = {
};
/** \defgroup echo_init Setup and teardown
if (rc)
goto out;
- /* Tricky case, I have to determine the obd type since
- * CLIO uses the different parameters to initialize
- * objects for lov & osc. */
- if (strcmp(tgt_type_name, LUSTRE_LOV_NAME) == 0)
- ed->ed_next_islov = 1;
- else
- LASSERT(strcmp(tgt_type_name,
- LUSTRE_OSC_NAME) == 0);
} else {
LASSERT(strcmp(tgt_type_name, LUSTRE_OST_NAME) == 0);
}
info = echo_env_info(env);
conf = &info->eti_conf;
if (d->ed_next) {
- if (!d->ed_next_islov) {
- struct lov_oinfo *oinfo = lsm->lsm_oinfo[0];
-
- LASSERT(oinfo != NULL);
- oinfo->loi_oi = lsm->lsm_oi;
- conf->eoc_cl.u.coc_oinfo = oinfo;
- } else {
- struct lustre_md *md;
+ struct lov_oinfo *oinfo = lsm->lsm_oinfo[0];
- md = &info->eti_md;
- memset(md, 0, sizeof(*md));
- md->lsm = lsm;
- conf->eoc_cl.u.coc_md = md;
- }
+ LASSERT(oinfo);
+ oinfo->loi_oi = lsm->lsm_oi;
+ conf->eoc_cl.u.coc_oinfo = oinfo;
}
conf->eoc_md = lsmp;
return rc;
}
-static int cl_echo_enqueue(struct echo_object *eco, u64 start, u64 end,
- int mode, __u64 *cookie)
-{
- struct echo_thread_info *info;
- struct lu_env *env;
- struct cl_io *io;
- int refcheck;
- int result;
-
- env = cl_env_get(&refcheck);
- if (IS_ERR(env))
- return PTR_ERR(env);
-
- info = echo_env_info(env);
- io = &info->eti_io;
-
- io->ci_ignore_layout = 1;
- result = cl_io_init(env, io, CIT_MISC, echo_obj2cl(eco));
- if (result < 0)
- goto out;
- LASSERT(result == 0);
-
- result = cl_echo_enqueue0(env, eco, start, end, mode, cookie, 0);
- cl_io_fini(env, io);
-
-out:
- cl_env_put(env, &refcheck);
- return result;
-}
-
static int cl_echo_cancel0(struct lu_env *env, struct echo_device *ed,
__u64 cookie)
{
return 0;
}
-static int cl_echo_cancel(struct echo_device *ed, __u64 cookie)
-{
- struct lu_env *env;
- int refcheck;
- int rc;
-
- env = cl_env_get(&refcheck);
- if (IS_ERR(env))
- return PTR_ERR(env);
-
- rc = cl_echo_cancel0(env, ed, cookie);
-
- cl_env_put(env, &refcheck);
- return rc;
-}
-
static int cl_echo_async_brw(const struct lu_env *env, struct cl_io *io,
enum cl_req_type unused, struct cl_2queue *queue)
{
static u64 last_object_id;
-static int
-echo_copyout_lsm(struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob)
-{
- struct lov_stripe_md *ulsm = _ulsm;
- struct lov_oinfo **p;
- int nob, i;
-
- nob = offsetof(struct lov_stripe_md, lsm_oinfo[lsm->lsm_stripe_count]);
- if (nob > ulsm_nob)
- return -EINVAL;
-
- if (copy_to_user(ulsm, lsm, sizeof(*ulsm)))
- return -EFAULT;
-
- for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) {
- struct lov_oinfo __user *up;
- if (get_user(up, ulsm->lsm_oinfo + i) ||
- copy_to_user(up, *p, sizeof(struct lov_oinfo)))
- return -EFAULT;
- }
- return 0;
-}
-
-static int
-echo_copyin_lsm(struct echo_device *ed, struct lov_stripe_md *lsm,
- struct lov_stripe_md __user *ulsm, int ulsm_nob)
-{
- struct echo_client_obd *ec = ed->ed_ec;
- struct lov_oinfo **p;
- int i;
-
- if (ulsm_nob < sizeof(*lsm))
- return -EINVAL;
-
- if (copy_from_user(lsm, ulsm, sizeof(*lsm)))
- return -EFAULT;
-
- if (lsm->lsm_stripe_count > ec->ec_nstripes ||
- lsm->lsm_magic != LOV_MAGIC ||
- (lsm->lsm_stripe_size & (~CFS_PAGE_MASK)) != 0 ||
- ((__u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count > ~0UL))
- return -EINVAL;
-
- for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) {
- struct lov_oinfo __user *up;
- if (get_user(up, ulsm->lsm_oinfo + i) ||
- copy_from_user(*p, up, sizeof(struct lov_oinfo)))
- return -EFAULT;
- }
- return 0;
-}
-
static int echo_create_object(const struct lu_env *env, struct echo_device *ed,
- int on_target, struct obdo *oa, void *ulsm,
- int ulsm_nob, struct obd_trans_info *oti)
+ struct obdo *oa, struct obd_trans_info *oti)
{
struct echo_object *eco;
struct echo_client_obd *ec = ed->ed_ec;
int rc;
int created = 0;
- if ((oa->o_valid & OBD_MD_FLID) == 0 && /* no obj id */
- (on_target || /* set_stripe */
- ec->ec_nstripes != 0)) { /* LOV */
+ if ((oa->o_valid & OBD_MD_FLID) == 0) { /* no obj id */
CERROR("No valid oid\n");
return -EINVAL;
}
goto failed;
}
- if (ulsm != NULL) {
- int i, idx;
-
- rc = echo_copyin_lsm(ed, lsm, ulsm, ulsm_nob);
- if (rc != 0)
- goto failed;
-
- if (lsm->lsm_stripe_count == 0)
- lsm->lsm_stripe_count = ec->ec_nstripes;
-
- if (lsm->lsm_stripe_size == 0)
- lsm->lsm_stripe_size = PAGE_CACHE_SIZE;
-
- idx = cfs_rand();
-
- /* setup stripes: indices + default ids if required */
- for (i = 0; i < lsm->lsm_stripe_count; i++) {
- if (ostid_id(&lsm->lsm_oinfo[i]->loi_oi) == 0)
- lsm->lsm_oinfo[i]->loi_oi = lsm->lsm_oi;
-
- lsm->lsm_oinfo[i]->loi_ost_idx =
- (idx + i) % ec->ec_nstripes;
- }
- }
-
- /* setup object ID here for !on_target and LOV hint */
+ /* setup object ID here */
if (oa->o_valid & OBD_MD_FLID) {
LASSERT(oa->o_valid & OBD_MD_FLGROUP);
lsm->lsm_oi = oa->o_oi;
if (ostid_id(&lsm->lsm_oi) == 0)
ostid_set_id(&lsm->lsm_oi, ++last_object_id);
- rc = 0;
- if (on_target) {
- /* Only echo objects are allowed to be created */
- LASSERT((oa->o_valid & OBD_MD_FLGROUP) &&
- (ostid_seq(&oa->o_oi) == FID_SEQ_ECHO));
- rc = obd_create(env, ec->ec_exp, oa, &lsm, oti);
- if (rc != 0) {
- CERROR("Cannot create objects: rc = %d\n", rc);
- goto failed;
- }
- created = 1;
+ /* Only echo objects are allowed to be created */
+ LASSERT((oa->o_valid & OBD_MD_FLGROUP) &&
+ (ostid_seq(&oa->o_oi) == FID_SEQ_ECHO));
+
+ rc = obd_create(env, ec->ec_exp, oa, &lsm, oti);
+ if (rc != 0) {
+ CERROR("Cannot create objects: rc = %d\n", rc);
+ goto failed;
}
+ created = 1;
/* See what object ID we were given */
oa->o_oi = lsm->lsm_oi;
}
static void
-echo_get_stripe_off_id(struct lov_stripe_md *lsm, u64 *offp, u64 *idp)
-{
- unsigned long stripe_count;
- unsigned long stripe_size;
- unsigned long width;
- unsigned long woffset;
- int stripe_index;
- u64 offset;
-
- if (lsm->lsm_stripe_count <= 1)
- return;
-
- offset = *offp;
- stripe_size = lsm->lsm_stripe_size;
- stripe_count = lsm->lsm_stripe_count;
-
- /* width = # bytes in all stripes */
- width = stripe_size * stripe_count;
-
- /* woffset = offset within a width; offset = whole number of widths */
- woffset = do_div(offset, width);
-
- stripe_index = woffset / stripe_size;
-
- *idp = ostid_id(&lsm->lsm_oinfo[stripe_index]->loi_oi);
- *offp = offset * stripe_size + woffset % stripe_size;
-}
-
-static void
-echo_client_page_debug_setup(struct lov_stripe_md *lsm,
- struct page *page, int rw, u64 id,
+echo_client_page_debug_setup(struct page *page, int rw, u64 id,
u64 offset, u64 count)
{
char *addr;
if (rw == OBD_BRW_WRITE) {
stripe_off = offset + delta;
stripe_id = id;
- echo_get_stripe_off_id(lsm, &stripe_off, &stripe_id);
} else {
stripe_off = 0xdeadbeef00c0ffeeULL;
stripe_id = 0xdeadbeef00c0ffeeULL;
kunmap(page);
}
-static int echo_client_page_debug_check(struct lov_stripe_md *lsm,
- struct page *page, u64 id,
+static int echo_client_page_debug_check(struct page *page, u64 id,
u64 offset, u64 count)
{
u64 stripe_off;
for (rc = delta = 0; delta < PAGE_CACHE_SIZE; delta += OBD_ECHO_BLOCK_SIZE) {
stripe_off = offset + delta;
stripe_id = id;
- echo_get_stripe_off_id(lsm, &stripe_off, &stripe_id);
rc2 = block_debug_check("test_brw",
addr + delta, OBD_ECHO_BLOCK_SIZE,
u64 count, int async,
struct obd_trans_info *oti)
{
- struct lov_stripe_md *lsm = eco->eo_lsm;
u32 npages;
struct brw_page *pga;
struct brw_page *pgp;
gfp_mask = ((ostid_id(&oa->o_oi) & 2) == 0) ? GFP_KERNEL : GFP_HIGHUSER;
LASSERT(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ);
- LASSERT(lsm != NULL);
- LASSERT(ostid_id(&lsm->lsm_oi) == ostid_id(&oa->o_oi));
if (count <= 0 ||
(count & (~CFS_PAGE_MASK)) != 0)
pgp->flag = brw_flags;
if (verify)
- echo_client_page_debug_setup(lsm, pgp->pg, rw,
+ echo_client_page_debug_setup(pgp->pg, rw,
ostid_id(&oa->o_oi), off,
pgp->count);
}
if (verify) {
int vrc;
- vrc = echo_client_page_debug_check(lsm, pgp->pg,
+ vrc = echo_client_page_debug_check(pgp->pg,
ostid_id(&oa->o_oi),
pgp->off, pgp->count);
if (vrc != 0 && rc == 0)
u64 batch, struct obd_trans_info *oti,
int async)
{
- struct lov_stripe_md *lsm = eco->eo_lsm;
struct obd_ioobj ioo;
struct niobuf_local *lnb;
struct niobuf_remote *rnb;
u64 npages, tot_pages;
int i, ret = 0, brw_flags = 0;
- if (count <= 0 || (count & (~CFS_PAGE_MASK)) != 0 ||
- (lsm != NULL && ostid_id(&lsm->lsm_oi) != ostid_id(&oa->o_oi)))
+ if (count <= 0 || (count & (~CFS_PAGE_MASK)) != 0)
return -EINVAL;
npages = batch >> PAGE_CACHE_SHIFT;
continue;
if (rw == OBD_BRW_WRITE)
- echo_client_page_debug_setup(lsm, page, rw,
+ echo_client_page_debug_setup(page, rw,
ostid_id(&oa->o_oi),
rnb[i].offset,
rnb[i].len);
else
- echo_client_page_debug_check(lsm, page,
+ echo_client_page_debug_check(page,
ostid_id(&oa->o_oi),
rnb[i].offset,
rnb[i].len);
return rc;
}
-static int
-echo_client_enqueue(struct obd_export *exp, struct obdo *oa,
- int mode, u64 offset, u64 nob)
-{
- struct echo_device *ed = obd2echo_dev(exp->exp_obd);
- struct lustre_handle *ulh = &oa->o_handle;
- struct echo_object *eco;
- u64 end;
- int rc;
-
- if (ed->ed_next == NULL)
- return -EOPNOTSUPP;
-
- if (!(mode == LCK_PR || mode == LCK_PW))
- return -EINVAL;
-
- if ((offset & (~CFS_PAGE_MASK)) != 0 ||
- (nob & (~CFS_PAGE_MASK)) != 0)
- return -EINVAL;
-
- rc = echo_get_object(&eco, ed, oa);
- if (rc != 0)
- return rc;
-
- end = (nob == 0) ? ((u64) -1) : (offset + nob - 1);
- rc = cl_echo_enqueue(eco, offset, end, mode, &ulh->cookie);
- if (rc == 0) {
- oa->o_valid |= OBD_MD_FLHANDLE;
- CDEBUG(D_INFO, "Cookie is %#llx\n", ulh->cookie);
- }
- echo_put_object(eco);
- return rc;
-}
-
-static int
-echo_client_cancel(struct obd_export *exp, struct obdo *oa)
-{
- struct echo_device *ed = obd2echo_dev(exp->exp_obd);
- __u64 cookie = oa->o_handle.cookie;
-
- if ((oa->o_valid & OBD_MD_FLHANDLE) == 0)
- return -EINVAL;
-
- CDEBUG(D_INFO, "Cookie is %#llx\n", cookie);
- return cl_echo_cancel(ed, cookie);
-}
-
static int
echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
- void *karg, void *uarg)
+ void *karg, void __user *uarg)
{
struct obd_device *obd = exp->exp_obd;
struct echo_device *ed = obd2echo_dev(obd);
goto out;
}
- rc = echo_create_object(env, ed, 1, oa, data->ioc_pbuf1,
- data->ioc_plen1, &dummy_oti);
+ rc = echo_create_object(env, ed, oa, &dummy_oti);
goto out;
case OBD_IOC_DESTROY:
rc = echo_get_object(&eco, ed, oa);
if (rc == 0) {
- rc = obd_destroy(env, ec->ec_exp, oa, eco->eo_lsm,
+ rc = obd_destroy(env, ec->ec_exp, oa, NULL,
&dummy_oti, NULL);
if (rc == 0)
eco->eo_deleted = 1;
case OBD_IOC_GETATTR:
rc = echo_get_object(&eco, ed, oa);
if (rc == 0) {
- struct obd_info oinfo = { };
+ struct obd_info oinfo = {
+ .oi_oa = oa,
+ };
- oinfo.oi_md = eco->eo_lsm;
- oinfo.oi_oa = oa;
rc = obd_getattr(env, ec->ec_exp, &oinfo);
echo_put_object(eco);
}
rc = echo_get_object(&eco, ed, oa);
if (rc == 0) {
- struct obd_info oinfo = { };
-
- oinfo.oi_oa = oa;
- oinfo.oi_md = eco->eo_lsm;
+ struct obd_info oinfo = {
+ .oi_oa = oa,
+ };
rc = obd_setattr(env, ec->ec_exp, &oinfo, NULL);
echo_put_object(eco);
rc = echo_client_brw_ioctl(env, rw, exp, data, &dummy_oti);
goto out;
- case ECHO_IOC_GET_STRIPE:
- rc = echo_get_object(&eco, ed, oa);
- if (rc == 0) {
- rc = echo_copyout_lsm(eco->eo_lsm, data->ioc_pbuf1,
- data->ioc_plen1);
- echo_put_object(eco);
- }
- goto out;
-
- case ECHO_IOC_SET_STRIPE:
- if (!capable(CFS_CAP_SYS_ADMIN)) {
- rc = -EPERM;
- goto out;
- }
-
- if (data->ioc_pbuf1 == NULL) { /* unset */
- rc = echo_get_object(&eco, ed, oa);
- if (rc == 0) {
- eco->eo_deleted = 1;
- echo_put_object(eco);
- }
- } else {
- rc = echo_create_object(env, ed, 0, oa,
- data->ioc_pbuf1,
- data->ioc_plen1, &dummy_oti);
- }
- goto out;
-
- case ECHO_IOC_ENQUEUE:
- if (!capable(CFS_CAP_SYS_ADMIN)) {
- rc = -EPERM;
- goto out;
- }
-
- rc = echo_client_enqueue(exp, oa,
- data->ioc_conn1, /* lock mode */
- data->ioc_offset,
- data->ioc_count);/*extent*/
- goto out;
-
- case ECHO_IOC_CANCEL:
- rc = echo_client_cancel(exp, oa);
- goto out;
-
default:
CERROR("echo_ioctl(): unrecognised ioctl %#x\n", cmd);
rc = -ENOTTY;
INIT_LIST_HEAD(&ec->ec_objects);
INIT_LIST_HEAD(&ec->ec_locks);
ec->ec_unique = 0;
- ec->ec_nstripes = 0;
ocd = kzalloc(sizeof(*ocd), GFP_NOFS);
if (!ocd) {
struct obd_device *obd = container_of(kobj, struct obd_device,
obd_kobj);
struct osc_device *od = obd2osc_dev(obd);
+ int rc;
+ int val;
+
+ rc = kstrtoint(buffer, 10, &val);
+ if (rc)
+ return rc;
+
+ if (val < 0)
+ return -EINVAL;
+
+ od->od_contention_time = val;
- return lprocfs_write_helper(buffer, count, &od->od_contention_time) ?:
- count;
+ return count;
}
LUSTRE_RW_ATTR(contention_seconds);
struct obd_device *obd = container_of(kobj, struct obd_device,
obd_kobj);
struct osc_device *od = obd2osc_dev(obd);
+ int rc;
+ unsigned int val;
- return lprocfs_write_helper(buffer, count, &od->od_lockless_truncate) ?:
- count;
+ rc = kstrtouint(buffer, 10, &val);
+ if (rc)
+ return rc;
+
+ od->od_lockless_truncate = val;
+
+ return count;
}
LUSTRE_RW_ATTR(lockless_truncate);
static int
osc_send_write_rpc(const struct lu_env *env, struct client_obd *cli,
struct osc_object *osc)
+ __must_hold(osc)
{
LIST_HEAD(rpclist);
struct osc_extent *ext;
static int
osc_send_read_rpc(const struct lu_env *env, struct client_obd *cli,
struct osc_object *osc)
+ __must_hold(osc)
{
struct osc_extent *ext;
struct osc_extent *next;
/* called with the loi list lock held */
static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli)
+ __must_hold(&cli->cl_loi_list_lock)
{
struct osc_object *osc;
int rc = 0;
osc_lru_del(osc_cli(obj), opg, true);
}
-void osc_page_clip(const struct lu_env *env, const struct cl_page_slice *slice,
- int from, int to)
+static void osc_page_clip(const struct lu_env *env,
+ const struct cl_page_slice *slice, int from, int to)
{
struct osc_page *opg = cl2osc_page(slice);
struct osc_async_page *oap = &opg->ops_oap;
* the maximum number of OST indices which will fit in the user buffer.
* lmm_magic must be LOV_MAGIC (we only use 1 slot here).
*/
-static int osc_getstripe(struct lov_stripe_md *lsm, struct lov_user_md *lump)
+static int osc_getstripe(struct lov_stripe_md *lsm,
+ struct lov_user_md __user *lump)
{
/* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */
struct lov_user_md_v3 lum, *lumk;
}
static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
- void *karg, void *uarg)
+ void *karg, void __user *uarg)
{
struct obd_device *obd = exp->exp_obd;
struct obd_ioctl_data *data = karg;
* If anything goes wrong just ignore it - same as if it never happened
*/
static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req)
+ __must_hold(&req->rq_lock)
{
struct ptlrpc_request *early_req;
time64_t olddl;
(s64)req->rq_sent, (s64)req->rq_real_sent);
if (imp != NULL && obd_debug_peer_on_timeout)
- LNetCtl(IOC_LIBCFS_DEBUG_PEER, &imp->imp_connection->c_peer);
+ LNetDebugPeer(imp->imp_connection->c_peer);
ptlrpc_unregister_reply(req, async_unlink);
ptlrpc_unregister_bulk(req, async_unlink);
__u32 best_order = 0;
int count = 0;
int rc = -ENOENT;
- int portals_compatibility;
int dist;
__u32 order;
lnet_nid_t dst_nid;
lnet_nid_t src_nid;
- portals_compatibility = LNetCtl(IOC_LIBCFS_PORTALS_COMPATIBILITY, NULL);
-
peer->pid = LUSTRE_SRV_LNET_PID;
/* Choose the matching UUID that's closest */
best_dist = dist;
best_order = order;
- if (portals_compatibility > 1) {
- /* Strong portals compatibility: Zero the nid's
- * NET, so if I'm reading new config logs, or
- * getting configured by (new) lconf I can
- * still talk to old servers. */
- dst_nid = LNET_MKNID(0, LNET_NIDADDR(dst_nid));
- src_nid = LNET_MKNID(0, LNET_NIDADDR(src_nid));
- }
peer->nid = dst_nid;
*self = src_nid;
rc = 0;
static void nrs_resource_put_safe(struct ptlrpc_nrs_resource **resp)
{
struct ptlrpc_nrs_policy *pols[NRS_RES_MAX];
- struct ptlrpc_nrs *nrs = NULL;
int i;
for (i = 0; i < NRS_RES_MAX; i++) {
}
for (i = 0; i < NRS_RES_MAX; i++) {
- if (pols[i] == NULL)
- continue;
-
- if (nrs == NULL) {
- nrs = pols[i]->pol_nrs;
- spin_lock(&nrs->nrs_lock);
- }
- nrs_policy_put_locked(pols[i]);
+ if (pols[i])
+ nrs_policy_put(pols[i]);
}
-
- if (nrs != NULL)
- spin_unlock(&nrs->nrs_lock);
}
/**
static inline void enc_pools_wakeup(void)
{
assert_spin_locked(&page_pools.epp_lock);
- LASSERT(page_pools.epp_waitqlen >= 0);
if (unlikely(page_pools.epp_waitqlen)) {
LASSERT(waitqueue_active(&page_pools.epp_waitq));
struct aim_channel {
wait_queue_head_t wq;
+ spinlock_t unlink; /* synchronization lock to unlink channels */
struct cdev cdev;
struct device *dev;
struct mutex io_mutex;
struct most_channel_config *cfg;
unsigned int channel_id;
dev_t devno;
- bool keep_mbo;
- unsigned int mbo_offs;
- struct mbo *stacked_mbo;
+ size_t mbo_offs;
DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *));
- atomic_t access_ref;
+ int access_ref;
struct list_head list;
};
static struct list_head channel_list;
static spinlock_t ch_list_lock;
+static inline bool ch_has_mbo(struct aim_channel *c)
+{
+ return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0;
+}
+
+static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo)
+{
+ *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim);
+ return *mbo;
+}
+
static struct aim_channel *get_channel(struct most_interface *iface, int id)
{
- struct aim_channel *channel, *tmp;
+ struct aim_channel *c, *tmp;
unsigned long flags;
int found_channel = 0;
spin_lock_irqsave(&ch_list_lock, flags);
- list_for_each_entry_safe(channel, tmp, &channel_list, list) {
- if ((channel->iface == iface) && (channel->channel_id == id)) {
+ list_for_each_entry_safe(c, tmp, &channel_list, list) {
+ if ((c->iface == iface) && (c->channel_id == id)) {
found_channel = 1;
break;
}
spin_unlock_irqrestore(&ch_list_lock, flags);
if (!found_channel)
return NULL;
- return channel;
+ return c;
+}
+
+static void stop_channel(struct aim_channel *c)
+{
+ struct mbo *mbo;
+
+ while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1))
+ most_put_mbo(mbo);
+ most_stop_channel(c->iface, c->channel_id, &cdev_aim);
+}
+
+static void destroy_cdev(struct aim_channel *c)
+{
+ unsigned long flags;
+
+ device_destroy(aim_class, c->devno);
+ cdev_del(&c->cdev);
+ kfifo_free(&c->fifo);
+ spin_lock_irqsave(&ch_list_lock, flags);
+ list_del(&c->list);
+ spin_unlock_irqrestore(&ch_list_lock, flags);
+ ida_simple_remove(&minor_id, MINOR(c->devno));
}
/**
*/
static int aim_open(struct inode *inode, struct file *filp)
{
- struct aim_channel *channel;
+ struct aim_channel *c;
int ret;
- channel = to_channel(inode->i_cdev);
- filp->private_data = channel;
+ c = to_channel(inode->i_cdev);
+ filp->private_data = c;
- if (((channel->cfg->direction == MOST_CH_RX) &&
+ if (((c->cfg->direction == MOST_CH_RX) &&
((filp->f_flags & O_ACCMODE) != O_RDONLY)) ||
- ((channel->cfg->direction == MOST_CH_TX) &&
+ ((c->cfg->direction == MOST_CH_TX) &&
((filp->f_flags & O_ACCMODE) != O_WRONLY))) {
pr_info("WARN: Access flags mismatch\n");
return -EACCES;
}
- if (!atomic_inc_and_test(&channel->access_ref)) {
+
+ mutex_lock(&c->io_mutex);
+ if (!c->dev) {
+ pr_info("WARN: Device is destroyed\n");
+ mutex_unlock(&c->io_mutex);
+ return -EBUSY;
+ }
+
+ if (c->access_ref) {
pr_info("WARN: Device is busy\n");
- atomic_dec(&channel->access_ref);
+ mutex_unlock(&c->io_mutex);
return -EBUSY;
}
- ret = most_start_channel(channel->iface, channel->channel_id,
- &cdev_aim);
- if (ret)
- atomic_dec(&channel->access_ref);
+ c->mbo_offs = 0;
+ ret = most_start_channel(c->iface, c->channel_id, &cdev_aim);
+ if (!ret)
+ c->access_ref = 1;
+ mutex_unlock(&c->io_mutex);
return ret;
}
*/
static int aim_close(struct inode *inode, struct file *filp)
{
- int ret;
- struct mbo *mbo;
- struct aim_channel *channel = to_channel(inode->i_cdev);
-
- mutex_lock(&channel->io_mutex);
- if (!channel->dev) {
- mutex_unlock(&channel->io_mutex);
- atomic_dec(&channel->access_ref);
- device_destroy(aim_class, channel->devno);
- cdev_del(&channel->cdev);
- kfifo_free(&channel->fifo);
- list_del(&channel->list);
- ida_simple_remove(&minor_id, MINOR(channel->devno));
- wake_up_interruptible(&channel->wq);
- kfree(channel);
- return 0;
+ struct aim_channel *c = to_channel(inode->i_cdev);
+
+ mutex_lock(&c->io_mutex);
+ spin_lock(&c->unlink);
+ c->access_ref = 0;
+ spin_unlock(&c->unlink);
+ if (c->dev) {
+ stop_channel(c);
+ mutex_unlock(&c->io_mutex);
+ } else {
+ destroy_cdev(c);
+ mutex_unlock(&c->io_mutex);
+ kfree(c);
}
- mutex_unlock(&channel->io_mutex);
-
- while (kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1))
- most_put_mbo(mbo);
- if (channel->keep_mbo)
- most_put_mbo(channel->stacked_mbo);
- ret = most_stop_channel(channel->iface, channel->channel_id, &cdev_aim);
- atomic_dec(&channel->access_ref);
- wake_up_interruptible(&channel->wq);
- return ret;
+ return 0;
}
/**
static ssize_t aim_write(struct file *filp, const char __user *buf,
size_t count, loff_t *offset)
{
- int ret, err;
- size_t actual_len = 0;
- size_t max_len = 0;
- ssize_t retval;
- struct mbo *mbo;
- struct aim_channel *channel = filp->private_data;
-
- mutex_lock(&channel->io_mutex);
- if (unlikely(!channel->dev)) {
- mutex_unlock(&channel->io_mutex);
- return -EPIPE;
- }
- mutex_unlock(&channel->io_mutex);
+ int ret;
+ size_t actual_len;
+ size_t max_len;
+ struct mbo *mbo = NULL;
+ struct aim_channel *c = filp->private_data;
- mbo = most_get_mbo(channel->iface, channel->channel_id, &cdev_aim);
+ mutex_lock(&c->io_mutex);
+ while (c->dev && !ch_get_mbo(c, &mbo)) {
+ mutex_unlock(&c->io_mutex);
- if (!mbo) {
if ((filp->f_flags & O_NONBLOCK))
return -EAGAIN;
- if (wait_event_interruptible(
- channel->wq,
- (mbo = most_get_mbo(channel->iface,
- channel->channel_id,
- &cdev_aim)) ||
- (!channel->dev)))
+ if (wait_event_interruptible(c->wq, ch_has_mbo(c) || !c->dev))
return -ERESTARTSYS;
+ mutex_lock(&c->io_mutex);
}
- mutex_lock(&channel->io_mutex);
- if (unlikely(!channel->dev)) {
- mutex_unlock(&channel->io_mutex);
- err = -EPIPE;
- goto error;
+ if (unlikely(!c->dev)) {
+ ret = -EPIPE;
+ goto unlock;
}
- mutex_unlock(&channel->io_mutex);
- max_len = channel->cfg->buffer_size;
+ max_len = c->cfg->buffer_size;
actual_len = min(count, max_len);
mbo->buffer_length = actual_len;
- retval = copy_from_user(mbo->virt_address, buf, mbo->buffer_length);
- if (retval) {
- err = -EIO;
- goto error;
+ if (copy_from_user(mbo->virt_address, buf, mbo->buffer_length)) {
+ ret = -EFAULT;
+ goto put_mbo;
}
ret = most_submit_mbo(mbo);
- if (ret) {
- pr_info("submitting MBO to core failed\n");
- err = ret;
- goto error;
- }
- return actual_len - retval;
-error:
+ if (ret)
+ goto put_mbo;
+
+ mutex_unlock(&c->io_mutex);
+ return actual_len;
+put_mbo:
most_put_mbo(mbo);
- return err;
+unlock:
+ mutex_unlock(&c->io_mutex);
+ return ret;
}
/**
static ssize_t
aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset)
{
- ssize_t retval;
- size_t not_copied, proc_len;
+ size_t to_copy, not_copied, copied;
struct mbo *mbo;
- struct aim_channel *channel = filp->private_data;
+ struct aim_channel *c = filp->private_data;
- if (channel->keep_mbo) {
- mbo = channel->stacked_mbo;
- channel->keep_mbo = false;
- goto start_copy;
- }
- while ((!kfifo_out(&channel->fifo, &mbo, 1)) && (channel->dev)) {
+ mutex_lock(&c->io_mutex);
+ while (c->dev && !kfifo_peek(&c->fifo, &mbo)) {
+ mutex_unlock(&c->io_mutex);
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
- if (wait_event_interruptible(channel->wq,
- (!kfifo_is_empty(&channel->fifo) ||
- (!channel->dev))))
+ if (wait_event_interruptible(c->wq,
+ (!kfifo_is_empty(&c->fifo) ||
+ (!c->dev))))
return -ERESTARTSYS;
+ mutex_lock(&c->io_mutex);
}
-start_copy:
/* make sure we don't submit to gone devices */
- mutex_lock(&channel->io_mutex);
- if (unlikely(!channel->dev)) {
- mutex_unlock(&channel->io_mutex);
+ if (unlikely(!c->dev)) {
+ mutex_unlock(&c->io_mutex);
return -EIO;
}
- if (count < mbo->processed_length)
- channel->keep_mbo = true;
-
- proc_len = min((int)count,
- (int)(mbo->processed_length - channel->mbo_offs));
+ to_copy = min_t(size_t,
+ count,
+ mbo->processed_length - c->mbo_offs);
not_copied = copy_to_user(buf,
- mbo->virt_address + channel->mbo_offs,
- proc_len);
+ mbo->virt_address + c->mbo_offs,
+ to_copy);
- retval = not_copied ? proc_len - not_copied : proc_len;
+ copied = to_copy - not_copied;
- if (channel->keep_mbo) {
- channel->mbo_offs = retval;
- channel->stacked_mbo = mbo;
- } else {
+ c->mbo_offs += copied;
+ if (c->mbo_offs >= mbo->processed_length) {
+ kfifo_skip(&c->fifo);
most_put_mbo(mbo);
- channel->mbo_offs = 0;
+ c->mbo_offs = 0;
}
- mutex_unlock(&channel->io_mutex);
- return retval;
-}
-
-static inline bool __must_check IS_ERR_OR_FALSE(int x)
-{
- return x <= 0;
+ mutex_unlock(&c->io_mutex);
+ return copied;
}
static unsigned int aim_poll(struct file *filp, poll_table *wait)
if (!kfifo_is_empty(&c->fifo))
mask |= POLLIN | POLLRDNORM;
} else {
- if (!IS_ERR_OR_FALSE(channel_has_mbo(c->iface, c->channel_id)))
+ if (ch_has_mbo(c))
mask |= POLLOUT | POLLWRNORM;
}
return mask;
*/
static int aim_disconnect_channel(struct most_interface *iface, int channel_id)
{
- struct aim_channel *channel;
- unsigned long flags;
+ struct aim_channel *c;
if (!iface) {
pr_info("Bad interface pointer\n");
return -EINVAL;
}
- channel = get_channel(iface, channel_id);
- if (!channel)
+ c = get_channel(iface, channel_id);
+ if (!c)
return -ENXIO;
- mutex_lock(&channel->io_mutex);
- channel->dev = NULL;
- mutex_unlock(&channel->io_mutex);
-
- if (atomic_read(&channel->access_ref)) {
- device_destroy(aim_class, channel->devno);
- cdev_del(&channel->cdev);
- kfifo_free(&channel->fifo);
- ida_simple_remove(&minor_id, MINOR(channel->devno));
- spin_lock_irqsave(&ch_list_lock, flags);
- list_del(&channel->list);
- spin_unlock_irqrestore(&ch_list_lock, flags);
- kfree(channel);
+ mutex_lock(&c->io_mutex);
+ spin_lock(&c->unlink);
+ c->dev = NULL;
+ spin_unlock(&c->unlink);
+ if (c->access_ref) {
+ stop_channel(c);
+ wake_up_interruptible(&c->wq);
+ mutex_unlock(&c->io_mutex);
} else {
- wake_up_interruptible(&channel->wq);
+ destroy_cdev(c);
+ mutex_unlock(&c->io_mutex);
+ kfree(c);
}
return 0;
}
*/
static int aim_rx_completion(struct mbo *mbo)
{
- struct aim_channel *channel;
+ struct aim_channel *c;
if (!mbo)
return -EINVAL;
- channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
- if (!channel)
+ c = get_channel(mbo->ifp, mbo->hdm_channel_id);
+ if (!c)
return -ENXIO;
- kfifo_in(&channel->fifo, &mbo, 1);
+ spin_lock(&c->unlink);
+ if (!c->access_ref || !c->dev) {
+ spin_unlock(&c->unlink);
+ return -EFAULT;
+ }
+ kfifo_in(&c->fifo, &mbo, 1);
+ spin_unlock(&c->unlink);
#ifdef DEBUG_MESG
- if (kfifo_is_full(&channel->fifo))
+ if (kfifo_is_full(&c->fifo))
pr_info("WARN: Fifo is full\n");
#endif
- wake_up_interruptible(&channel->wq);
+ wake_up_interruptible(&c->wq);
return 0;
}
*/
static int aim_tx_completion(struct most_interface *iface, int channel_id)
{
- struct aim_channel *channel;
+ struct aim_channel *c;
if (!iface) {
pr_info("Bad interface pointer\n");
return -EINVAL;
}
- channel = get_channel(iface, channel_id);
- if (!channel)
+ c = get_channel(iface, channel_id);
+ if (!c)
return -ENXIO;
- wake_up_interruptible(&channel->wq);
+ wake_up_interruptible(&c->wq);
return 0;
}
-static struct most_aim cdev_aim;
-
/**
* aim_probe - probe function of the driver module
* @iface: pointer to interface instance
struct most_channel_config *cfg,
struct kobject *parent, char *name)
{
- struct aim_channel *channel;
+ struct aim_channel *c;
unsigned long cl_flags;
int retval;
int current_minor;
pr_info("Probing AIM with bad arguments");
return -EINVAL;
}
- channel = get_channel(iface, channel_id);
- if (channel)
+ c = get_channel(iface, channel_id);
+ if (c)
return -EEXIST;
current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL);
if (current_minor < 0)
return current_minor;
- channel = kzalloc(sizeof(*channel), GFP_KERNEL);
- if (!channel) {
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
+ if (!c) {
retval = -ENOMEM;
goto error_alloc_channel;
}
- channel->devno = MKDEV(major, current_minor);
- cdev_init(&channel->cdev, &channel_fops);
- channel->cdev.owner = THIS_MODULE;
- cdev_add(&channel->cdev, channel->devno, 1);
- channel->iface = iface;
- channel->cfg = cfg;
- channel->channel_id = channel_id;
- channel->mbo_offs = 0;
- atomic_set(&channel->access_ref, -1);
- INIT_KFIFO(channel->fifo);
- retval = kfifo_alloc(&channel->fifo, cfg->num_buffers, GFP_KERNEL);
+ c->devno = MKDEV(major, current_minor);
+ cdev_init(&c->cdev, &channel_fops);
+ c->cdev.owner = THIS_MODULE;
+ cdev_add(&c->cdev, c->devno, 1);
+ c->iface = iface;
+ c->cfg = cfg;
+ c->channel_id = channel_id;
+ c->access_ref = 0;
+ spin_lock_init(&c->unlink);
+ INIT_KFIFO(c->fifo);
+ retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL);
if (retval) {
pr_info("failed to alloc channel kfifo");
goto error_alloc_kfifo;
}
- init_waitqueue_head(&channel->wq);
- mutex_init(&channel->io_mutex);
+ init_waitqueue_head(&c->wq);
+ mutex_init(&c->io_mutex);
spin_lock_irqsave(&ch_list_lock, cl_flags);
- list_add_tail(&channel->list, &channel_list);
+ list_add_tail(&c->list, &channel_list);
spin_unlock_irqrestore(&ch_list_lock, cl_flags);
- channel->dev = device_create(aim_class,
+ c->dev = device_create(aim_class,
NULL,
- channel->devno,
+ c->devno,
NULL,
"%s", name);
- retval = IS_ERR(channel->dev);
+ retval = IS_ERR(c->dev);
if (retval) {
pr_info("failed to create new device node %s\n", name);
goto error_create_device;
}
- kobject_uevent(&channel->dev->kobj, KOBJ_ADD);
+ kobject_uevent(&c->dev->kobj, KOBJ_ADD);
return 0;
error_create_device:
- kfifo_free(&channel->fifo);
- list_del(&channel->list);
+ kfifo_free(&c->fifo);
+ list_del(&c->list);
error_alloc_kfifo:
- cdev_del(&channel->cdev);
- kfree(channel);
+ cdev_del(&c->cdev);
+ kfree(c);
error_alloc_channel:
ida_simple_remove(&minor_id, current_minor);
return retval;
static void __exit mod_exit(void)
{
- struct aim_channel *channel, *tmp;
+ struct aim_channel *c, *tmp;
pr_info("exit module\n");
most_deregister_aim(&cdev_aim);
- list_for_each_entry_safe(channel, tmp, &channel_list, list) {
- device_destroy(aim_class, channel->devno);
- cdev_del(&channel->cdev);
- kfifo_free(&channel->fifo);
- list_del(&channel->list);
- ida_simple_remove(&minor_id, MINOR(channel->devno));
- kfree(channel);
+ list_for_each_entry_safe(c, tmp, &channel_list, list) {
+ destroy_cdev(c);
+ kfree(c);
}
class_destroy(aim_class);
unregister_chrdev_region(aim_devno, 1);
u32 len = mbo->processed_length;
struct sk_buff *skb;
struct net_device *dev;
+ unsigned int skb_len;
nd = get_net_dev_context(mbo->ifp);
if (!nd || !nd->channels_opened || nd->rx.ch_id != mbo->hdm_channel_id)
memcpy(skb_put(skb, len), buf, len);
skb->protocol = eth_type_trans(skb, dev);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += skb->len;
- netif_rx(skb);
+ skb_len = skb->len;
+ if (netif_rx(skb) == NET_RX_SUCCESS) {
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb_len;
+ } else {
+ dev->stats.rx_dropped++;
+ }
out:
most_put_mbo(mbo);
struct lld_global_vars_t {
bool dim_is_initialized;
bool mcm_is_initialized;
- struct dim2_regs *dim2; /* DIM2 core base address */
+ struct dim2_regs __iomem *dim2; /* DIM2 core base address */
u32 dbr_map[DBR_MAP_SIZE];
};
/* -------------------------------------------------------------------------- */
/* API */
-u8 dim_startup(void *dim_base_address, u32 mlb_clock)
+u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock)
{
g.dim_is_initialized = false;
#define _DIM2_HAL_H
#include <linux/types.h>
+#include "dim2_reg.h"
#ifdef __cplusplus
extern "C" {
u16 done_sw_buffers_number; /*< Done software buffers number. */
};
-u8 dim_startup(void *dim_base_address, u32 mlb_clock);
+u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock);
void dim_shutdown(void);
bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number);
-u32 dimcb_io_read(u32 *ptr32);
+u32 dimcb_io_read(u32 __iomem *ptr32);
-void dimcb_io_write(u32 *ptr32, u32 value);
+void dimcb_io_write(u32 __iomem *ptr32, u32 value);
void dimcb_on_error(u8 error_id, const char *error_message);
struct most_channel_capability capabilities[DMA_CHANNELS];
struct most_interface most_iface;
char name[16 + sizeof "dim2-"];
- void *io_base;
+ void __iomem *io_base;
unsigned int irq_ahb0;
int clk_speed;
struct task_struct *netinfo_task;
* dimcb_io_read - callback from HAL to read an I/O register
* @ptr32: register address
*/
-u32 dimcb_io_read(u32 *ptr32)
+u32 dimcb_io_read(u32 __iomem *ptr32)
{
- return __raw_readl(ptr32);
+ return readl(ptr32);
}
/**
* @ptr32: register address
* @value: value to write
*/
-void dimcb_io_write(u32 *ptr32, u32 value)
+void dimcb_io_write(u32 __iomem *ptr32, u32 value)
{
- __raw_writel(value, ptr32);
+ writel(value, ptr32);
}
/**
/* platform dependent data for dim2 interface */
struct dim2_platform_data {
- int (*init)(struct dim2_platform_data *pd, void *io_base,
+ int (*init)(struct dim2_platform_data *pd, void __iomem *io_base,
int clk_speed);
void (*destroy)(struct dim2_platform_data *pd);
void *priv;
static struct class *most_class;
static struct device *class_glue_dir;
static struct ida mdev_id;
-static int modref;
static int dummy_num_buffers;
struct most_c_aim_obj {
struct most_c_aim_obj aim1;
struct list_head trash_fifo;
struct task_struct *hdm_enqueue_task;
- struct mutex stop_task_mutex;
wait_queue_head_t hdm_fifo_wq;
};
struct most_inst_obj {
int dev_id;
- atomic_t tainted;
struct most_interface *iface;
struct list_head channel_list;
struct most_c_obj *channel[MAX_CHANNELS];
struct list_head list;
};
+static const struct {
+ int most_ch_data_type;
+ char *name;
+} ch_data_type[] = { { MOST_CH_CONTROL, "control\n" },
+ { MOST_CH_ASYNC, "async\n" },
+ { MOST_CH_SYNC, "sync\n" },
+ { MOST_CH_ISOC_AVP, "isoc_avp\n"} };
+
#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj)
/**
_mbo; \
})
-static struct mutex deregister_mutex;
-
/* ___ ___
* ___C H A N N E L___
*/
struct most_c_attr *attr,
char *buf)
{
- if (c->cfg.data_type & MOST_CH_CONTROL)
- return snprintf(buf, PAGE_SIZE, "control\n");
- else if (c->cfg.data_type & MOST_CH_ASYNC)
- return snprintf(buf, PAGE_SIZE, "async\n");
- else if (c->cfg.data_type & MOST_CH_SYNC)
- return snprintf(buf, PAGE_SIZE, "sync\n");
- else if (c->cfg.data_type & MOST_CH_ISOC_AVP)
- return snprintf(buf, PAGE_SIZE, "isoc_avp\n");
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
+ if (c->cfg.data_type & ch_data_type[i].most_ch_data_type)
+ return snprintf(buf, PAGE_SIZE, ch_data_type[i].name);
+ }
return snprintf(buf, PAGE_SIZE, "unconfigured\n");
}
const char *buf,
size_t count)
{
- if (!strcmp(buf, "control\n")) {
- c->cfg.data_type = MOST_CH_CONTROL;
- } else if (!strcmp(buf, "async\n")) {
- c->cfg.data_type = MOST_CH_ASYNC;
- } else if (!strcmp(buf, "sync\n")) {
- c->cfg.data_type = MOST_CH_SYNC;
- } else if (!strcmp(buf, "isoc_avp\n")) {
- c->cfg.data_type = MOST_CH_ISOC_AVP;
- } else {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
+ if (!strcmp(buf, ch_data_type[i].name)) {
+ c->cfg.data_type = ch_data_type[i].most_ch_data_type;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(ch_data_type)) {
pr_info("WARN: invalid attribute settings\n");
return -EINVAL;
}
return c;
}
-/**
- * destroy_most_c_obj - channel release function
- * @c: pointer to channel object
- *
- * This decrements the reference counter of the channel object.
- * If the reference count turns zero, its release function is called.
- */
-static void destroy_most_c_obj(struct most_c_obj *c)
-{
- if (c->aim0.ptr)
- c->aim0.ptr->disconnect_channel(c->iface, c->channel_id);
- if (c->aim1.ptr)
- c->aim1.ptr->disconnect_channel(c->iface, c->channel_id);
- c->aim0.ptr = NULL;
- c->aim1.ptr = NULL;
-
- mutex_lock(&deregister_mutex);
- flush_trash_fifo(c);
- flush_channel_fifos(c);
- mutex_unlock(&deregister_mutex);
- kobject_put(&c->kobj);
-}
-
/* ___ ___
* ___I N S T A N C E___
*/
{
struct most_c_obj *c, *tmp;
- /* need to destroy channels first, since
- * each channel incremented the
- * reference count of the inst->kobj
- */
list_for_each_entry_safe(c, tmp, &inst->channel_list, list) {
- destroy_most_c_obj(c);
+ flush_trash_fifo(c);
+ flush_channel_fifos(c);
+ kobject_put(&c->kobj);
}
kobject_put(&inst->kobj);
}
else
return -ENOSPC;
+ *aim_ptr = aim_obj->driver;
ret = aim_obj->driver->probe_channel(c->iface, c->channel_id,
&c->cfg, &c->kobj, mdev_devnod);
- if (ret)
+ if (ret) {
+ *aim_ptr = NULL;
return ret;
- *aim_ptr = aim_obj->driver;
+ }
+
return len;
}
if (IS_ERR(c))
return -ENODEV;
+ if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id))
+ return -EIO;
if (c->aim0.ptr == aim_obj->driver)
c->aim0.ptr = NULL;
if (c->aim1.ptr == aim_obj->driver)
c->aim1.ptr = NULL;
- if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id))
- return -EIO;
return len;
}
*/
int most_submit_mbo(struct mbo *mbo)
{
- struct most_c_obj *c;
- struct most_inst_obj *i;
-
if (unlikely((!mbo) || (!mbo->context))) {
pr_err("Bad MBO or missing channel reference\n");
return -EINVAL;
}
- c = mbo->context;
- i = c->inst;
-
- if (unlikely(atomic_read(&i->tainted)))
- return -ENODEV;
nq_hdm_mbo(mbo);
return 0;
return i->channel[id];
}
-int channel_has_mbo(struct most_interface *iface, int id)
+int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim)
{
struct most_c_obj *c = get_channel_by_iface(iface, id);
unsigned long flags;
if (unlikely(!c))
return -EINVAL;
+ if (c->aim0.refs && c->aim1.refs &&
+ ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) ||
+ (aim == c->aim1.ptr && c->aim1.num_buffers <= 0)))
+ return 0;
+
spin_lock_irqsave(&c->fifo_lock, flags);
empty = list_empty(&c->fifo);
spin_unlock_irqrestore(&c->fifo_lock, flags);
*/
void most_put_mbo(struct mbo *mbo)
{
- struct most_c_obj *c;
- struct most_inst_obj *i;
-
- c = mbo->context;
- i = c->inst;
+ struct most_c_obj *c = mbo->context;
- if (unlikely(atomic_read(&i->tainted))) {
- mbo->status = MBO_E_CLOSE;
- trash_mbo(mbo);
- return;
- }
if (c->cfg.direction == MOST_CH_TX) {
arm_mbo(mbo);
return;
mutex_unlock(&c->start_mutex);
return -ENOLCK;
}
- modref++;
c->cfg.extra_len = 0;
if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) {
error:
module_put(iface->mod);
- modref--;
mutex_unlock(&c->start_mutex);
return ret;
}
if (c->aim0.refs + c->aim1.refs >= 2)
goto out;
- mutex_lock(&c->stop_task_mutex);
if (c->hdm_enqueue_task)
kthread_stop(c->hdm_enqueue_task);
c->hdm_enqueue_task = NULL;
- mutex_unlock(&c->stop_task_mutex);
-
- mutex_lock(&deregister_mutex);
- if (atomic_read(&c->inst->tainted)) {
- mutex_unlock(&deregister_mutex);
- mutex_unlock(&c->start_mutex);
- return -ENODEV;
- }
- mutex_unlock(&deregister_mutex);
- if (iface->mod && modref) {
+ if (iface->mod)
module_put(iface->mod);
- modref--;
- }
c->is_poisoned = true;
if (c->iface->poison_channel(c->iface, c->channel_id)) {
inst = create_most_inst_obj(name);
if (!inst) {
pr_info("Failed to allocate interface instance\n");
+ ida_simple_remove(&mdev_id, id);
return ERR_PTR(-ENOMEM);
}
INIT_LIST_HEAD(&inst->channel_list);
inst->iface = iface;
inst->dev_id = id;
- atomic_set(&inst->tainted, 0);
list_add_tail(&inst->list, &instance_list);
for (i = 0; i < iface->num_channels; i++) {
init_completion(&c->cleanup);
atomic_set(&c->mbo_ref, 0);
mutex_init(&c->start_mutex);
- mutex_init(&c->stop_task_mutex);
list_add_tail(&c->list, &inst->channel_list);
}
pr_info("registered new MOST device mdev%d (%s)\n",
free_instance:
pr_info("Failed allocate channel(s)\n");
list_del(&inst->list);
+ ida_simple_remove(&mdev_id, id);
destroy_most_inst_obj(inst);
return ERR_PTR(-ENOMEM);
}
struct most_inst_obj *i = iface->priv;
struct most_c_obj *c;
- mutex_lock(&deregister_mutex);
if (unlikely(!i)) {
pr_info("Bad Interface\n");
- mutex_unlock(&deregister_mutex);
return;
}
pr_info("deregistering MOST device %s (%s)\n", i->kobj.name,
iface->description);
- atomic_set(&i->tainted, 1);
- mutex_unlock(&deregister_mutex);
-
- while (modref) {
- if (iface->mod && modref)
- module_put(iface->mod);
- modref--;
- }
-
list_for_each_entry(c, &i->channel_list, list) {
- if (c->aim0.refs + c->aim1.refs <= 0)
- continue;
-
- mutex_lock(&c->stop_task_mutex);
- if (c->hdm_enqueue_task)
- kthread_stop(c->hdm_enqueue_task);
- c->hdm_enqueue_task = NULL;
- mutex_unlock(&c->stop_task_mutex);
-
- if (iface->poison_channel(iface, c->channel_id))
- pr_err("Can't poison channel %d\n", c->channel_id);
+ if (c->aim0.ptr)
+ c->aim0.ptr->disconnect_channel(c->iface,
+ c->channel_id);
+ if (c->aim1.ptr)
+ c->aim1.ptr->disconnect_channel(c->iface,
+ c->channel_id);
+ c->aim0.ptr = NULL;
+ c->aim1.ptr = NULL;
}
+
ida_simple_remove(&mdev_id, i->dev_id);
list_del(&i->list);
destroy_most_inst_obj(i);
pr_info("init()\n");
INIT_LIST_HEAD(&instance_list);
INIT_LIST_HEAD(&aim_list);
- mutex_init(&deregister_mutex);
ida_init(&mdev_id);
if (bus_register(&most_bus)) {
class_glue_dir =
device_create(most_class, NULL, 0, NULL, "mostcore");
- if (!class_glue_dir)
+ if (IS_ERR(class_glue_dir))
goto exit_driver;
most_aim_kset =
struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx,
struct most_aim *);
void most_put_mbo(struct mbo *mbo);
-int channel_has_mbo(struct most_interface *iface, int channel_idx);
+int channel_has_mbo(struct most_interface *iface, int channel_idx,
+ struct most_aim *aim);
int most_start_channel(struct most_interface *iface, int channel_idx,
struct most_aim *);
int most_stop_channel(struct most_interface *iface, int channel_idx,
};
#endif
-/*
- * spinand_cmd - to process a command to send to the SPI Nand
+/**
+ * spinand_cmd - process a command to send to the SPI Nand
* Description:
* Set up the command buffer to send to the SPI controller.
* The command buffer has to initialized to 0.
return spi_sync(spi, &message);
}
-/*
- * spinand_read_id- Read SPI Nand ID
+/**
+ * spinand_read_id - Read SPI Nand ID
* Description:
- * Read ID: read two ID bytes from the SPI Nand device
+ * read two ID bytes from the SPI Nand device
*/
static int spinand_read_id(struct spi_device *spi_nand, u8 *id)
{
return retval;
}
-/*
- * spinand_read_status- send command 0xf to the SPI Nand status register
+/**
+ * spinand_read_status - send command 0xf to the SPI Nand status register
* Description:
* After read, write, or erase, the Nand device is expected to set the
* busy status.
}
/**
- * spinand_get_otp- send command 0xf to read the SPI Nand OTP register
+ * spinand_get_otp - send command 0xf to read the SPI Nand OTP register
* Description:
* There is one bit( bit 0x10 ) to set or to clear the internal ECC.
* Enable chip internal ECC, set the bit to 1
}
/**
- * spinand_set_otp- send command 0x1f to write the SPI Nand OTP register
+ * spinand_set_otp - send command 0x1f to write the SPI Nand OTP register
* Description:
* There is one bit( bit 0x10 ) to set or to clear the internal ECC.
* Enable chip internal ECC, set the bit to 1
int retval;
struct spinand_cmd cmd = {0};
- cmd.cmd = CMD_WRITE_REG,
- cmd.n_addr = 1,
- cmd.addr[0] = REG_OTP,
- cmd.n_tx = 1,
- cmd.tx_buf = otp,
+ cmd.cmd = CMD_WRITE_REG;
+ cmd.n_addr = 1;
+ cmd.addr[0] = REG_OTP;
+ cmd.n_tx = 1;
+ cmd.tx_buf = otp;
retval = spinand_cmd(spi_nand, &cmd);
if (retval < 0)
#ifdef CONFIG_MTD_SPINAND_ONDIEECC
/**
- * spinand_enable_ecc- send command 0x1f to write the SPI Nand OTP register
+ * spinand_enable_ecc - send command 0x1f to write the SPI Nand OTP register
* Description:
* There is one bit( bit 0x10 ) to set or to clear the internal ECC.
* Enable chip internal ECC, set the bit to 1
}
/**
- * spinand_write_enable- send command 0x06 to enable write or erase the
+ * spinand_write_enable - send command 0x06 to enable write or erase the
* Nand cells
* Description:
* Before write and erase the Nand cells, the write enable has to be set.
return spinand_cmd(spi_nand, &cmd);
}
-/*
- * spinand_read_from_cache- send command 0x03 to read out the data from the
- * cache register(2112 bytes max)
+/**
+ * spinand_read_from_cache - send command 0x03 to read out the data from the
+ * cache register (2112 bytes max)
* Description:
* The read can specify 1 to 2112 bytes of data read at the corresponding
* locations.
return spinand_cmd(spi_nand, &cmd);
}
-/*
- * spinand_read_page-to read a page with:
+/**
+ * spinand_read_page - read a page
* @page_id: the physical page number
* @offset: the location from 0 to 2111
* @len: number of bytes to read
* @rbuf: read buffer to hold @len bytes
*
* Description:
- * The read includes two commands to the Nand: 0x13 and 0x03 commands
+ * The read includes two commands to the Nand - 0x13 and 0x03 commands
* Poll to read status to wait for tRD time.
*/
static int spinand_read_page(struct spi_device *spi_nand, u16 page_id,
return ret;
}
-/*
- * spinand_program_data_to_cache--to write a page to cache with:
+/**
+ * spinand_program_data_to_cache - write a page to cache
* @byte_id: the location to write to the cache
* @len: number of bytes to write
- * @rbuf: read buffer to hold @len bytes
+ * @wbuf: write buffer holding @len bytes
*
* Description:
* The write command used here is 0x84--indicating that the cache is
}
/**
- * spinand_program_execute--to write a page from cache to the Nand array with
+ * spinand_program_execute - write a page from cache to the Nand array
* @page_id: the physical page location to write the page.
*
* Description:
}
/**
- * spinand_program_page--to write a page with:
+ * spinand_program_page - write a page
* @page_id: the physical page location to write the page.
* @offset: the location from the cache starting from 0 to 2111
* @len: the number of bytes to write
- * @wbuf: the buffer to hold the number of bytes
+ * @buf: the buffer holding @len bytes
*
* Description:
* The commands used here are 0x06, 0x84, and 0x10--indicating that
#ifdef CONFIG_MTD_SPINAND_ONDIEECC
unsigned int i, j;
- enable_read_hw_ecc = 0;
wbuf = devm_kzalloc(&spi_nand->dev, CACHE_BUF, GFP_KERNEL);
+ if (!wbuf)
+ return -ENOMEM;
+
+ enable_read_hw_ecc = 0;
spinand_read_page(spi_nand, page_id, 0, CACHE_BUF, wbuf);
for (i = offset, j = 0; i < len; i++, j++)
}
/**
- * spinand_erase_block_erase--to erase a page with:
+ * spinand_erase_block_erase - erase a page
* @block_id: the physical block location to erase.
*
* Description:
}
/**
- * spinand_erase_block--to erase a page with:
+ * spinand_erase_block - erase a page
* @block_id: the physical block location to erase.
*
* Description:
}
/**
- * spinand_lock_block- send write register 0x1f command to the Nand device
+ * spinand_lock_block - send write register 0x1f command to the Nand device
*
* Description:
* After power up, all the Nand blocks are locked. This function allows
return ret;
}
-/*
+/**
* spinand_probe - [spinand Interface]
* @spi_nand: registered device driver.
*
* Description:
- * To set up the device driver parameters to make the device available.
+ * Set up the device driver parameters to make the device available.
*/
static int spinand_probe(struct spi_device *spi_nand)
{
return mtd_device_register(mtd, NULL, 0);
}
-/*
- * spinand_remove: Remove the device driver
+/**
+ * spinand_remove - remove the device driver
* @spi: the spi device.
*
* Description:
- * To remove the device driver parameters and free up allocated memories.
+ * Remove the device driver parameters and free up allocated memories.
*/
static int spinand_remove(struct spi_device *spi)
{
*
*/
-/* #define DEBUG */
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/atomic.h>
spin_lock(&nvec->rx_lock);
- /* add the received data to the work list
- and move the ring buffer pointer to the next entry */
+ /*
+ * Add the received data to the work list and move the ring buffer
+ * pointer to the next entry.
+ */
list_add_tail(&nvec->rx->node, &nvec->rx_data);
spin_unlock(&nvec->rx_lock);
platform_set_drvdata(pdev, led);
- ret = led_classdev_register(&pdev->dev, &led->cdev);
+ ret = devm_led_classdev_register(&pdev->dev, &led->cdev);
if (ret < 0)
return ret;
return 0;
}
-static int nvec_paz00_remove(struct platform_device *pdev)
-{
- struct nvec_led *led = platform_get_drvdata(pdev);
-
- led_classdev_unregister(&led->cdev);
-
- return 0;
-}
-
static struct platform_driver nvec_paz00_driver = {
.probe = nvec_paz00_probe,
- .remove = nvec_paz00_remove,
.driver = {
.name = "nvec-paz00",
},
case TYPE:
memcpy(power->bat_type, &res->plc, res->length - 2);
power->bat_type[res->length - 2] = '\0';
- /* this differs a little from the spec
- fill in more if you find some */
+ /*
+ * This differs a little from the spec fill in more if you find
+ * some.
+ */
if (!strncmp(power->bat_type, "Li", 30))
power->bat_type_enum = POWER_SUPPLY_TECHNOLOGY_LION;
else
if (counter >= ARRAY_SIZE(bat_iter))
counter = 0;
-/* AC status via sys req */
+ /* AC status via sys req */
nvec_write_async(power->nvec, buf, 2);
msleep(100);
-/* select a battery request function via round robin
- doing it all at once seems to overload the power supply */
+ /*
+ * Select a battery request function via round robin doing it all at
+ * once seems to overload the power supply.
+ */
buf[0] = NVEC_BAT;
buf[1] = bat_iter[counter++];
nvec_write_async(power->nvec, buf, 2);
urb->hcpriv = NULL;
/* For Isochronous transactions we need to update the URB packet status
- list from data in our private copy */
+ * list from data in our private copy
+ */
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
int i;
/*
if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
&& (priv->port == 0))
|| (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
-
if (!octeon_is_simulation()) {
-
union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
int interface = INTERFACE(priv->port);
int index = INDEX(priv->port);
if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
&& (priv->port == 0))
|| (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
-
if (!octeon_is_simulation()) {
-
union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
int interface = INTERFACE(priv->port);
int index = INDEX(priv->port);
}
total_remaining += skb_queue_len(&priv->tx_free_list[qos]);
}
- if (total_freed >= 0 && netif_queue_stopped(dev))
+ if (total_remaining < MAX_OUT_QUEUE_DEPTH && netif_queue_stopped(dev))
netif_wake_queue(dev);
if (total_remaining)
cvm_oct_kick_tx_poll_watchdog();
((ip_hdr(skb)->protocol == IPPROTO_TCP) ||
(ip_hdr(skb)->protocol == IPPROTO_UDP))) {
/* Use hardware checksum calc */
- pko_command.s.ipoffp1 = sizeof(struct ethhdr) + 1;
+ pko_command.s.ipoffp1 = skb_network_offset(skb) + 1;
}
if (USE_ASYNC_IOBDMA) {
+++ /dev/null
-config FB_OLPC_DCON
- tristate "One Laptop Per Child Display CONtroller support"
- depends on OLPC && FB
- depends on I2C
- depends on (GPIO_CS5535 || GPIO_CS5535=n)
- select BACKLIGHT_CLASS_DEVICE
- ---help---
- In order to support very low power operation, the XO laptop uses a
- secondary Display CONtroller, or DCON. This secondary controller
- is present in the video pipeline between the primary display
- controller (integrate into the processor or chipset) and the LCD
- panel. It allows the main processor/display controller to be
- completely powered off while still retaining an image on the display.
- This controller is only available on OLPC platforms. Unless you have
- one of these platforms, you will want to say 'N'.
-
-config FB_OLPC_DCON_1
- bool "OLPC XO-1 DCON support"
- depends on FB_OLPC_DCON && GPIO_CS5535
- default y
- ---help---
- Enable support for the DCON in XO-1 model laptops. The kernel
- communicates with the DCON using model-specific code. If you
- have an XO-1 (or if you're unsure what model you have), you should
- say 'Y'.
-
-config FB_OLPC_DCON_1_5
- bool "OLPC XO-1.5 DCON support"
- depends on FB_OLPC_DCON && ACPI
- default y
- ---help---
- Enable support for the DCON in XO-1.5 model laptops. The kernel
- communicates with the DCON using model-specific code. If you
- have an XO-1.5 (or if you're unsure what model you have), you
- should say 'Y'.
+++ /dev/null
-olpc-dcon-objs += olpc_dcon.o
-olpc-dcon-$(CONFIG_FB_OLPC_DCON_1) += olpc_dcon_xo_1.o
-olpc-dcon-$(CONFIG_FB_OLPC_DCON_1_5) += olpc_dcon_xo_1_5.o
-obj-$(CONFIG_FB_OLPC_DCON) += olpc-dcon.o
-
-
+++ /dev/null
-TODO:
- - see if vx855 gpio API can be made similar enough to cs5535 so we can
- share more code
- - allow simultaneous XO-1 and XO-1.5 support
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
-copy:
- Daniel Drake <dsd@laptop.org>
- Jens Frederich <jfrederich@gmail.com>
+++ /dev/null
-/*
- * Mainly by David Woodhouse, somewhat modified by Jordan Crouse
- *
- * Copyright © 2006-2007 Red Hat, Inc.
- * Copyright © 2006-2007 Advanced Micro Devices, Inc.
- * Copyright © 2009 VIA Technology, Inc.
- * Copyright (c) 2010-2011 Andres Salomon <dilinger@queued.net>
- *
- * This program is free software. You can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/backlight.h>
-#include <linux/device.h>
-#include <linux/uaccess.h>
-#include <linux/ctype.h>
-#include <linux/reboot.h>
-#include <linux/olpc-ec.h>
-#include <asm/tsc.h>
-#include <asm/olpc.h>
-
-#include "olpc_dcon.h"
-
-/* Module definitions */
-
-static ushort resumeline = 898;
-module_param(resumeline, ushort, 0444);
-
-static struct dcon_platform_data *pdata;
-
-/* I2C structures */
-
-/* Platform devices */
-static struct platform_device *dcon_device;
-
-static unsigned short normal_i2c[] = { 0x0d, I2C_CLIENT_END };
-
-static s32 dcon_write(struct dcon_priv *dcon, u8 reg, u16 val)
-{
- return i2c_smbus_write_word_data(dcon->client, reg, val);
-}
-
-static s32 dcon_read(struct dcon_priv *dcon, u8 reg)
-{
- return i2c_smbus_read_word_data(dcon->client, reg);
-}
-
-/* ===== API functions - these are called by a variety of users ==== */
-
-static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
-{
- u16 ver;
- int rc = 0;
-
- ver = dcon_read(dcon, DCON_REG_ID);
- if ((ver >> 8) != 0xDC) {
- pr_err("DCON ID not 0xDCxx: 0x%04x instead.\n", ver);
- rc = -ENXIO;
- goto err;
- }
-
- if (is_init) {
- pr_info("Discovered DCON version %x\n", ver & 0xFF);
- rc = pdata->init(dcon);
- if (rc != 0) {
- pr_err("Unable to init.\n");
- goto err;
- }
- }
-
- if (ver < 0xdc02) {
- dev_err(&dcon->client->dev,
- "DCON v1 is unsupported, giving up..\n");
- rc = -ENODEV;
- goto err;
- }
-
- /* SDRAM setup/hold time */
- dcon_write(dcon, 0x3a, 0xc040);
- dcon_write(dcon, DCON_REG_MEM_OPT_A, 0x0000); /* clear option bits */
- dcon_write(dcon, DCON_REG_MEM_OPT_A,
- MEM_DLL_CLOCK_DELAY | MEM_POWER_DOWN);
- dcon_write(dcon, DCON_REG_MEM_OPT_B, MEM_SOFT_RESET);
-
- /* Colour swizzle, AA, no passthrough, backlight */
- if (is_init) {
- dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE |
- MODE_CSWIZZLE | MODE_COL_AA;
- }
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
-
- /* Set the scanline to interrupt on during resume */
- dcon_write(dcon, DCON_REG_SCAN_INT, resumeline);
-
-err:
- return rc;
-}
-
-/*
- * The smbus doesn't always come back due to what is believed to be
- * hardware (power rail) bugs. For older models where this is known to
- * occur, our solution is to attempt to wait for the bus to stabilize;
- * if it doesn't happen, cut power to the dcon, repower it, and wait
- * for the bus to stabilize. Rinse, repeat until we have a working
- * smbus. For newer models, we simply BUG(); we want to know if this
- * still happens despite the power fixes that have been made!
- */
-static int dcon_bus_stabilize(struct dcon_priv *dcon, int is_powered_down)
-{
- unsigned long timeout;
- u8 pm;
- int x;
-
-power_up:
- if (is_powered_down) {
- pm = 1;
- x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
- if (x) {
- pr_warn("unable to force dcon to power up: %d!\n", x);
- return x;
- }
- usleep_range(10000, 11000); /* we'll be conservative */
- }
-
- pdata->bus_stabilize_wiggle();
-
- for (x = -1, timeout = 50; timeout && x < 0; timeout--) {
- usleep_range(1000, 1100);
- x = dcon_read(dcon, DCON_REG_ID);
- }
- if (x < 0) {
- pr_err("unable to stabilize dcon's smbus, reasserting power and praying.\n");
- BUG_ON(olpc_board_at_least(olpc_board(0xc2)));
- pm = 0;
- olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
- msleep(100);
- is_powered_down = 1;
- goto power_up; /* argh, stupid hardware.. */
- }
-
- if (is_powered_down)
- return dcon_hw_init(dcon, 0);
- return 0;
-}
-
-static void dcon_set_backlight(struct dcon_priv *dcon, u8 level)
-{
- dcon->bl_val = level;
- dcon_write(dcon, DCON_REG_BRIGHT, dcon->bl_val);
-
- /* Purposely turn off the backlight when we go to level 0 */
- if (dcon->bl_val == 0) {
- dcon->disp_mode &= ~MODE_BL_ENABLE;
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
- } else if (!(dcon->disp_mode & MODE_BL_ENABLE)) {
- dcon->disp_mode |= MODE_BL_ENABLE;
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
- }
-}
-
-/* Set the output type to either color or mono */
-static int dcon_set_mono_mode(struct dcon_priv *dcon, bool enable_mono)
-{
- if (dcon->mono == enable_mono)
- return 0;
-
- dcon->mono = enable_mono;
-
- if (enable_mono) {
- dcon->disp_mode &= ~(MODE_CSWIZZLE | MODE_COL_AA);
- dcon->disp_mode |= MODE_MONO_LUMA;
- } else {
- dcon->disp_mode &= ~(MODE_MONO_LUMA);
- dcon->disp_mode |= MODE_CSWIZZLE | MODE_COL_AA;
- }
-
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
- return 0;
-}
-
-/* For now, this will be really stupid - we need to address how
- * DCONLOAD works in a sleep and account for it accordingly
- */
-
-static void dcon_sleep(struct dcon_priv *dcon, bool sleep)
-{
- int x;
-
- /* Turn off the backlight and put the DCON to sleep */
-
- if (dcon->asleep == sleep)
- return;
-
- if (!olpc_board_at_least(olpc_board(0xc2)))
- return;
-
- if (sleep) {
- u8 pm = 0;
-
- x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
- if (x)
- pr_warn("unable to force dcon to power down: %d!\n", x);
- else
- dcon->asleep = sleep;
- } else {
- /* Only re-enable the backlight if the backlight value is set */
- if (dcon->bl_val != 0)
- dcon->disp_mode |= MODE_BL_ENABLE;
- x = dcon_bus_stabilize(dcon, 1);
- if (x)
- pr_warn("unable to reinit dcon hardware: %d!\n", x);
- else
- dcon->asleep = sleep;
-
- /* Restore backlight */
- dcon_set_backlight(dcon, dcon->bl_val);
- }
-
- /* We should turn off some stuff in the framebuffer - but what? */
-}
-
-/* the DCON seems to get confused if we change DCONLOAD too
- * frequently -- i.e., approximately faster than frame time.
- * normally we don't change it this fast, so in general we won't
- * delay here.
- */
-static void dcon_load_holdoff(struct dcon_priv *dcon)
-{
- ktime_t delta_t, now;
-
- while (1) {
- now = ktime_get();
- delta_t = ktime_sub(now, dcon->load_time);
- if (ktime_to_ns(delta_t) > NSEC_PER_MSEC * 20)
- break;
- mdelay(4);
- }
-}
-
-static bool dcon_blank_fb(struct dcon_priv *dcon, bool blank)
-{
- int err;
-
- console_lock();
- if (!lock_fb_info(dcon->fbinfo)) {
- console_unlock();
- dev_err(&dcon->client->dev, "unable to lock framebuffer\n");
- return false;
- }
-
- dcon->ignore_fb_events = true;
- err = fb_blank(dcon->fbinfo,
- blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
- dcon->ignore_fb_events = false;
- unlock_fb_info(dcon->fbinfo);
- console_unlock();
-
- if (err) {
- dev_err(&dcon->client->dev, "couldn't %sblank framebuffer\n",
- blank ? "" : "un");
- return false;
- }
- return true;
-}
-
-/* Set the source of the display (CPU or DCON) */
-static void dcon_source_switch(struct work_struct *work)
-{
- struct dcon_priv *dcon = container_of(work, struct dcon_priv,
- switch_source);
- int source = dcon->pending_src;
-
- if (dcon->curr_src == source)
- return;
-
- dcon_load_holdoff(dcon);
-
- dcon->switched = false;
-
- switch (source) {
- case DCON_SOURCE_CPU:
- pr_info("dcon_source_switch to CPU\n");
- /* Enable the scanline interrupt bit */
- if (dcon_write(dcon, DCON_REG_MODE,
- dcon->disp_mode | MODE_SCAN_INT))
- pr_err("couldn't enable scanline interrupt!\n");
- else
- /* Wait up to one second for the scanline interrupt */
- wait_event_timeout(dcon->waitq, dcon->switched, HZ);
-
- if (!dcon->switched)
- pr_err("Timeout entering CPU mode; expect a screen glitch.\n");
-
- /* Turn off the scanline interrupt */
- if (dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode))
- pr_err("couldn't disable scanline interrupt!\n");
-
- /*
- * Ideally we'd like to disable interrupts here so that the
- * fb unblanking and DCON turn on happen at a known time value;
- * however, we can't do that right now with fb_blank
- * messing with semaphores.
- *
- * For now, we just hope..
- */
- if (!dcon_blank_fb(dcon, false)) {
- pr_err("Failed to enter CPU mode\n");
- dcon->pending_src = DCON_SOURCE_DCON;
- return;
- }
-
- /* And turn off the DCON */
- pdata->set_dconload(1);
- dcon->load_time = ktime_get();
-
- pr_info("The CPU has control\n");
- break;
- case DCON_SOURCE_DCON:
- {
- ktime_t delta_t;
-
- pr_info("dcon_source_switch to DCON\n");
-
- /* Clear DCONLOAD - this implies that the DCON is in control */
- pdata->set_dconload(0);
- dcon->load_time = ktime_get();
-
- wait_event_timeout(dcon->waitq, dcon->switched, HZ/2);
-
- if (!dcon->switched) {
- pr_err("Timeout entering DCON mode; expect a screen glitch.\n");
- } else {
- /* sometimes the DCON doesn't follow its own rules,
- * and doesn't wait for two vsync pulses before
- * ack'ing the frame load with an IRQ. the result
- * is that the display shows the *previously*
- * loaded frame. we can detect this by looking at
- * the time between asserting DCONLOAD and the IRQ --
- * if it's less than 20msec, then the DCON couldn't
- * have seen two VSYNC pulses. in that case we
- * deassert and reassert, and hope for the best.
- * see http://dev.laptop.org/ticket/9664
- */
- delta_t = ktime_sub(dcon->irq_time, dcon->load_time);
- if (dcon->switched && ktime_to_ns(delta_t)
- < NSEC_PER_MSEC * 20) {
- pr_err("missed loading, retrying\n");
- pdata->set_dconload(1);
- mdelay(41);
- pdata->set_dconload(0);
- dcon->load_time = ktime_get();
- mdelay(41);
- }
- }
-
- dcon_blank_fb(dcon, true);
- pr_info("The DCON has control\n");
- break;
- }
- default:
- BUG();
- }
-
- dcon->curr_src = source;
-}
-
-static void dcon_set_source(struct dcon_priv *dcon, int arg)
-{
- if (dcon->pending_src == arg)
- return;
-
- dcon->pending_src = arg;
-
- if (dcon->curr_src != arg)
- schedule_work(&dcon->switch_source);
-}
-
-static void dcon_set_source_sync(struct dcon_priv *dcon, int arg)
-{
- dcon_set_source(dcon, arg);
- flush_scheduled_work();
-}
-
-static ssize_t dcon_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%4.4X\n", dcon->disp_mode);
-}
-
-static ssize_t dcon_sleep_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", dcon->asleep);
-}
-
-static ssize_t dcon_freeze_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", dcon->curr_src == DCON_SOURCE_DCON ? 1 : 0);
-}
-
-static ssize_t dcon_mono_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", dcon->mono);
-}
-
-static ssize_t dcon_resumeline_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "%d\n", resumeline);
-}
-
-static ssize_t dcon_mono_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned long enable_mono;
- int rc;
-
- rc = kstrtoul(buf, 10, &enable_mono);
- if (rc)
- return rc;
-
- dcon_set_mono_mode(dev_get_drvdata(dev), enable_mono ? true : false);
-
- return count;
-}
-
-static ssize_t dcon_freeze_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
- unsigned long output;
- int ret;
-
- ret = kstrtoul(buf, 10, &output);
- if (ret)
- return ret;
-
- pr_info("dcon_freeze_store: %lu\n", output);
-
- switch (output) {
- case 0:
- dcon_set_source(dcon, DCON_SOURCE_CPU);
- break;
- case 1:
- dcon_set_source_sync(dcon, DCON_SOURCE_DCON);
- break;
- case 2: /* normally unused */
- dcon_set_source(dcon, DCON_SOURCE_DCON);
- break;
- default:
- return -EINVAL;
- }
-
- return count;
-}
-
-static ssize_t dcon_resumeline_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned short rl;
- int rc;
-
- rc = kstrtou16(buf, 10, &rl);
- if (rc)
- return rc;
-
- resumeline = rl;
- dcon_write(dev_get_drvdata(dev), DCON_REG_SCAN_INT, resumeline);
-
- return count;
-}
-
-static ssize_t dcon_sleep_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned long output;
- int ret;
-
- ret = kstrtoul(buf, 10, &output);
- if (ret)
- return ret;
-
- dcon_sleep(dev_get_drvdata(dev), output ? true : false);
- return count;
-}
-
-static struct device_attribute dcon_device_files[] = {
- __ATTR(mode, 0444, dcon_mode_show, NULL),
- __ATTR(sleep, 0644, dcon_sleep_show, dcon_sleep_store),
- __ATTR(freeze, 0644, dcon_freeze_show, dcon_freeze_store),
- __ATTR(monochrome, 0644, dcon_mono_show, dcon_mono_store),
- __ATTR(resumeline, 0644, dcon_resumeline_show, dcon_resumeline_store),
-};
-
-static int dcon_bl_update(struct backlight_device *dev)
-{
- struct dcon_priv *dcon = bl_get_data(dev);
- u8 level = dev->props.brightness & 0x0F;
-
- if (dev->props.power != FB_BLANK_UNBLANK)
- level = 0;
-
- if (level != dcon->bl_val)
- dcon_set_backlight(dcon, level);
-
- /* power down the DCON when the screen is blanked */
- if (!dcon->ignore_fb_events)
- dcon_sleep(dcon, !!(dev->props.state & BL_CORE_FBBLANK));
-
- return 0;
-}
-
-static int dcon_bl_get(struct backlight_device *dev)
-{
- struct dcon_priv *dcon = bl_get_data(dev);
-
- return dcon->bl_val;
-}
-
-static const struct backlight_ops dcon_bl_ops = {
- .update_status = dcon_bl_update,
- .get_brightness = dcon_bl_get,
-};
-
-static struct backlight_properties dcon_bl_props = {
- .max_brightness = 15,
- .type = BACKLIGHT_RAW,
- .power = FB_BLANK_UNBLANK,
-};
-
-static int dcon_reboot_notify(struct notifier_block *nb,
- unsigned long foo, void *bar)
-{
- struct dcon_priv *dcon = container_of(nb, struct dcon_priv, reboot_nb);
-
- if (!dcon || !dcon->client)
- return NOTIFY_DONE;
-
- /* Turn off the DCON. Entirely. */
- dcon_write(dcon, DCON_REG_MODE, 0x39);
- dcon_write(dcon, DCON_REG_MODE, 0x32);
- return NOTIFY_DONE;
-}
-
-static int unfreeze_on_panic(struct notifier_block *nb,
- unsigned long e, void *p)
-{
- pdata->set_dconload(1);
- return NOTIFY_DONE;
-}
-
-static struct notifier_block dcon_panic_nb = {
- .notifier_call = unfreeze_on_panic,
-};
-
-static int dcon_detect(struct i2c_client *client, struct i2c_board_info *info)
-{
- strlcpy(info->type, "olpc_dcon", I2C_NAME_SIZE);
-
- return 0;
-}
-
-static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
- struct dcon_priv *dcon;
- int rc, i, j;
-
- if (!pdata)
- return -ENXIO;
-
- dcon = kzalloc(sizeof(*dcon), GFP_KERNEL);
- if (!dcon)
- return -ENOMEM;
-
- dcon->client = client;
- init_waitqueue_head(&dcon->waitq);
- INIT_WORK(&dcon->switch_source, dcon_source_switch);
- dcon->reboot_nb.notifier_call = dcon_reboot_notify;
- dcon->reboot_nb.priority = -1;
-
- i2c_set_clientdata(client, dcon);
-
- if (num_registered_fb < 1) {
- dev_err(&client->dev, "DCON driver requires a registered fb\n");
- rc = -EIO;
- goto einit;
- }
- dcon->fbinfo = registered_fb[0];
-
- rc = dcon_hw_init(dcon, 1);
- if (rc)
- goto einit;
-
- /* Add the DCON device */
-
- dcon_device = platform_device_alloc("dcon", -1);
-
- if (!dcon_device) {
- pr_err("Unable to create the DCON device\n");
- rc = -ENOMEM;
- goto eirq;
- }
- rc = platform_device_add(dcon_device);
- platform_set_drvdata(dcon_device, dcon);
-
- if (rc) {
- pr_err("Unable to add the DCON device\n");
- goto edev;
- }
-
- for (i = 0; i < ARRAY_SIZE(dcon_device_files); i++) {
- rc = device_create_file(&dcon_device->dev,
- &dcon_device_files[i]);
- if (rc) {
- dev_err(&dcon_device->dev, "Cannot create sysfs file\n");
- goto ecreate;
- }
- }
-
- dcon->bl_val = dcon_read(dcon, DCON_REG_BRIGHT) & 0x0F;
-
- /* Add the backlight device for the DCON */
- dcon_bl_props.brightness = dcon->bl_val;
- dcon->bl_dev = backlight_device_register("dcon-bl", &dcon_device->dev,
- dcon, &dcon_bl_ops, &dcon_bl_props);
- if (IS_ERR(dcon->bl_dev)) {
- dev_err(&client->dev, "cannot register backlight dev (%ld)\n",
- PTR_ERR(dcon->bl_dev));
- dcon->bl_dev = NULL;
- }
-
- register_reboot_notifier(&dcon->reboot_nb);
- atomic_notifier_chain_register(&panic_notifier_list, &dcon_panic_nb);
-
- return 0;
-
- ecreate:
- for (j = 0; j < i; j++)
- device_remove_file(&dcon_device->dev, &dcon_device_files[j]);
- edev:
- platform_device_unregister(dcon_device);
- dcon_device = NULL;
- eirq:
- free_irq(DCON_IRQ, dcon);
- einit:
- kfree(dcon);
- return rc;
-}
-
-static int dcon_remove(struct i2c_client *client)
-{
- struct dcon_priv *dcon = i2c_get_clientdata(client);
-
- unregister_reboot_notifier(&dcon->reboot_nb);
- atomic_notifier_chain_unregister(&panic_notifier_list, &dcon_panic_nb);
-
- free_irq(DCON_IRQ, dcon);
-
- backlight_device_unregister(dcon->bl_dev);
-
- if (dcon_device)
- platform_device_unregister(dcon_device);
- cancel_work_sync(&dcon->switch_source);
-
- kfree(dcon);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int dcon_suspend(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct dcon_priv *dcon = i2c_get_clientdata(client);
-
- if (!dcon->asleep) {
- /* Set up the DCON to have the source */
- dcon_set_source_sync(dcon, DCON_SOURCE_DCON);
- }
-
- return 0;
-}
-
-static int dcon_resume(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct dcon_priv *dcon = i2c_get_clientdata(client);
-
- if (!dcon->asleep) {
- dcon_bus_stabilize(dcon, 0);
- dcon_set_source(dcon, DCON_SOURCE_CPU);
- }
-
- return 0;
-}
-
-#else
-
-#define dcon_suspend NULL
-#define dcon_resume NULL
-
-#endif /* CONFIG_PM */
-
-irqreturn_t dcon_interrupt(int irq, void *id)
-{
- struct dcon_priv *dcon = id;
- u8 status;
-
- if (pdata->read_status(&status))
- return IRQ_NONE;
-
- switch (status & 3) {
- case 3:
- pr_debug("DCONLOAD_MISSED interrupt\n");
- break;
-
- case 2: /* switch to DCON mode */
- case 1: /* switch to CPU mode */
- dcon->switched = true;
- dcon->irq_time = ktime_get();
- wake_up(&dcon->waitq);
- break;
-
- case 0:
- /* workaround resume case: the DCON (on 1.5) doesn't
- * ever assert status 0x01 when switching to CPU mode
- * during resume. this is because DCONLOAD is de-asserted
- * _immediately_ upon exiting S3, so the actual release
- * of the DCON happened long before this point.
- * see http://dev.laptop.org/ticket/9869
- */
- if (dcon->curr_src != dcon->pending_src && !dcon->switched) {
- dcon->switched = true;
- dcon->irq_time = ktime_get();
- wake_up(&dcon->waitq);
- pr_debug("switching w/ status 0/0\n");
- } else {
- pr_debug("scanline interrupt w/CPU\n");
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static const struct dev_pm_ops dcon_pm_ops = {
- .suspend = dcon_suspend,
- .resume = dcon_resume,
-};
-
-static const struct i2c_device_id dcon_idtable[] = {
- { "olpc_dcon", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, dcon_idtable);
-
-static struct i2c_driver dcon_driver = {
- .driver = {
- .name = "olpc_dcon",
- .pm = &dcon_pm_ops,
- },
- .class = I2C_CLASS_DDC | I2C_CLASS_HWMON,
- .id_table = dcon_idtable,
- .probe = dcon_probe,
- .remove = dcon_remove,
- .detect = dcon_detect,
- .address_list = normal_i2c,
-};
-
-static int __init olpc_dcon_init(void)
-{
-#ifdef CONFIG_FB_OLPC_DCON_1_5
- /* XO-1.5 */
- if (olpc_board_at_least(olpc_board(0xd0)))
- pdata = &dcon_pdata_xo_1_5;
-#endif
-#ifdef CONFIG_FB_OLPC_DCON_1
- if (!pdata)
- pdata = &dcon_pdata_xo_1;
-#endif
-
- return i2c_add_driver(&dcon_driver);
-}
-
-static void __exit olpc_dcon_exit(void)
-{
- i2c_del_driver(&dcon_driver);
-}
-
-module_init(olpc_dcon_init);
-module_exit(olpc_dcon_exit);
-
-MODULE_LICENSE("GPL");
+++ /dev/null
-#ifndef OLPC_DCON_H_
-#define OLPC_DCON_H_
-
-#include <linux/notifier.h>
-#include <linux/workqueue.h>
-
-/* DCON registers */
-
-#define DCON_REG_ID 0
-#define DCON_REG_MODE 1
-
-#define MODE_PASSTHRU (1<<0)
-#define MODE_SLEEP (1<<1)
-#define MODE_SLEEP_AUTO (1<<2)
-#define MODE_BL_ENABLE (1<<3)
-#define MODE_BLANK (1<<4)
-#define MODE_CSWIZZLE (1<<5)
-#define MODE_COL_AA (1<<6)
-#define MODE_MONO_LUMA (1<<7)
-#define MODE_SCAN_INT (1<<8)
-#define MODE_CLOCKDIV (1<<9)
-#define MODE_DEBUG (1<<14)
-#define MODE_SELFTEST (1<<15)
-
-#define DCON_REG_HRES 0x2
-#define DCON_REG_HTOTAL 0x3
-#define DCON_REG_HSYNC_WIDTH 0x4
-#define DCON_REG_VRES 0x5
-#define DCON_REG_VTOTAL 0x6
-#define DCON_REG_VSYNC_WIDTH 0x7
-#define DCON_REG_TIMEOUT 0x8
-#define DCON_REG_SCAN_INT 0x9
-#define DCON_REG_BRIGHT 0xa
-#define DCON_REG_MEM_OPT_A 0x41
-#define DCON_REG_MEM_OPT_B 0x42
-
-/* Load Delay Locked Loop (DLL) settings for clock delay */
-#define MEM_DLL_CLOCK_DELAY (1<<0)
-/* Memory controller power down function */
-#define MEM_POWER_DOWN (1<<8)
-/* Memory controller software reset */
-#define MEM_SOFT_RESET (1<<0)
-
-/* Status values */
-
-#define DCONSTAT_SCANINT 0
-#define DCONSTAT_SCANINT_DCON 1
-#define DCONSTAT_DISPLAYLOAD 2
-#define DCONSTAT_MISSED 3
-
-/* Source values */
-
-#define DCON_SOURCE_DCON 0
-#define DCON_SOURCE_CPU 1
-
-/* Interrupt */
-#define DCON_IRQ 6
-
-struct dcon_priv {
- struct i2c_client *client;
- struct fb_info *fbinfo;
- struct backlight_device *bl_dev;
-
- wait_queue_head_t waitq;
- struct work_struct switch_source;
- struct notifier_block reboot_nb;
-
- /* Shadow register for the DCON_REG_MODE register */
- u8 disp_mode;
-
- /* The current backlight value - this saves us some smbus traffic */
- u8 bl_val;
-
- /* Current source, initialized at probe time */
- int curr_src;
-
- /* Desired source */
- int pending_src;
-
- /* Variables used during switches */
- bool switched;
- ktime_t irq_time;
- ktime_t load_time;
-
- /* Current output type; true == mono, false == color */
- bool mono;
- bool asleep;
- /* This get set while controlling fb blank state from the driver */
- bool ignore_fb_events;
-};
-
-struct dcon_platform_data {
- int (*init)(struct dcon_priv *);
- void (*bus_stabilize_wiggle)(void);
- void (*set_dconload)(int);
- int (*read_status)(u8 *);
-};
-
-#include <linux/interrupt.h>
-
-irqreturn_t dcon_interrupt(int irq, void *id);
-
-#ifdef CONFIG_FB_OLPC_DCON_1
-extern struct dcon_platform_data dcon_pdata_xo_1;
-#endif
-
-#ifdef CONFIG_FB_OLPC_DCON_1_5
-extern struct dcon_platform_data dcon_pdata_xo_1_5;
-#endif
-
-#endif
+++ /dev/null
-/*
- * Mainly by David Woodhouse, somewhat modified by Jordan Crouse
- *
- * Copyright © 2006-2007 Red Hat, Inc.
- * Copyright © 2006-2007 Advanced Micro Devices, Inc.
- * Copyright © 2009 VIA Technology, Inc.
- * Copyright (c) 2010 Andres Salomon <dilinger@queued.net>
- *
- * This program is free software. You can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/cs5535.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <asm/olpc.h>
-
-#include "olpc_dcon.h"
-
-static int dcon_init_xo_1(struct dcon_priv *dcon)
-{
- unsigned char lob;
-
- if (gpio_request(OLPC_GPIO_DCON_STAT0, "OLPC-DCON")) {
- pr_err("failed to request STAT0 GPIO\n");
- return -EIO;
- }
- if (gpio_request(OLPC_GPIO_DCON_STAT1, "OLPC-DCON")) {
- pr_err("failed to request STAT1 GPIO\n");
- goto err_gp_stat1;
- }
- if (gpio_request(OLPC_GPIO_DCON_IRQ, "OLPC-DCON")) {
- pr_err("failed to request IRQ GPIO\n");
- goto err_gp_irq;
- }
- if (gpio_request(OLPC_GPIO_DCON_LOAD, "OLPC-DCON")) {
- pr_err("failed to request LOAD GPIO\n");
- goto err_gp_load;
- }
- if (gpio_request(OLPC_GPIO_DCON_BLANK, "OLPC-DCON")) {
- pr_err("failed to request BLANK GPIO\n");
- goto err_gp_blank;
- }
-
- /* Turn off the event enable for GPIO7 just to be safe */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE);
-
- /*
- * Determine the current state by reading the GPIO bit; earlier
- * stages of the boot process have established the state.
- *
- * Note that we read GPIO_OUTPUT_VAL rather than GPIO_READ_BACK here;
- * this is because OFW will disable input for the pin and set a value..
- * READ_BACK will only contain a valid value if input is enabled and
- * then a value is set. So, future readings of the pin can use
- * READ_BACK, but the first one cannot. Awesome, huh?
- */
- dcon->curr_src = cs5535_gpio_isset(OLPC_GPIO_DCON_LOAD, GPIO_OUTPUT_VAL)
- ? DCON_SOURCE_CPU
- : DCON_SOURCE_DCON;
- dcon->pending_src = dcon->curr_src;
-
- /* Set the directions for the GPIO pins */
- gpio_direction_input(OLPC_GPIO_DCON_STAT0);
- gpio_direction_input(OLPC_GPIO_DCON_STAT1);
- gpio_direction_input(OLPC_GPIO_DCON_IRQ);
- gpio_direction_input(OLPC_GPIO_DCON_BLANK);
- gpio_direction_output(OLPC_GPIO_DCON_LOAD,
- dcon->curr_src == DCON_SOURCE_CPU);
-
- /* Set up the interrupt mappings */
-
- /* Set the IRQ to pair 2 */
- cs5535_gpio_setup_event(OLPC_GPIO_DCON_IRQ, 2, 0);
-
- /* Enable group 2 to trigger the DCON interrupt */
- cs5535_gpio_set_irq(2, DCON_IRQ);
-
- /* Select edge level for interrupt (in PIC) */
- lob = inb(0x4d0);
- lob &= ~(1 << DCON_IRQ);
- outb(lob, 0x4d0);
-
- /* Register the interrupt handler */
- if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", dcon)) {
- pr_err("failed to request DCON's irq\n");
- goto err_req_irq;
- }
-
- /* Clear INV_EN for GPIO7 (DCONIRQ) */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_INVERT);
-
- /* Enable filter for GPIO12 (DCONBLANK) */
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_FILTER);
-
- /* Disable filter for GPIO7 */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_FILTER);
-
- /* Disable event counter for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_EVENT_COUNT);
- cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_EVENT_COUNT);
-
- /* Add GPIO12 to the Filter Event Pair #7 */
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_FE7_SEL);
-
- /* Turn off negative Edge Enable for GPIO12 */
- cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_EN);
-
- /* Enable negative Edge Enable for GPIO7 */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_EN);
-
- /* Zero the filter amount for Filter Event Pair #7 */
- cs5535_gpio_set(0, GPIO_FLTR7_AMOUNT);
-
- /* Clear the negative edge status for GPIO7 and GPIO12 */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS);
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_STS);
-
- /* FIXME: Clear the positive status as well, just to be sure */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_POSITIVE_EDGE_STS);
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_POSITIVE_EDGE_STS);
-
- /* Enable events for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE);
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_EVENTS_ENABLE);
-
- return 0;
-
-err_req_irq:
- gpio_free(OLPC_GPIO_DCON_BLANK);
-err_gp_blank:
- gpio_free(OLPC_GPIO_DCON_LOAD);
-err_gp_load:
- gpio_free(OLPC_GPIO_DCON_IRQ);
-err_gp_irq:
- gpio_free(OLPC_GPIO_DCON_STAT1);
-err_gp_stat1:
- gpio_free(OLPC_GPIO_DCON_STAT0);
- return -EIO;
-}
-
-static void dcon_wiggle_xo_1(void)
-{
- int x;
-
- /*
- * According to HiMax, when powering the DCON up we should hold
- * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON
- * state machine to reset to a (sane) initial state. Mitch Bradley
- * did some testing and discovered that holding for 16 SMB_CLK cycles
- * worked a lot more reliably, so that's what we do here.
- *
- * According to the cs5536 spec, to set GPIO14 to SMB_CLK we must
- * simultaneously set AUX1 IN/OUT to GPIO14; ditto for SMB_DATA and
- * GPIO15.
- */
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_VAL);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_ENABLE);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_ENABLE);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1);
- cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX2);
- cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX2);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1);
- cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1);
-
- for (x = 0; x < 16; x++) {
- udelay(5);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL);
- udelay(5);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL);
- }
- udelay(5);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1);
-}
-
-static void dcon_set_dconload_1(int val)
-{
- gpio_set_value(OLPC_GPIO_DCON_LOAD, val);
-}
-
-static int dcon_read_status_xo_1(u8 *status)
-{
- *status = gpio_get_value(OLPC_GPIO_DCON_STAT0);
- *status |= gpio_get_value(OLPC_GPIO_DCON_STAT1) << 1;
-
- /* Clear the negative edge status for GPIO7 */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS);
-
- return 0;
-}
-
-struct dcon_platform_data dcon_pdata_xo_1 = {
- .init = dcon_init_xo_1,
- .bus_stabilize_wiggle = dcon_wiggle_xo_1,
- .set_dconload = dcon_set_dconload_1,
- .read_status = dcon_read_status_xo_1,
-};
+++ /dev/null
-/*
- * Copyright (c) 2009,2010 One Laptop per Child
- *
- * This program is free software. You can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/acpi.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <asm/olpc.h>
-
-/* TODO: this eventually belongs in linux/vx855.h */
-#define NR_VX855_GPI 14
-#define NR_VX855_GPO 13
-#define NR_VX855_GPIO 15
-
-#define VX855_GPI(n) (n)
-#define VX855_GPO(n) (NR_VX855_GPI + (n))
-#define VX855_GPIO(n) (NR_VX855_GPI + NR_VX855_GPO + (n))
-
-#include "olpc_dcon.h"
-
-/* Hardware setup on the XO 1.5:
- * DCONLOAD connects to VX855_GPIO1 (not SMBCK2)
- * DCONBLANK connects to VX855_GPIO8 (not SSPICLK) unused in driver
- * DCONSTAT0 connects to VX855_GPI10 (not SSPISDI)
- * DCONSTAT1 connects to VX855_GPI11 (not nSSPISS)
- * DCONIRQ connects to VX855_GPIO12
- * DCONSMBDATA connects to VX855 graphics CRTSPD
- * DCONSMBCLK connects to VX855 graphics CRTSPCLK
- */
-
-#define VX855_GENL_PURPOSE_OUTPUT 0x44c /* PMIO_Rx4c-4f */
-#define VX855_GPI_STATUS_CHG 0x450 /* PMIO_Rx50 */
-#define VX855_GPI_SCI_SMI 0x452 /* PMIO_Rx52 */
-#define BIT_GPIO12 0x40
-
-#define PREFIX "OLPC DCON:"
-
-static void dcon_clear_irq(void)
-{
- /* irq status will appear in PMIO_Rx50[6] (RW1C) on gpio12 */
- outb(BIT_GPIO12, VX855_GPI_STATUS_CHG);
-}
-
-static int dcon_was_irq(void)
-{
- u_int8_t tmp;
-
- /* irq status will appear in PMIO_Rx50[6] on gpio12 */
- tmp = inb(VX855_GPI_STATUS_CHG);
- return !!(tmp & BIT_GPIO12);
-
- return 0;
-}
-
-static int dcon_init_xo_1_5(struct dcon_priv *dcon)
-{
- unsigned int irq;
-
- dcon_clear_irq();
-
- /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */
- outb(inb(VX855_GPI_SCI_SMI)|BIT_GPIO12, VX855_GPI_SCI_SMI);
-
- /* Determine the current state of DCONLOAD, likely set by firmware */
- /* GPIO1 */
- dcon->curr_src = (inl(VX855_GENL_PURPOSE_OUTPUT) & 0x1000) ?
- DCON_SOURCE_CPU : DCON_SOURCE_DCON;
- dcon->pending_src = dcon->curr_src;
-
- /* we're sharing the IRQ with ACPI */
- irq = acpi_gbl_FADT.sci_interrupt;
- if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) {
- pr_err("DCON (IRQ%d) allocation failed\n", irq);
- return 1;
- }
-
- return 0;
-}
-
-static void set_i2c_line(int sda, int scl)
-{
- unsigned char tmp;
- unsigned int port = 0x26;
-
- /* FIXME: This directly accesses the CRT GPIO controller !!! */
- outb(port, 0x3c4);
- tmp = inb(0x3c5);
-
- if (scl)
- tmp |= 0x20;
- else
- tmp &= ~0x20;
-
- if (sda)
- tmp |= 0x10;
- else
- tmp &= ~0x10;
-
- tmp |= 0x01;
-
- outb(port, 0x3c4);
- outb(tmp, 0x3c5);
-}
-
-
-static void dcon_wiggle_xo_1_5(void)
-{
- int x;
-
- /*
- * According to HiMax, when powering the DCON up we should hold
- * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON
- * state machine to reset to a (sane) initial state. Mitch Bradley
- * did some testing and discovered that holding for 16 SMB_CLK cycles
- * worked a lot more reliably, so that's what we do here.
- */
- set_i2c_line(1, 1);
-
- for (x = 0; x < 16; x++) {
- udelay(5);
- set_i2c_line(1, 0);
- udelay(5);
- set_i2c_line(1, 1);
- }
- udelay(5);
-
- /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */
- outb(inb(VX855_GPI_SCI_SMI)|BIT_GPIO12, VX855_GPI_SCI_SMI);
-}
-
-static void dcon_set_dconload_xo_1_5(int val)
-{
- gpio_set_value(VX855_GPIO(1), val);
-}
-
-static int dcon_read_status_xo_1_5(u8 *status)
-{
- if (!dcon_was_irq())
- return -1;
-
- /* i believe this is the same as "inb(0x44b) & 3" */
- *status = gpio_get_value(VX855_GPI(10));
- *status |= gpio_get_value(VX855_GPI(11)) << 1;
-
- dcon_clear_irq();
-
- return 0;
-}
-
-struct dcon_platform_data dcon_pdata_xo_1_5 = {
- .init = dcon_init_xo_1_5,
- .bus_stabilize_wiggle = dcon_wiggle_xo_1_5,
- .set_dconload = dcon_set_dconload_xo_1_5,
- .read_status = dcon_read_status_xo_1_5,
-};
+++ /dev/null
-config PANEL
- tristate "Parallel port LCD/Keypad Panel support"
- depends on PARPORT
- ---help---
- Say Y here if you have an HD44780 or KS-0074 LCD connected to your
- parallel port. This driver also features 4 and 6-key keypads. The LCD
- is accessible through the /dev/lcd char device (10, 156), and the
- keypad through /dev/keypad (10, 185). Both require misc device to be
- enabled. This code can either be compiled as a module, or linked into
- the kernel and started at boot. If you don't understand what all this
- is about, say N.
-
-config PANEL_PARPORT
- int "Default parallel port number (0=LPT1)"
- depends on PANEL
- range 0 255
- default "0"
- ---help---
- This is the index of the parallel port the panel is connected to. One
- driver instance only supports one parallel port, so if your keypad
- and LCD are connected to two separate ports, you have to start two
- modules with different arguments. Numbering starts with '0' for LPT1,
- and so on.
-
-config PANEL_PROFILE
- int "Default panel profile (0-5, 0=custom)"
- depends on PANEL
- range 0 5
- default "5"
- ---help---
- To ease configuration, the driver supports different configuration
- profiles for past and recent wirings. These profiles can also be
- used to define an approximative configuration, completed by a few
- other options. Here are the profiles :
-
- 0 = custom (see further)
- 1 = 2x16 parallel LCD, old keypad
- 2 = 2x16 serial LCD (KS-0074), new keypad
- 3 = 2x16 parallel LCD (Hantronix), no keypad
- 4 = 2x16 parallel LCD (Nexcom NSA1045) with Nexcom's keypad
- 5 = 2x40 parallel LCD (old one), with old keypad
-
- Custom configurations allow you to define how your display is
- wired to the parallel port, and how it works. This is only intended
- for experts.
-
-config PANEL_KEYPAD
- depends on PANEL && PANEL_PROFILE="0"
- int "Keypad type (0=none, 1=old 6 keys, 2=new 6 keys, 3=Nexcom 4 keys)"
- range 0 3
- default 0
- ---help---
- This enables and configures a keypad connected to the parallel port.
- The keys will be read from character device 10,185. Valid values are :
-
- 0 : do not enable this driver
- 1 : old 6 keys keypad
- 2 : new 6 keys keypad, as used on the server at www.ant-computing.com
- 3 : Nexcom NSA1045's 4 keys keypad
-
- New profiles can be described in the driver source. The driver also
- supports simultaneous keys pressed when the keypad supports them.
-
-config PANEL_LCD
- depends on PANEL && PANEL_PROFILE="0"
- int "LCD type (0=none, 1=custom, 2=old //, 3=ks0074, 4=hantronix, 5=Nexcom)"
- range 0 5
- default 0
- ---help---
- This enables and configures an LCD connected to the parallel port.
- The driver includes an interpreter for escape codes starting with
- '\e[L' which are specific to the LCD, and a few ANSI codes. The
- driver will be registered as character device 10,156, usually
- under the name '/dev/lcd'. There are a total of 6 supported types :
-
- 0 : do not enable the driver
- 1 : custom configuration and wiring (see further)
- 2 : 2x16 & 2x40 parallel LCD (old wiring)
- 3 : 2x16 serial LCD (KS-0074 based)
- 4 : 2x16 parallel LCD (Hantronix wiring)
- 5 : 2x16 parallel LCD (Nexcom wiring)
-
- When type '1' is specified, other options will appear to configure
- more precise aspects (wiring, dimensions, protocol, ...). Please note
- that those values changed from the 2.4 driver for better consistency.
-
-config PANEL_LCD_HEIGHT
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
- int "Number of lines on the LCD (1-2)"
- range 1 2
- default 2
- ---help---
- This is the number of visible character lines on the LCD in custom profile.
- It can either be 1 or 2.
-
-config PANEL_LCD_WIDTH
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
- int "Number of characters per line on the LCD (1-40)"
- range 1 40
- default 40
- ---help---
- This is the number of characters per line on the LCD in custom profile.
- Common values are 16,20,24,40.
-
-config PANEL_LCD_BWIDTH
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
- int "Internal LCD line width (1-40, 40 by default)"
- range 1 40
- default 40
- ---help---
- Most LCDs use a standard controller which supports hardware lines of 40
- characters, although sometimes only 16, 20 or 24 of them are really wired
- to the terminal. This results in some non-visible but addressable characters,
- and is the case for most parallel LCDs. Other LCDs, and some serial ones,
- however, use the same line width internally as what is visible. The KS0074
- for example, uses 16 characters per line for 16 visible characters per line.
-
- This option lets you configure the value used by your LCD in 'custom' profile.
- If you don't know, put '40' here.
-
-config PANEL_LCD_HWIDTH
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
- int "Hardware LCD line width (1-64, 64 by default)"
- range 1 64
- default 64
- ---help---
- Most LCDs use a single address bit to differentiate line 0 and line 1. Since
- some of them need to be able to address 40 chars with the lower bits, they
- often use the immediately superior power of 2, which is 64, to address the
- next line.
-
- If you don't know what your LCD uses, in doubt let 16 here for a 2x16, and
- 64 here for a 2x40.
-
-config PANEL_LCD_CHARSET
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
- int "LCD character set (0=normal, 1=KS0074)"
- range 0 1
- default 0
- ---help---
- Some controllers such as the KS0074 use a somewhat strange character set
- where many symbols are at unusual places. The driver knows how to map
- 'standard' ASCII characters to the character sets used by these controllers.
- Valid values are :
-
- 0 : normal (untranslated) character set
- 1 : KS0074 character set
-
- If you don't know, use the normal one (0).
-
-config PANEL_LCD_PROTO
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
- int "LCD communication mode (0=parallel 8 bits, 1=serial)"
- range 0 1
- default 0
- ---help---
- This driver now supports any serial or parallel LCD wired to a parallel
- port. But before assigning signals, the driver needs to know if it will
- be driving a serial LCD or a parallel one. Serial LCDs only use 2 wires
- (SDA/SCL), while parallel ones use 2 or 3 wires for the control signals
- (E, RS, sometimes RW), and 4 or 8 for the data. Use 0 here for a 8 bits
- parallel LCD, and 1 for a serial LCD.
-
-config PANEL_LCD_PIN_E
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
- int "Parallel port pin number & polarity connected to the LCD E signal (-17...17) "
- range -17 17
- default 14
- ---help---
- This describes the number of the parallel port pin to which the LCD 'E'
- signal has been connected. It can be :
-
- 0 : no connection (eg: connected to ground)
- 1..17 : directly connected to any of these pins on the DB25 plug
- -1..-17 : connected to the same pin through an inverter (eg: transistor).
-
- Default for the 'E' pin in custom profile is '14' (AUTOFEED).
-
-config PANEL_LCD_PIN_RS
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
- int "Parallel port pin number & polarity connected to the LCD RS signal (-17...17) "
- range -17 17
- default 17
- ---help---
- This describes the number of the parallel port pin to which the LCD 'RS'
- signal has been connected. It can be :
-
- 0 : no connection (eg: connected to ground)
- 1..17 : directly connected to any of these pins on the DB25 plug
- -1..-17 : connected to the same pin through an inverter (eg: transistor).
-
- Default for the 'RS' pin in custom profile is '17' (SELECT IN).
-
-config PANEL_LCD_PIN_RW
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
- int "Parallel port pin number & polarity connected to the LCD RW signal (-17...17) "
- range -17 17
- default 16
- ---help---
- This describes the number of the parallel port pin to which the LCD 'RW'
- signal has been connected. It can be :
-
- 0 : no connection (eg: connected to ground)
- 1..17 : directly connected to any of these pins on the DB25 plug
- -1..-17 : connected to the same pin through an inverter (eg: transistor).
-
- Default for the 'RW' pin in custom profile is '16' (INIT).
-
-config PANEL_LCD_PIN_SCL
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0"
- int "Parallel port pin number & polarity connected to the LCD SCL signal (-17...17) "
- range -17 17
- default 1
- ---help---
- This describes the number of the parallel port pin to which the serial
- LCD 'SCL' signal has been connected. It can be :
-
- 0 : no connection (eg: connected to ground)
- 1..17 : directly connected to any of these pins on the DB25 plug
- -1..-17 : connected to the same pin through an inverter (eg: transistor).
-
- Default for the 'SCL' pin in custom profile is '1' (STROBE).
-
-config PANEL_LCD_PIN_SDA
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0"
- int "Parallel port pin number & polarity connected to the LCD SDA signal (-17...17) "
- range -17 17
- default 2
- ---help---
- This describes the number of the parallel port pin to which the serial
- LCD 'SDA' signal has been connected. It can be :
-
- 0 : no connection (eg: connected to ground)
- 1..17 : directly connected to any of these pins on the DB25 plug
- -1..-17 : connected to the same pin through an inverter (eg: transistor).
-
- Default for the 'SDA' pin in custom profile is '2' (D0).
-
-config PANEL_LCD_PIN_BL
- depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
- int "Parallel port pin number & polarity connected to the LCD backlight signal (-17...17) "
- range -17 17
- default 0
- ---help---
- This describes the number of the parallel port pin to which the LCD 'BL' signal
- has been connected. It can be :
-
- 0 : no connection (eg: connected to ground)
- 1..17 : directly connected to any of these pins on the DB25 plug
- -1..-17 : connected to the same pin through an inverter (eg: transistor).
-
- Default for the 'BL' pin in custom profile is '0' (uncontrolled).
-
-config PANEL_CHANGE_MESSAGE
- depends on PANEL
- bool "Change LCD initialization message ?"
- default "n"
- ---help---
- This allows you to replace the boot message indicating the kernel version
- and the driver version with a custom message. This is useful on appliances
- where a simple 'Starting system' message can be enough to stop a customer
- from worrying.
-
- If you say 'Y' here, you'll be able to choose a message yourself. Otherwise,
- say 'N' and keep the default message with the version.
-
-config PANEL_BOOT_MESSAGE
- depends on PANEL && PANEL_CHANGE_MESSAGE="y"
- string "New initialization message"
- default ""
- ---help---
- This allows you to replace the boot message indicating the kernel version
- and the driver version with a custom message. This is useful on appliances
- where a simple 'Starting system' message can be enough to stop a customer
- from worrying.
-
- An empty message will only clear the display at driver init time. Any other
- printf()-formatted message is valid with newline and escape codes.
+++ /dev/null
-obj-$(CONFIG_PANEL) += panel.o
+++ /dev/null
-TODO:
- - checkpatch.pl cleanups
- - review major/minor usages
- - review userspace api
- - see if all of this could be easier done in userspace instead.
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
-Willy Tarreau <willy@meta-x.org>
write_kctxt_csr(dd, sctxt, SEND_CTXT_CHECK_JOB_KEY, reg);
/*
* Enable send-side J_KEY integrity check, unless this is A0 h/w
- * (due to A0 erratum).
*/
if (!is_ax(dd)) {
reg = read_kctxt_csr(dd, sctxt, SEND_CTXT_CHECK_ENABLE);
#define CCE_MSIX_TABLE_UPPER (CCE + 0x000000100008)
#define CCE_MSIX_TABLE_UPPER_RESETCSR 0x0000000100000000ull
#define CCE_MSIX_VEC_CLR_WITHOUT_INT (CCE + 0x000000110400)
+#define CCE_PCIE_CTRL (CCE + 0x0000000000C0)
+#define CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_MASK 0x3ull
+#define CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_SHIFT 0
+#define CCE_PCIE_CTRL_PCIE_LANE_DELAY_MASK 0xFull
+#define CCE_PCIE_CTRL_PCIE_LANE_DELAY_SHIFT 2
+#define CCE_PCIE_CTRL_XMT_MARGIN_OVERWRITE_ENABLE_SHIFT 8
+#define CCE_PCIE_CTRL_XMT_MARGIN_SHIFT 9
+#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_MASK 0x1ull
+#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_SHIFT 12
+#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_MASK 0x7ull
+#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_SHIFT 13
#define CCE_REVISION (CCE + 0x000000000000)
#define CCE_REVISION2 (CCE + 0x000000000008)
#define CCE_REVISION2_HFI_ID_MASK 0x1ull
static int hfi1_filter_ib_pkey(void *ibhdr, void *packet_data, void *value);
static int hfi1_filter_direction(void *ibhdr, void *packet_data, void *value);
-static struct hfi1_filter_array hfi1_filters[] = {
+static const struct hfi1_filter_array hfi1_filters[] = {
{ hfi1_filter_lid },
{ hfi1_filter_dlid },
{ hfi1_filter_mad_mgmt_class },
if (opcode == IB_OPCODE_CNP) {
/*
* Only in pre-B0 h/w is the CNP_OPCODE handled
- * via this code path (errata 291394).
+ * via this code path.
*/
struct hfi1_qp *qp = NULL;
u32 lqpn, rqpn;
if (!efi_enabled(EFI_RUNTIME_SERVICES))
return -EOPNOTSUPP;
- uni_name = kzalloc(sizeof(efi_char16_t) * (strlen(name) + 1),
- GFP_KERNEL);
+ uni_name = kcalloc(strlen(name) + 1, sizeof(efi_char16_t), GFP_KERNEL);
temp_buffer = kzalloc(EFI_DATA_SIZE, GFP_KERNEL);
if (!uni_name || !temp_buffer) {
base_sc_integrity |= HFI1_PKT_KERNEL_SC_INTEGRITY;
if (is_ax(dd))
- /* turn off send-side job key checks - A0 erratum */
+ /* turn off send-side job key checks - A0 */
return base_sc_integrity &
~SEND_CTXT_CHECK_ENABLE_CHECK_JOB_KEY_SMASK;
return base_sc_integrity;
| SEND_DMA_CHECK_ENABLE_CHECK_ENABLE_SMASK;
if (is_ax(dd))
- /* turn off send-side job key checks - A0 erratum */
+ /* turn off send-side job key checks - A0 */
return base_sdma_integrity &
~SEND_DMA_CHECK_ENABLE_CHECK_JOB_KEY_SMASK;
return base_sdma_integrity;
dev_info(&(dd)->pcidev->dev, "%s: " fmt, \
get_unit_name((dd)->unit), ##__VA_ARGS__)
+#define dd_dev_dbg(dd, fmt, ...) \
+ dev_dbg(&(dd)->pcidev->dev, "%s: " fmt, \
+ get_unit_name((dd)->unit), ##__VA_ARGS__)
+
#define hfi1_dev_porterr(dd, port, fmt, ...) \
dev_err(&(dd)->pcidev->dev, "%s: IB%u:%u " fmt, \
get_unit_name((dd)->unit), (dd)->unit, (port), \
{
if (!is_bx(ppd->dd)) {
unsigned long vl;
- u64 max_vl_xmit_wait = 0, tmp;
+ u64 sum_vl_xmit_wait = 0;
u32 vl_all_mask = VL_MASK_ALL;
for_each_set_bit(vl, (unsigned long *)&(vl_all_mask),
8 * sizeof(vl_all_mask)) {
- tmp = read_port_cntr(ppd, C_TX_WAIT_VL,
- idx_from_vl(vl));
- if (tmp > max_vl_xmit_wait)
- max_vl_xmit_wait = tmp;
+ u64 tmp = sum_vl_xmit_wait +
+ read_port_cntr(ppd, C_TX_WAIT_VL,
+ idx_from_vl(vl));
+ if (tmp < sum_vl_xmit_wait) {
+ /* we wrapped */
+ sum_vl_xmit_wait = (u64)~0;
+ break;
+ }
+ sum_vl_xmit_wait = tmp;
}
- rsp->port_xmit_wait = cpu_to_be64(max_vl_xmit_wait);
+ if (be64_to_cpu(rsp->port_xmit_wait) > sum_vl_xmit_wait)
+ rsp->port_xmit_wait = cpu_to_be64(sum_vl_xmit_wait);
}
}
return error_counter_summary;
}
-static void a0_datacounters(struct hfi1_devdata *dd, struct _port_dctrs *rsp,
+static void a0_datacounters(struct hfi1_pportdata *ppd, struct _port_dctrs *rsp,
u32 vl_select_mask)
{
- if (!is_bx(dd)) {
+ if (!is_bx(ppd->dd)) {
unsigned long vl;
- int vfi = 0;
u64 sum_vl_xmit_wait = 0;
+ u32 vl_all_mask = VL_MASK_ALL;
- for_each_set_bit(vl, (unsigned long *)&(vl_select_mask),
- 8 * sizeof(vl_select_mask)) {
+ for_each_set_bit(vl, (unsigned long *)&(vl_all_mask),
+ 8 * sizeof(vl_all_mask)) {
u64 tmp = sum_vl_xmit_wait +
- be64_to_cpu(rsp->vls[vfi++].port_vl_xmit_wait);
+ read_port_cntr(ppd, C_TX_WAIT_VL,
+ idx_from_vl(vl));
if (tmp < sum_vl_xmit_wait) {
/* we wrapped */
sum_vl_xmit_wait = (u64) ~0;
vfi++;
}
- a0_datacounters(dd, rsp, vl_select_mask);
+ a0_datacounters(ppd, rsp, vl_select_mask);
if (resp_len)
*resp_len += response_data_size;
read_csr(dd, ASIC_PCIE_SD_HOST_CMD);
}
+/*
+ * CCE_PCIE_CTRL long name helpers
+ * We redefine these shorter macros to use in the code while leaving
+ * chip_registers.h to be autogenerated from the hardware spec.
+ */
+#define LANE_BUNDLE_MASK CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_MASK
+#define LANE_BUNDLE_SHIFT CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_SHIFT
+#define LANE_DELAY_MASK CCE_PCIE_CTRL_PCIE_LANE_DELAY_MASK
+#define LANE_DELAY_SHIFT CCE_PCIE_CTRL_PCIE_LANE_DELAY_SHIFT
+#define MARGIN_OVERWRITE_ENABLE_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_OVERWRITE_ENABLE_SHIFT
+#define MARGIN_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_SHIFT
+#define MARGIN_G1_G2_OVERWRITE_MASK CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_MASK
+#define MARGIN_G1_G2_OVERWRITE_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_SHIFT
+#define MARGIN_GEN1_GEN2_MASK CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_MASK
+#define MARGIN_GEN1_GEN2_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_SHIFT
+
+ /*
+ * Write xmt_margin for full-swing (WFR-B) or half-swing (WFR-C).
+ */
+static void write_xmt_margin(struct hfi1_devdata *dd, const char *fname)
+{
+ u64 pcie_ctrl;
+ u64 xmt_margin;
+ u64 xmt_margin_oe;
+ u64 lane_delay;
+ u64 lane_bundle;
+
+ pcie_ctrl = read_csr(dd, CCE_PCIE_CTRL);
+
+ /*
+ * For Discrete, use full-swing.
+ * - PCIe TX defaults to full-swing.
+ * Leave this register as default.
+ * For Integrated, use half-swing
+ * - Copy xmt_margin and xmt_margin_oe
+ * from Gen1/Gen2 to Gen3.
+ */
+ if (dd->pcidev->device == PCI_DEVICE_ID_INTEL1) { /* integrated */
+ /* extract initial fields */
+ xmt_margin = (pcie_ctrl >> MARGIN_GEN1_GEN2_SHIFT)
+ & MARGIN_GEN1_GEN2_MASK;
+ xmt_margin_oe = (pcie_ctrl >> MARGIN_G1_G2_OVERWRITE_SHIFT)
+ & MARGIN_G1_G2_OVERWRITE_MASK;
+ lane_delay = (pcie_ctrl >> LANE_DELAY_SHIFT) & LANE_DELAY_MASK;
+ lane_bundle = (pcie_ctrl >> LANE_BUNDLE_SHIFT)
+ & LANE_BUNDLE_MASK;
+
+ /*
+ * For A0, EFUSE values are not set. Override with the
+ * correct values.
+ */
+ if (is_ax(dd)) {
+ /*
+ * xmt_margin and OverwiteEnabel should be the
+ * same for Gen1/Gen2 and Gen3
+ */
+ xmt_margin = 0x5;
+ xmt_margin_oe = 0x1;
+ lane_delay = 0xF; /* Delay 240ns. */
+ lane_bundle = 0x0; /* Set to 1 lane. */
+ }
+
+ /* overwrite existing values */
+ pcie_ctrl = (xmt_margin << MARGIN_GEN1_GEN2_SHIFT)
+ | (xmt_margin_oe << MARGIN_G1_G2_OVERWRITE_SHIFT)
+ | (xmt_margin << MARGIN_SHIFT)
+ | (xmt_margin_oe << MARGIN_OVERWRITE_ENABLE_SHIFT)
+ | (lane_delay << LANE_DELAY_SHIFT)
+ | (lane_bundle << LANE_BUNDLE_SHIFT);
+
+ write_csr(dd, CCE_PCIE_CTRL, pcie_ctrl);
+ }
+
+ dd_dev_dbg(dd, "%s: program XMT margin, CcePcieCtrl 0x%llx\n",
+ fname, pcie_ctrl);
+}
+
/*
* Do all the steps needed to transition the PCIe link to Gen3 speed.
*/
* PcieCfgRegPl100 - Gen3 Control
*
* turn off PcieCfgRegPl100.Gen3ZRxDcNonCompl
- * turn on PcieCfgRegPl100.EqEieosCnt (erratum)
+ * turn on PcieCfgRegPl100.EqEieosCnt
* Everything else zero.
*/
reg32 = PCIE_CFG_REG_PL100_EQ_EIEOS_CNT_SMASK;
/*
* step 5d: program XMT margin
- * Right now, leave the default alone. To change, do a
- * read-modify-write of:
- * CcePcieCtrl.XmtMargin
- * CcePcieCtrl.XmitMarginOverwriteEnable
*/
+ write_xmt_margin(dd, __func__);
/* step 5e: disable active state power management (ASPM) */
dd_dev_info(dd, "%s: clearing ASPM\n", __func__);
if (unlikely(bth1 & HFI1_BECN_SMASK)) {
/*
* In pre-B0 h/w the CNP_OPCODE is handled via an
- * error path (errata 291394).
+ * error path.
*/
struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
u32 lqpn = be32_to_cpu(ohdr->bth[1]) & HFI1_QPN_MASK;
obj-$(CONFIG_R8188EU) := r8188eu.o
-ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/include
+ccflags-y += -D__CHECK_ENDIAN__ -I$(srctree)/$(src)/include
psta->ieee8021x_blocked = 0;
- memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+ memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats));
/* prepare for add_RATid */
supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates);
/* todo: init other variables */
- memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+ memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats));
spin_lock_bh(&psta->lock);
psta->state |= _FW_LINKED;
return _SUCCESS;
}
-struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue)
+struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue)
{
unsigned long irqL;
struct cmd_obj *obj;
-
spin_lock_irqsave(&queue->lock, irqL);
- if (list_empty(&(queue->queue))) {
- obj = NULL;
- } else {
- obj = container_of((&queue->queue)->next, struct cmd_obj, list);
+ obj = list_first_entry_or_null(&queue->queue, struct cmd_obj, list);
+ if (obj)
list_del_init(&obj->list);
- }
-
spin_unlock_irqrestore(&queue->lock, irqL);
-
return obj;
}
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
int len = 0;
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
int len = 0;
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
int len = 0;
{
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
int len = 0;
struct sta_info *psta;
struct net_device *dev = data;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
- struct wlan_network *cur_network = &(pmlmepriv->cur_network);
+ struct wlan_network *cur_network = &pmlmepriv->cur_network;
struct sta_priv *pstapriv = &padapter->stapriv;
int len = 0;
spin_lock_bh(&pstapriv->sta_hash_lock);
for (i = 0; i < NUM_STA; i++) {
- phead = &(pstapriv->sta_hash[i]);
+ phead = &pstapriv->sta_hash[i];
plist = phead->next;
while (phead != plist) {
u8 badworden = 0x0F;
u8 tmpdata[8];
- memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE);
+ memset(tmpdata, 0xff, PGPKT_DATA_SIZE);
if (!(word_en & BIT(0))) {
tmpaddr = start_addr;
if (offset > max_section)
return false;
- memset((void *)data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
- memset((void *)tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE);
+ memset(data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
+ memset(tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE);
/* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
/* Skip dummy parts to prevent unexpected data read from Efuse. */
u16 efuse_addr = *pAddr;
u32 PgWriteSuccess = 0;
- memset((void *)originaldata, 0xff, 8);
+ memset(originaldata, 0xff, 8);
if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) {
/* check if data exist */
}
break;
default:
- DBG_88E("unknown vendor specific information element ignored (vendor OUI %02x:%02x:%02x len=%lu)\n",
- pos[0], pos[1], pos[2], (unsigned long)elen);
+ DBG_88E("unknown vendor specific information element ignored (vendor OUI %3phC len=%lu)\n",
+ pos, (unsigned long)elen);
return -1;
}
return 0;
}
}
-struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv)/* _queue *free_queue) */
+struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv)
+ /* _queue *free_queue) */
{
- struct wlan_network *pnetwork;
+ struct wlan_network *pnetwork;
struct __queue *free_queue = &pmlmepriv->free_bss_pool;
- struct list_head *plist = NULL;
spin_lock_bh(&free_queue->lock);
-
- if (list_empty(&free_queue->queue)) {
- pnetwork = NULL;
+ pnetwork = list_first_entry_or_null(&free_queue->queue,
+ struct wlan_network, list);
+ if (!pnetwork)
goto exit;
- }
- plist = free_queue->queue.next;
-
- pnetwork = container_of(plist, struct wlan_network, list);
list_del_init(&pnetwork->list);
- RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("_rtw_alloc_network: ptr=%p\n", plist));
+ RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+ ("_rtw_alloc_network: ptr=%p\n", &pnetwork->list));
pnetwork->network_type = 0;
pnetwork->fixed = false;
pnetwork->last_scanned = jiffies;
fctrl = &(pwlanhdr->frame_ctl);
*(fctrl) = 0;
- /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN);
memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
- if (pmlmeinfo->bAcceptAddbaReq)
- issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0);
- else
- issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
+ /* 37 = reject ADDBA Req */
+ issue_action_BA(padapter, addr,
+ RTW_WLAN_ACTION_ADDBA_RESP,
+ pmlmeinfo->accept_addba_req ? 0 : 37);
break;
case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
status = get_unaligned_le16(&frame_body[3]);
pmlmeext->padapter = padapter;
init_mlme_ext_priv_value(padapter);
- pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
+ pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req;
init_mlme_ext_timer(padapter);
struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
{
struct recv_frame *hdr;
- struct list_head *plist, *phead;
struct adapter *padapter;
struct recv_priv *precvpriv;
- if (list_empty(&pfree_recv_queue->queue)) {
- hdr = NULL;
- } else {
- phead = get_list_head(pfree_recv_queue);
-
- plist = phead->next;
-
- hdr = container_of(plist, struct recv_frame, list);
-
+ hdr = list_first_entry_or_null(&pfree_recv_queue->queue,
+ struct recv_frame, list);
+ if (hdr) {
list_del_init(&hdr->list);
padapter = hdr->adapter;
- if (padapter != NULL) {
+ if (padapter) {
precvpriv = &padapter->recvpriv;
if (pfree_recv_queue == &precvpriv->free_recv_queue)
precvpriv->free_recvframe_cnt--;
/* Dump rx packets */
rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
if (bDumpRxPkt == 1) {/* dump all rx packets */
- int i;
- DBG_88E("#############################\n");
-
- for (i = 0; i < 64; i += 8)
- DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i),
- *(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
- DBG_88E("#############################\n");
+ if (_drv_err_ <= GlobalDebugLevel) {
+ pr_info(DRIVER_PREFIX "#############################\n");
+ print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE,
+ 16, 1, ptr, 64, false);
+ pr_info(DRIVER_PREFIX "#############################\n");
+ }
} else if (bDumpRxPkt == 2) {
- if (type == WIFI_MGT_TYPE) {
- int i;
- DBG_88E("#############################\n");
-
- for (i = 0; i < 64; i += 8)
- DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i),
- *(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
- DBG_88E("#############################\n");
+ if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_MGT_TYPE)) {
+ pr_info(DRIVER_PREFIX "#############################\n");
+ print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE,
+ 16, 1, ptr, 64, false);
+ pr_info(DRIVER_PREFIX "#############################\n");
}
} else if (bDumpRxPkt == 3) {
- if (type == WIFI_DATA_TYPE) {
- int i;
- DBG_88E("#############################\n");
-
- for (i = 0; i < 64; i += 8)
- DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i),
- *(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
- DBG_88E("#############################\n");
+ if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_DATA_TYPE)) {
+ pr_info(DRIVER_PREFIX "#############################\n");
+ print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE,
+ 16, 1, ptr, 64, false);
+ pr_info(DRIVER_PREFIX "#############################\n");
}
}
switch (type) {
frsubtype >>= 4;
- memset((void *)mic_iv, 0, 16);
- memset((void *)mic_header1, 0, 16);
- memset((void *)mic_header2, 0, 16);
- memset((void *)ctr_preload, 0, 16);
- memset((void *)chain_buffer, 0, 16);
- memset((void *)aes_out, 0, 16);
- memset((void *)padded_buffer, 0, 16);
+ memset(mic_iv, 0, 16);
+ memset(mic_header1, 0, 16);
+ memset(mic_header2, 0, 16);
+ memset(ctr_preload, 0, 16);
+ memset(chain_buffer, 0, 16);
+ memset(aes_out, 0, 16);
+ memset(padded_buffer, 0, 16);
if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
a4_exists = 0;
uint frsubtype = GetFrameSubType(pframe);
frsubtype >>= 4;
- memset((void *)mic_iv, 0, 16);
- memset((void *)mic_header1, 0, 16);
- memset((void *)mic_header2, 0, 16);
- memset((void *)ctr_preload, 0, 16);
- memset((void *)chain_buffer, 0, 16);
- memset((void *)aes_out, 0, 16);
- memset((void *)padded_buffer, 0, 16);
+ memset(mic_iv, 0, 16);
+ memset(mic_header1, 0, 16);
+ memset(mic_header2, 0, 16);
+ memset(ctr_preload, 0, 16);
+ memset(chain_buffer, 0, 16);
+ memset(aes_out, 0, 16);
+ memset(padded_buffer, 0, 16);
/* start to decrypt the payload */
return _SUCCESS;
}
-struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
+struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
{
- s32 index;
+ s32 index;
struct list_head *phash_list;
struct sta_info *psta;
struct __queue *pfree_sta_queue;
int i = 0;
u16 wRxSeqInitialValue = 0xffff;
-
pfree_sta_queue = &pstapriv->free_sta_queue;
- spin_lock_bh(&(pfree_sta_queue->lock));
-
- if (list_empty(&pfree_sta_queue->queue)) {
+ spin_lock_bh(&pfree_sta_queue->lock);
+ psta = list_first_entry_or_null(&pfree_sta_queue->queue,
+ struct sta_info, list);
+ if (!psta) {
spin_unlock_bh(&pfree_sta_queue->lock);
- psta = NULL;
} else {
- psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list);
- list_del_init(&(psta->list));
+ list_del_init(&psta->list);
spin_unlock_bh(&pfree_sta_queue->lock);
_rtw_init_stainfo(psta);
memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
psta = NULL;
goto exit;
}
- phash_list = &(pstapriv->sta_hash[index]);
-
- spin_lock_bh(&(pstapriv->sta_hash_lock));
+ phash_list = &pstapriv->sta_hash[index];
+ spin_lock_bh(&pstapriv->sta_hash_lock);
list_add_tail(&psta->hash_list, phash_list);
-
pstapriv->asoc_sta_count++;
-
spin_unlock_bh(&pstapriv->sta_hash_lock);
/* Commented by Albert 2009/08/13 */
epigram_vendor_flag = 1;
if (ralink_vendor_flag) {
DBG_88E("link to Tenda W311R AP\n");
- return HT_IOT_PEER_TENDA;
+ return HT_IOT_PEER_TENDA;
} else {
DBG_88E("Capture EPIGRAM_OUI\n");
}
tid = (param>>2)&0x0f;
preorder_ctrl = &psta->recvreorder_ctrl[tid];
preorder_ctrl->indicate_seq = 0xffff;
- preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq) ? true : false;
+ preorder_ctrl->enable = (pmlmeinfo->accept_addba_req) ? true
+ : false;
}
}
struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv)
{
unsigned long irql;
- struct xmit_buf *pxmitbuf = NULL;
- struct list_head *plist, *phead;
+ struct xmit_buf *pxmitbuf;
struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
-
spin_lock_irqsave(&pfree_queue->lock, irql);
-
- if (list_empty(&pfree_queue->queue)) {
- pxmitbuf = NULL;
- } else {
- phead = get_list_head(pfree_queue);
-
- plist = phead->next;
-
- pxmitbuf = container_of(plist, struct xmit_buf, list);
-
- list_del_init(&(pxmitbuf->list));
- }
-
- if (pxmitbuf != NULL) {
+ pxmitbuf = list_first_entry_or_null(&pfree_queue->queue,
+ struct xmit_buf, list);
+ if (pxmitbuf) {
+ list_del_init(&pxmitbuf->list);
pxmitpriv->free_xmit_extbuf_cnt--;
-
pxmitbuf->priv_data = NULL;
/* pxmitbuf->ext_tag = true; */
-
if (pxmitbuf->sctx) {
DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__);
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
}
}
-
spin_unlock_irqrestore(&pfree_queue->lock, irql);
-
return pxmitbuf;
}
struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
{
unsigned long irql;
- struct xmit_buf *pxmitbuf = NULL;
- struct list_head *plist, *phead;
+ struct xmit_buf *pxmitbuf;
struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
-
/* DBG_88E("+rtw_alloc_xmitbuf\n"); */
spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irql);
-
- if (list_empty(&pfree_xmitbuf_queue->queue)) {
- pxmitbuf = NULL;
- } else {
- phead = get_list_head(pfree_xmitbuf_queue);
-
- plist = phead->next;
-
- pxmitbuf = container_of(plist, struct xmit_buf, list);
-
- list_del_init(&(pxmitbuf->list));
- }
-
- if (pxmitbuf != NULL) {
+ pxmitbuf = list_first_entry_or_null(&pfree_xmitbuf_queue->queue,
+ struct xmit_buf, list);
+ if (pxmitbuf) {
+ list_del_init(&pxmitbuf->list);
pxmitpriv->free_xmitbuf_cnt--;
pxmitbuf->priv_data = NULL;
if (pxmitbuf->sctx) {
}
spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irql);
-
return pxmitbuf;
}
*/
-struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* _queue *pfree_xmit_queue) */
+struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)
+ /* _queue *pfree_xmit_queue) */
{
/*
Please remember to use all the osdep_service api,
and lock/unlock or _enter/_exit critical to protect
pfree_xmit_queue
*/
-
- struct xmit_frame *pxframe = NULL;
- struct list_head *plist, *phead;
+ struct xmit_frame *pxframe;
struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
-
spin_lock_bh(&pfree_xmit_queue->lock);
-
- if (list_empty(&pfree_xmit_queue->queue)) {
- RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe:%d\n", pxmitpriv->free_xmitframe_cnt));
- pxframe = NULL;
+ pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue,
+ struct xmit_frame, list);
+ if (!pxframe) {
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+ ("rtw_alloc_xmitframe:%d\n",
+ pxmitpriv->free_xmitframe_cnt));
} else {
- phead = get_list_head(pfree_xmit_queue);
-
- plist = phead->next;
-
- pxframe = container_of(plist, struct xmit_frame, list);
+ list_del_init(&pxframe->list);
- list_del_init(&(pxframe->list));
- }
-
- if (pxframe != NULL) { /* default value setting */
+ /* default value setting */
pxmitpriv->free_xmitframe_cnt--;
- RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe():free_xmitframe_cnt=%d\n", pxmitpriv->free_xmitframe_cnt));
+ RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+ ("rtw_alloc_xmitframe():free_xmitframe_cnt=%d\n",
+ pxmitpriv->free_xmitframe_cnt));
pxframe->buf_addr = NULL;
pxframe->pxmitbuf = NULL;
pxframe->agg_num = 1;
pxframe->ack_report = 0;
}
-
spin_unlock_bh(&pfree_xmit_queue->lock);
-
return pxframe;
}
u8 wifi_spec;/* !turbo_mode */
u8 channel_plan;
- bool bAcceptAddbaReq;
+ bool accept_addba_req; /* true = accept AP's Add BA req */
u8 antdiv_cfg;
u8 antdiv_type;
u8 candidate_tid_bitmap;
u8 dialogToken;
/* Accept ADDBA Request */
- bool bAcceptAddbaReq;
+ bool accept_addba_req;
u8 bwmode_updated;
u8 hidden_ssid_mode;
memset(param, 0, param_len);
param->cmd = IEEE_CMD_SET_ENCRYPTION;
- memset(param->sta_addr, 0xff, ETH_ALEN);
+ eth_broadcast_addr(param->sta_addr);
switch (pext->alg) {
case IW_ENCODE_ALG_NONE:
static int rtw_low_power;
static int rtw_wifi_spec;
static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX;
-/* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */
-static int rtw_AcceptAddbaReq = true;
static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */
registry_par->low_power = (u8)rtw_low_power;
registry_par->wifi_spec = (u8)rtw_wifi_spec;
registry_par->channel_plan = (u8)rtw_channel_plan;
- registry_par->bAcceptAddbaReq = (u8)rtw_AcceptAddbaReq;
+ registry_par->accept_addba_req = true;
registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg;
registry_par->antdiv_type = (u8)rtw_antdiv_type;
registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode;
#include "rtllib.h"
-
-
struct chnl_txpow_triple {
u8 FirstChnl;
u8 NumChnls;
*/
struct rt_dot11d_info {
-
bool bEnabled;
u16 CountryIeLen;
#define container_of_work_rsl(x, y, z) container_of(x, y, z)
#define container_of_dwork_rsl(x, y, z) \
- container_of(container_of(x, struct delayed_work, work), y, z)
+ container_of(to_delayed_work(x), y, z)
#define iwe_stream_add_event_rsl(info, start, stop, iwe, len) \
iwe_stream_add_event(info, start, stop, iwe, len)
#include <linux/etherdevice.h>
#include <linux/uaccess.h>
#include <net/arp.h>
-
#include "rtllib.h"
-
u32 rt_global_debug_component = COMP_ERR;
EXPORT_SYMBOL(rt_global_debug_component);
-
-
static inline int rtllib_networks_allocate(struct rtllib_device *ieee)
{
if (ieee->networks)
}
rtllib_networks_initialize(ieee);
-
/* Default fragmentation threshold is maximum payload size */
ieee->fts = DEFAULT_FTS;
ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
goto done;
}
new_crypt->ops = ops;
- if (new_crypt->ops)
+ if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
new_crypt->priv =
new_crypt->ops->init(param->u.crypt.idx);
goto done;
}
new_crypt->ops = ops;
- if (new_crypt->ops)
+ if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
new_crypt->priv = new_crypt->ops->init(idx);
if (new_crypt->priv == NULL) {
{
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
PRX_REORDER_ENTRY pReorderEntry = NULL;
- struct ieee80211_rxb *prxbIndicateArray[REORDER_WIN_SIZE];
+ struct ieee80211_rxb **prxbIndicateArray;
u8 WinSize = pHTInfo->RxReorderWinSize;
u16 WinEnd = (pTS->RxIndicateSeq + WinSize -1)%4096;
u8 index = 0;
bool bMatchWinStart = false, bPktInBuf = false;
IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->RxIndicateSeq is %d, WinSize is %d\n",__func__,SeqNum,pTS->RxIndicateSeq,WinSize);
+
+ prxbIndicateArray = kmalloc(sizeof(struct ieee80211_rxb *) *
+ REORDER_WIN_SIZE, GFP_KERNEL);
+ if (!prxbIndicateArray)
+ return;
+
/* Rx Reorder initialize condition.*/
if (pTS->RxIndicateSeq == 0xffff) {
pTS->RxIndicateSeq = SeqNum;
kfree(prxb);
prxb = NULL;
}
+
+ kfree(prxbIndicateArray);
return;
}
// Indicate packets
if(index>REORDER_WIN_SIZE){
IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n");
+ kfree(prxbIndicateArray);
return;
}
ieee80211_indicate_packets(ieee, prxbIndicateArray, index);
pTS->RxPktPendingTimer.expires = jiffies + MSECS(pHTInfo->RxReorderPendingTime);
add_timer(&pTS->RxPktPendingTimer);
}
+
+ kfree(prxbIndicateArray);
}
static u8 parse_subframe(struct sk_buff *skb,
static void ieee80211_softmac_scan_wq(struct work_struct *work)
{
- struct delayed_work *dwork = container_of(work, struct delayed_work, work);
+ struct delayed_work *dwork = to_delayed_work(work);
struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
static short watchdog;
u8 channel_map[MAX_CHANNEL_NUMBER+1];
static void ieee80211_start_ibss_wq(struct work_struct *work)
{
- struct delayed_work *dwork = container_of(work, struct delayed_work, work);
+ struct delayed_work *dwork = to_delayed_work(work);
struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
/* iwconfig mode ad-hoc will schedule this and return
* on the other hand this will block further iwconfig SET
static void ieee80211_associate_retry_wq(struct work_struct *work)
{
- struct delayed_work *dwork = container_of(work, struct delayed_work, work);
+ struct delayed_work *dwork = to_delayed_work(work);
struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
unsigned long flags;
/*
- This is part of the rtl8192 driver
- released under the GPL (See file COPYING for details).
-
- This files contains programming code for the rtl8256
- radio frontend.
-
- *Many* thanks to Realtek Corp. for their great support!
-
+* This is part of the rtl8192 driver
+* released under the GPL (See file COPYING for details).
+*
+* This files contains programming code for the rtl8256
+* radio frontend.
+*
+* *Many* thanks to Realtek Corp. for their great support!
*/
#include "r8192U.h"
* Output: NONE
* Return: NONE
* Note: 8226 support both 20M and 40 MHz
- *---------------------------------------------------------------------------*/
+ *--------------------------------------------------------------------------
+ */
void PHY_SetRF8256Bandwidth(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth)
{
u8 eRFPath;
* Input: struct net_device* dev
* Output: NONE
* Return: NONE
- *---------------------------------------------------------------------------*/
+ *--------------------------------------------------------------------------
+ */
void PHY_RF8256_Config(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
* Input: struct net_device* dev
* Output: NONE
* Return: NONE
- *---------------------------------------------------------------------------*/
+ *--------------------------------------------------------------------------
+ */
void phy_RF8256_Config_ParaFile(struct net_device *dev)
{
u32 u4RegValue = 0;
static void rtl8192_tx_isr(struct urb *tx_urb)
{
struct sk_buff *skb = (struct sk_buff *)tx_urb->context;
- struct net_device *dev = (struct net_device *)(skb->cb);
+ struct net_device *dev;
struct r8192_priv *priv = NULL;
- cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
- u8 queue_index = tcb_desc->queue_index;
+ cb_desc *tcb_desc;
+ u8 queue_index;
+
+ if (!skb)
+ return;
+
+ dev = (struct net_device *)(skb->cb);
+ tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+ queue_index = tcb_desc->queue_index;
priv = ieee80211_priv(dev);
}
/* free skb and tx_urb */
- if (skb != NULL) {
- dev_kfree_skb_any(skb);
- usb_free_urb(tx_urb);
- atomic_dec(&priv->tx_pending[queue_index]);
- }
+ dev_kfree_skb_any(skb);
+ usb_free_urb(tx_urb);
+ atomic_dec(&priv->tx_pending[queue_index]);
/*
* Handle HW Beacon:
*/
static u8 MapHwQueueToFirmwareQueue(u8 QueueID)
{
- u8 QueueSelect = 0x0; /* defualt set to */
+ u8 QueueSelect = 0x0; /* default set to */
switch (QueueID) {
case BE_QUEUE:
static void rtl819x_watchdog_wqcallback(struct work_struct *work)
{
- struct delayed_work *dwork = container_of(work,
- struct delayed_work, work);
+ struct delayed_work *dwork = to_delayed_work(work);
struct r8192_priv *priv = container_of(dwork,
struct r8192_priv, watch_dog_wq);
struct net_device *dev = priv->ieee80211->dev;
if (is_cck_rate) {
/* (1)Hardware does not provide RSSI for CCK */
- /* (2)PWDB, Average PWDB cacluated by hardware
+ /* (2)PWDB, Average PWDB calculated by hardware
* (for rate adaptive)
*/
u8 report;
}
- /* (2)PWDB, Average PWDB cacluated by hardware
+ /* (2)PWDB, Average PWDB calculated by hardware
* (for rate adaptive)
*/
rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1) & 0x7f) - 106;
void dm_txpower_trackingcallback(struct work_struct *work)
{
- struct delayed_work *dwork = container_of(work, struct delayed_work, work);
+ struct delayed_work *dwork = to_delayed_work(work);
struct r8192_priv *priv = container_of(dwork, struct r8192_priv, txpower_tracking_wq);
struct net_device *dev = priv->ieee80211->dev;
*---------------------------------------------------------------------------*/
void dm_rf_pathcheck_workitemcallback(struct work_struct *work)
{
- struct delayed_work *dwork = container_of(work, struct delayed_work, work);
+ struct delayed_work *dwork = to_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;*/
-/*
- This file contains wireless extension handlers.
-
- This is part of rtl8180 OpenSource driver.
- Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
- Released under the terms of GPL (General Public Licence)
-
- Parts of this driver are based on the GPL part
- of the official realtek driver.
-
- Parts of this driver are based on the rtl8180 driver skeleton
- from Patric Schenke & Andres Salomon.
-
- Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
-
- We want to thank the Authors of those projects and the Ndiswrapper
- project Authors.
-*/
+/******************************************************************************
+ *
+ * This file contains wireless extension handlers.
+ *
+ * This is part of rtl8180 OpenSource driver.
+ * Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
+ * Released under the terms of GPL (General Public Licence)
+ *
+ * Parts of this driver are based on the GPL part
+ * of the official realtek driver.
+ *
+ * Parts of this driver are based on the rtl8180 driver skeleton
+ * from Patric Schenke & Andres Salomon.
+ *
+ * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
+ *
+ * We want to thank the Authors of those projects and the Ndiswrapper
+ * project Authors.
+ *
+ *****************************************************************************/
#include <linux/string.h>
#include "r8192U.h"
void InitialGainOperateWorkItemCallBack(struct work_struct *work)
{
- struct delayed_work *dwork = container_of(work, struct delayed_work,
- work);
+ struct delayed_work *dwork = to_delayed_work(work);
struct r8192_priv *priv = container_of(dwork, struct r8192_priv,
initialgain_operate_wq);
struct net_device *dev = priv->ieee80211->dev;
struct mp_priv mppriv;
s32 bDriverStopped;
s32 bSurpriseRemoved;
+ s32 bSuspended;
u32 IsrContent;
u32 ImrContent;
u8 EepromAddressSize;
* more details.
*
* You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ * this program; if not, see <http://www.gnu.org/licenses/>.
*
* Modifications for inclusion into the Linux staging tree are
* Copyright(c) 2010 Larry Finger. All rights reserved.
#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6
#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7
-
#define IEEE_CRYPT_ALG_NAME_LEN 16
#define WPA_CIPHER_NONE BIT(0)
#define WPA_CIPHER_TKIP BIT(3)
#define WPA_CIPHER_CCMP BIT(4)
-
-
#define WPA_SELECTOR_LEN 4
#define RSN_HEADER_LEN 4
WIRELESS_11BGN = (WIRELESS_11B | WIRELESS_11G | WIRELESS_11N),
};
-
struct ieee_param {
u32 cmd;
u8 sta_addr[ETH_ALEN];
u16 seq_ctl;
} __packed;
-
struct ieee80211_hdr_qos {
u16 frame_ctl;
u16 duration_id;
u16 length;
} __packed;
-
enum eap_type {
EAP_PACKET = 0,
EAPOL_START,
#define IEEE80211_STYPE_CFPOLL 0x0060
#define IEEE80211_STYPE_CFACKPOLL 0x0070
#define IEEE80211_QOS_DATAGRP 0x0080
-#define IEEE80211_QoS_DATAGRP IEEE80211_QOS_DATAGRP
#define IEEE80211_SCTL_FRAG 0x000F
#define IEEE80211_SCTL_SEQ 0xFFF0
#define WLAN_AUTH_CHALLENGE_LEN 128
-#define WLAN_CAPABILITY_BSS (1<<0)
-#define WLAN_CAPABILITY_IBSS (1<<1)
-#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
-#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
-#define WLAN_CAPABILITY_PRIVACY (1<<4)
-#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
-#define WLAN_CAPABILITY_PBCC (1<<6)
-#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
-#define WLAN_CAPABILITY_SHORT_SLOT (1<<10)
+#define WLAN_CAPABILITY_BSS BIT(0)
+#define WLAN_CAPABILITY_IBSS BIT(1)
+#define WLAN_CAPABILITY_CF_POLLABLE BIT(2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3)
+#define WLAN_CAPABILITY_PRIVACY BIT(4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5)
+#define WLAN_CAPABILITY_PBCC BIT(6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
+#define WLAN_CAPABILITY_SHORT_SLOT BIT(10)
/* Information Element IDs */
#define WLAN_EID_SSID 0
#define IEEE80211_DATA_HDR3_LEN 24
#define IEEE80211_DATA_HDR4_LEN 30
-
-#define IEEE80211_STATMASK_SIGNAL (1<<0)
-#define IEEE80211_STATMASK_RSSI (1<<1)
-#define IEEE80211_STATMASK_NOISE (1<<2)
-#define IEEE80211_STATMASK_RATE (1<<3)
+#define IEEE80211_STATMASK_SIGNAL BIT(0)
+#define IEEE80211_STATMASK_RSSI BIT(1)
+#define IEEE80211_STATMASK_NOISE BIT(2)
+#define IEEE80211_STATMASK_RATE BIT(3)
#define IEEE80211_STATMASK_WEMASK 0x7
+#define IEEE80211_CCK_MODULATION BIT(0)
+#define IEEE80211_OFDM_MODULATION BIT(1)
-#define IEEE80211_CCK_MODULATION (1<<0)
-#define IEEE80211_OFDM_MODULATION (1<<1)
-
-#define IEEE80211_24GHZ_BAND (1<<0)
-#define IEEE80211_52GHZ_BAND (1<<1)
+#define IEEE80211_24GHZ_BAND BIT(0)
+#define IEEE80211_52GHZ_BAND BIT(1)
#define IEEE80211_CCK_RATE_LEN 4
#define IEEE80211_NUM_OFDM_RATESLEN 8
-
#define IEEE80211_CCK_RATE_1MB 0x02
#define IEEE80211_CCK_RATE_2MB 0x04
#define IEEE80211_CCK_RATE_5MB 0x0B
#define IEEE80211_OFDM_RATE_54MB 0x6C
#define IEEE80211_BASIC_RATE_MASK 0x80
-#define IEEE80211_CCK_RATE_1MB_MASK (1<<0)
-#define IEEE80211_CCK_RATE_2MB_MASK (1<<1)
-#define IEEE80211_CCK_RATE_5MB_MASK (1<<2)
-#define IEEE80211_CCK_RATE_11MB_MASK (1<<3)
-#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4)
-#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5)
-#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6)
-#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7)
-#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8)
-#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9)
-#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10)
-#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11)
+#define IEEE80211_CCK_RATE_1MB_MASK BIT(0)
+#define IEEE80211_CCK_RATE_2MB_MASK BIT(1)
+#define IEEE80211_CCK_RATE_5MB_MASK BIT(2)
+#define IEEE80211_CCK_RATE_11MB_MASK BIT(3)
+#define IEEE80211_OFDM_RATE_6MB_MASK BIT(4)
+#define IEEE80211_OFDM_RATE_9MB_MASK BIT(5)
+#define IEEE80211_OFDM_RATE_12MB_MASK BIT(6)
+#define IEEE80211_OFDM_RATE_18MB_MASK BIT(7)
+#define IEEE80211_OFDM_RATE_24MB_MASK BIT(8)
+#define IEEE80211_OFDM_RATE_36MB_MASK BIT(9)
+#define IEEE80211_OFDM_RATE_48MB_MASK BIT(10)
+#define IEEE80211_OFDM_RATE_54MB_MASK BIT(11)
#define IEEE80211_CCK_RATES_MASK 0x0000000F
#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \
#define IEEE80211_NUM_CCK_RATES 4
#define IEEE80211_OFDM_SHIFT_MASK_A 4
-
-
-
/* NOTE: This data is for statistical purposes; not all hardware provides this
* information for frames received. Not setting these will not cause
* any adverse affects.
uint swtxawake;
};
-#define SEC_KEY_1 (1<<0)
-#define SEC_KEY_2 (1<<1)
-#define SEC_KEY_3 (1<<2)
-#define SEC_KEY_4 (1<<3)
-#define SEC_ACTIVE_KEY (1<<4)
-#define SEC_AUTH_MODE (1<<5)
-#define SEC_UNICAST_GROUP (1<<6)
-#define SEC_LEVEL (1<<7)
-#define SEC_ENABLED (1<<8)
+#define SEC_KEY_1 BIT(0)
+#define SEC_KEY_2 BIT(1)
+#define SEC_KEY_3 BIT(2)
+#define SEC_KEY_4 BIT(3)
+#define SEC_ACTIVE_KEY BIT(4)
+#define SEC_AUTH_MODE BIT(5)
+#define SEC_UNICAST_GROUP BIT(6)
+#define SEC_LEVEL BIT(7)
+#define SEC_ENABLED BIT(8)
#define SEC_LEVEL_0 0 /* None */
#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */
#define MAX_WPA_IE_LEN 128
-#define NETWORK_EMPTY_ESSID (1<<0)
-#define NETWORK_HAS_OFDM (1<<1)
-#define NETWORK_HAS_CCK (1<<2)
+#define NETWORK_EMPTY_ESSID BIT(0)
+#define NETWORK_HAS_OFDM BIT(1)
+#define NETWORK_HAS_CCK BIT(2)
#define IEEE80211_DTIM_MBCAST 4
#define IEEE80211_DTIM_UCAST 2
#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
#define DEFAULT_FTS 2346
-#define CFG_IEEE80211_RESERVE_FCS (1<<0)
-#define CFG_IEEE80211_COMPUTE_FCS (1<<1)
+#define CFG_IEEE80211_RESERVE_FCS BIT(0)
+#define CFG_IEEE80211_COMPUTE_FCS BIT(1)
#define MAXTID 16
-#define IEEE_A (1<<0)
-#define IEEE_B (1<<1)
-#define IEEE_G (1<<2)
-#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G)
+#define IEEE_A BIT(0)
+#define IEEE_B BIT(1)
+#define IEEE_G BIT(2)
+#define IEEE_MODE_MASK (IEEE_A | IEEE_B | IEEE_G)
static inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
{
unsigned char *r8712_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len,
int limit);
int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
- int *pairwise_cipher);
+ int *pairwise_cipher);
int r8712_parse_wpa2_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
int *pairwise_cipher);
int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
r8712_write32(pAdapter, IOCMD_CTRL_REG, cmd);
msleep(100);
- while ((0 != r8712_read32(pAdapter, IOCMD_CTRL_REG)) &&
+ while ((r8712_read32(pAdapter, IOCMD_CTRL_REG != 0)) &&
(pollingcnts > 0)) {
pollingcnts--;
msleep(20);
u8 r8712_read8(struct _adapter *adapter, u32 addr)
{
- struct io_queue *pio_queue = adapter->pio_queue;
- struct intf_hdl *pintfhdl = &(pio_queue->intf);
- u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
+ struct intf_hdl *hdl = &adapter->pio_queue->intf;
- _read8 = pintfhdl->io_ops._read8;
- return _read8(pintfhdl, addr);
+ return hdl->io_ops._read8(hdl, addr);
}
u16 r8712_read16(struct _adapter *adapter, u32 addr)
{
- struct io_queue *pio_queue = adapter->pio_queue;
- struct intf_hdl *pintfhdl = &(pio_queue->intf);
- u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+ struct intf_hdl *hdl = &adapter->pio_queue->intf;
- _read16 = pintfhdl->io_ops._read16;
- return _read16(pintfhdl, addr);
+ return hdl->io_ops._read16(hdl, addr);
}
u32 r8712_read32(struct _adapter *adapter, u32 addr)
{
- struct io_queue *pio_queue = adapter->pio_queue;
- struct intf_hdl *pintfhdl = &(pio_queue->intf);
- u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+ struct intf_hdl *hdl = &adapter->pio_queue->intf;
- _read32 = pintfhdl->io_ops._read32;
- return _read32(pintfhdl, addr);
+ return hdl->io_ops._read32(hdl, addr);
}
void r8712_write8(struct _adapter *adapter, u32 addr, u8 val)
{
- struct io_queue *pio_queue = adapter->pio_queue;
- struct intf_hdl *pintfhdl = &(pio_queue->intf);
- void (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
+ struct intf_hdl *hdl = &adapter->pio_queue->intf;
- _write8 = pintfhdl->io_ops._write8;
- _write8(pintfhdl, addr, val);
+ hdl->io_ops._write8(hdl, addr, val);
}
void r8712_write16(struct _adapter *adapter, u32 addr, u16 val)
{
- struct io_queue *pio_queue = adapter->pio_queue;
- struct intf_hdl *pintfhdl = &(pio_queue->intf);
- void (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
+ struct intf_hdl *hdl = &adapter->pio_queue->intf;
- _write16 = pintfhdl->io_ops._write16;
- _write16(pintfhdl, addr, val);
+ hdl->io_ops._write16(hdl, addr, val);
}
void r8712_write32(struct _adapter *adapter, u32 addr, u32 val)
{
- struct io_queue *pio_queue = adapter->pio_queue;
- struct intf_hdl *pintfhdl = &(pio_queue->intf);
+ struct intf_hdl *hdl = &adapter->pio_queue->intf;
- void (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
-
- _write32 = pintfhdl->io_ops._write32;
- _write32(pintfhdl, addr, val);
+ hdl->io_ops._write32(hdl, addr, val);
}
void r8712_read_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
- struct io_queue *pio_queue = adapter->pio_queue;
- struct intf_hdl *pintfhdl = &(pio_queue->intf);
+ struct intf_hdl *hdl = &adapter->pio_queue->intf;
- void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
return;
- _read_mem = pintfhdl->io_ops._read_mem;
- _read_mem(pintfhdl, addr, cnt, pmem);
+
+ hdl->io_ops._read_mem(hdl, addr, cnt, pmem);
}
void r8712_write_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
- struct io_queue *pio_queue = adapter->pio_queue;
- struct intf_hdl *pintfhdl = &(pio_queue->intf);
- void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
+ struct intf_hdl *hdl = &adapter->pio_queue->intf;
- _write_mem = pintfhdl->io_ops._write_mem;
- _write_mem(pintfhdl, addr, cnt, pmem);
+ hdl->io_ops._write_mem(hdl, addr, cnt, pmem);
}
void r8712_read_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
- struct io_queue *pio_queue = adapter->pio_queue;
- struct intf_hdl *pintfhdl = &(pio_queue->intf);
+ struct intf_hdl *hdl = &adapter->pio_queue->intf;
- u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
return;
- _read_port = pintfhdl->io_ops._read_port;
- _read_port(pintfhdl, addr, cnt, pmem);
+
+ hdl->io_ops._read_port(hdl, addr, cnt, pmem);
}
void r8712_write_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
- struct io_queue *pio_queue = adapter->pio_queue;
- struct intf_hdl *pintfhdl = &(pio_queue->intf);
+ struct intf_hdl *hdl = &adapter->pio_queue->intf;
- u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
- _write_port = pintfhdl->io_ops._write_port;
- _write_port(pintfhdl, addr, cnt, pmem);
+ hdl->io_ops._write_port(hdl, addr, cnt, pmem);
}
unsigned long irqL;
struct cmd_obj *obj;
- spin_lock_irqsave(&(queue->lock), irqL);
- if (list_empty(&(queue->queue))) {
- obj = NULL;
- } else {
- obj = LIST_CONTAINOR(queue->queue.next,
- struct cmd_obj, list);
+ spin_lock_irqsave(&queue->lock, irqL);
+ obj = list_first_entry_or_null(&queue->queue,
+ struct cmd_obj, list);
+ if (obj)
list_del_init(&obj->list);
- }
- spin_unlock_irqrestore(&(queue->lock), irqL);
+ spin_unlock_irqrestore(&queue->lock, irqL);
return obj;
}
wep_key_idx = 0;
if (wep_key_len > 0) {
wep_key_len = wep_key_len <= 5 ? 5 : 13;
- pwep = kmalloc((u32)(wep_key_len +
- FIELD_OFFSET(struct NDIS_802_11_WEP,
- KeyMaterial)), GFP_ATOMIC);
+ pwep = kzalloc(sizeof(*pwep), GFP_ATOMIC);
if (pwep == NULL)
return -ENOMEM;
- memset(pwep, 0, sizeof(struct NDIS_802_11_WEP));
pwep->KeyLength = wep_key_len;
pwep->Length = wep_key_len +
FIELD_OFFSET(struct NDIS_802_11_WEP,
uint oid_rt_get_small_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
if (poid_par_priv->type_of_oid != QUERY_OID)
return RNDIS_STATUS_NOT_ACCEPTED;
uint oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
if (poid_par_priv->type_of_oid != QUERY_OID)
return RNDIS_STATUS_NOT_ACCEPTED;
uint oid_rt_get_large_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
if (poid_par_priv->type_of_oid != QUERY_OID)
return RNDIS_STATUS_NOT_ACCEPTED;
uint oid_rt_get_rx_total_packet_hdl(struct oid_par_priv *poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
if (poid_par_priv->type_of_oid != QUERY_OID)
return RNDIS_STATUS_NOT_ACCEPTED;
uint oid_rt_get_rx_icv_err_hdl(struct oid_par_priv *poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
if (poid_par_priv->type_of_oid != QUERY_OID)
return RNDIS_STATUS_NOT_ACCEPTED;
uint oid_rt_get_preamble_mode_hdl(struct oid_par_priv *poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
u32 preamblemode = 0;
if (poid_par_priv->type_of_oid != QUERY_OID)
uint oid_rt_get_channelplan_hdl(struct oid_par_priv *poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
if (poid_par_priv->type_of_oid != QUERY_OID)
uint oid_rt_set_channelplan_hdl(struct oid_par_priv
*poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
if (poid_par_priv->type_of_oid != SET_OID)
uint oid_rt_set_preamble_mode_hdl(struct oid_par_priv
*poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
u32 preamblemode = 0;
if (poid_par_priv->type_of_oid != SET_OID)
uint oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv
*poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
if (poid_par_priv->type_of_oid != QUERY_OID)
return RNDIS_STATUS_NOT_ACCEPTED;
uint oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv
*poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
if (poid_par_priv->type_of_oid != QUERY_OID)
return RNDIS_STATUS_NOT_ACCEPTED;
uint oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct NDIS_802_11_CONFIGURATION *pnic_Config;
u32 channelnum;
poid_par_priv)
{
uint status = RNDIS_STATUS_SUCCESS;
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *Adapter = poid_par_priv->adapter_context;
if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
return RNDIS_STATUS_NOT_ACCEPTED;
uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
{
uint status = RNDIS_STATUS_SUCCESS;
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *Adapter = poid_par_priv->adapter_context;
if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
return RNDIS_STATUS_NOT_ACCEPTED;
uint oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv)
{
- struct _adapter *padapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
+ struct _adapter *padapter = poid_par_priv->adapter_context;
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
u32 ulInfo;
unsigned long irqL;
struct wlan_network *pnetwork;
struct __queue *free_queue = &pmlmepriv->free_bss_pool;
- struct list_head *plist = NULL;
- if (list_empty(&free_queue->queue))
- return NULL;
spin_lock_irqsave(&free_queue->lock, irqL);
- plist = free_queue->queue.next;
- pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
- list_del_init(&pnetwork->list);
- pnetwork->last_scanned = jiffies;
- pmlmepriv->num_of_scanned++;
+ pnetwork = list_first_entry_or_null(&free_queue->queue,
+ struct wlan_network, list);
+ if (pnetwork) {
+ list_del_init(&pnetwork->list);
+ pnetwork->last_scanned = jiffies;
+ pmlmepriv->num_of_scanned++;
+ }
spin_unlock_irqrestore(&free_queue->lock, irqL);
return pnetwork;
}
_init_queue(&precvpriv->recv_pending_queue);
precvpriv->adapter = padapter;
precvpriv->free_recvframe_cnt = NR_RECVFRAME;
- precvpriv->pallocated_frame_buf = kmalloc(NR_RECVFRAME *
+ precvpriv->pallocated_frame_buf = kzalloc(NR_RECVFRAME *
sizeof(union recv_frame) + RXFRAME_ALIGN_SZ,
GFP_ATOMIC);
if (precvpriv->pallocated_frame_buf == NULL)
return _FAIL;
kmemleak_not_leak(precvpriv->pallocated_frame_buf);
- memset(precvpriv->pallocated_frame_buf, 0, NR_RECVFRAME *
- sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf +
RXFRAME_ALIGN_SZ -
((addr_t)(precvpriv->pallocated_frame_buf) &
r8712_free_recv_priv(precvpriv);
}
-union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue)
+union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue)
{
unsigned long irqL;
union recv_frame *precvframe;
- struct list_head *plist, *phead;
struct _adapter *padapter;
struct recv_priv *precvpriv;
spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
- if (list_empty(&pfree_recv_queue->queue)) {
- precvframe = NULL;
- } else {
- phead = &pfree_recv_queue->queue;
- plist = phead->next;
- precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
+ precvframe = list_first_entry_or_null(&pfree_recv_queue->queue,
+ union recv_frame, u.hdr.list);
+ if (precvframe) {
list_del_init(&precvframe->u.hdr.list);
padapter = precvframe->u.hdr.adapter;
if (padapter != NULL) {
spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
}
-
-static void mfree_sta_priv_lock(struct sta_priv *pstapriv)
-{
- mfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */
-}
-
u32 _r8712_free_sta_priv(struct sta_priv *pstapriv)
{
if (pstapriv) {
- mfree_sta_priv_lock(pstapriv);
+ /* be done before free sta_hash_lock */
+ mfree_all_stainfo(pstapriv);
kfree(pstapriv->pallocated_stainfo_buf);
}
return _SUCCESS;
unsigned long flags;
pfree_sta_queue = &pstapriv->free_sta_queue;
- spin_lock_irqsave(&(pfree_sta_queue->lock), flags);
- if (list_empty(&pfree_sta_queue->queue)) {
- psta = NULL;
- } else {
- psta = LIST_CONTAINOR(pfree_sta_queue->queue.next,
- struct sta_info, list);
- list_del_init(&(psta->list));
+ spin_lock_irqsave(&pfree_sta_queue->lock, flags);
+ psta = list_first_entry_or_null(&pfree_sta_queue->queue,
+ struct sta_info, list);
+ if (psta) {
+ list_del_init(&psta->list);
_init_stainfo(psta);
memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
index = wifi_mac_hash(hwaddr);
psta = NULL;
goto exit;
}
- phash_list = &(pstapriv->sta_hash[index]);
+ phash_list = &pstapriv->sta_hash[index];
list_add_tail(&psta->hash_list, phash_list);
pstapriv->asoc_sta_count++;
}
}
exit:
- spin_unlock_irqrestore(&(pfree_sta_queue->lock), flags);
+ spin_unlock_irqrestore(&pfree_sta_queue->lock, flags);
return psta;
}
struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
{
unsigned long irqL;
- struct xmit_buf *pxmitbuf = NULL;
- struct list_head *plist, *phead;
+ struct xmit_buf *pxmitbuf;
struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
- if (list_empty(&pfree_xmitbuf_queue->queue)) {
- pxmitbuf = NULL;
- } else {
- phead = &pfree_xmitbuf_queue->queue;
- plist = phead->next;
- pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
- list_del_init(&(pxmitbuf->list));
- }
- if (pxmitbuf != NULL)
+ pxmitbuf = list_first_entry_or_null(&pfree_xmitbuf_queue->queue,
+ struct xmit_buf, list);
+ if (pxmitbuf) {
+ list_del_init(&pxmitbuf->list);
pxmitpriv->free_xmitbuf_cnt--;
+ }
spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
return pxmitbuf;
}
pfree_xmit_queue
*/
unsigned long irqL;
- struct xmit_frame *pxframe = NULL;
- struct list_head *plist, *phead;
+ struct xmit_frame *pxframe;
struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
- if (list_empty(&pfree_xmit_queue->queue)) {
- pxframe = NULL;
- } else {
- phead = &pfree_xmit_queue->queue;
- plist = phead->next;
- pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
- list_del_init(&(pxframe->list));
- }
- if (pxframe != NULL) {
+ pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue,
+ struct xmit_frame, list);
+ if (pxframe) {
+ list_del_init(&pxframe->list);
pxmitpriv->free_xmitframe_cnt--;
pxframe->buf_addr = NULL;
pxframe->pxmitbuf = NULL;
static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state)
{
struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
+ struct _adapter *padapter = netdev_priv(pnetdev);
netdev_info(pnetdev, "Suspending...\n");
if (!pnetdev || !netif_running(pnetdev)) {
netdev_info(pnetdev, "Unable to suspend\n");
return 0;
}
+ padapter->bSuspended = true;
+ rtl871x_intf_stop(padapter);
if (pnetdev->netdev_ops->ndo_stop)
pnetdev->netdev_ops->ndo_stop(pnetdev);
mdelay(10);
return 0;
}
+void rtl871x_intf_resume(struct _adapter *padapter)
+{
+ if (padapter->dvobjpriv.inirp_init)
+ padapter->dvobjpriv.inirp_init(padapter);
+}
+
static int r871x_resume(struct usb_interface *pusb_intf)
{
struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
+ struct _adapter *padapter = netdev_priv(pnetdev);
netdev_info(pnetdev, "Resuming...\n");
if (!pnetdev || !netif_running(pnetdev)) {
netif_device_attach(pnetdev);
if (pnetdev->netdev_ops->ndo_open)
pnetdev->netdev_ops->ndo_open(pnetdev);
+ padapter->bSuspended = false;
+ rtl871x_intf_resume(padapter);
return 0;
}
}
} else {
switch (purb->status) {
+ case -ENOENT:
+ if (padapter->bSuspended)
+ break;
+ /* Fall through. */
case -EINVAL:
case -EPIPE:
case -ENODEV:
case -ESHUTDOWN:
- case -ENOENT:
padapter->bDriverStopped = true;
break;
case -EPROTO:
pattrib->last_txcmdsz = pattrib->pktlen;
dump_mgntframe23a(padapter, pmgntframe);
-
- return;
}
static int _issue_probereq(struct rtw_adapter *padapter,
rtw_wep_encrypt23a(padapter, pmgntframe);
DBG_8723A("%s\n", __func__);
dump_mgntframe23a(padapter, pmgntframe);
-
- return;
}
#ifdef CONFIG_8723AU_AP_MODE
}
} else
kfree(pmlmepriv->assoc_req);
-
- return;
}
/* when wait_ack is true, this function should be called at process context */
pmlmeext->chan_scan_time = SURVEY_TO;
pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
}
-
- return;
}
/* collect bss info from Beacon and Probe request/response frames. */
rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
pmlmeext->sitesurvey_res.bss_cnt++;
-
- return;
}
void report_surveydone_event23a(struct rtw_adapter *padapter)
DBG_8723A("survey done event(%x)\n", psurveydone_evt->bss_cnt);
rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
-
- return;
}
void report_join_res23a(struct rtw_adapter *padapter, int res)
rtw_joinbss_event_prehandle23a(padapter, (u8 *)&pjoinbss_evt->network);
rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
-
- return;
}
void report_del_sta_event23a(struct rtw_adapter *padapter,
DBG_8723A("report_del_sta_event23a: delete STA, mac_id =%d\n", mac_id);
rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
-
- return;
}
void report_add_sta_event23a(struct rtw_adapter *padapter,
DBG_8723A("report_add_sta_event23a: add STA\n");
rtw_enqueue_cmd23a(pcmdpriv, pcmd_obj);
-
- return;
}
/****************************************************************************
issue_assocreq(padapter);
set_link_timer(pmlmeext, REASSOC_TO);
}
-
- return;
}
static void addba_timer_hdl(unsigned long data)
int i;
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
- "*(pframemic-8)-*(pframemic-1) =0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
- *(pframemic - 8), *(pframemic - 7),
- *(pframemic - 6), *(pframemic - 5),
- *(pframemic - 4), *(pframemic - 3),
- *(pframemic - 2), *(pframemic - 1));
+ "*(pframemic-8)-*(pframemic-1) =%*phC\n",
+ 8, pframemic - 8);
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
- "*(pframemic-16)-*(pframemic-9) =0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
- *(pframemic - 16), *(pframemic - 15),
- *(pframemic - 14), *(pframemic - 13),
- *(pframemic - 12), *(pframemic - 11),
- *(pframemic - 10), *(pframemic - 9));
+ "*(pframemic-16)-*(pframemic-9) =%*phC\n",
+ 8, pframemic - 16);
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
"====== demp packet (len =%d) ======\n",
precvframe->pkt->len);
for (i = 0; i < precvframe->pkt->len; i = i + 8) {
RT_TRACE(_module_rtl871x_recv_c_,
- _drv_err_,
- "0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
- *(precvframe->pkt->data+i),
- *(precvframe->pkt->data+i+1),
- *(precvframe->pkt->data+i+2),
- *(precvframe->pkt->data+i+3),
- *(precvframe->pkt->data+i+4),
- *(precvframe->pkt->data+i+5),
- *(precvframe->pkt->data+i+6),
- *(precvframe->pkt->data+i+7));
+ _drv_err_, "%*phC\n",
+ 8, precvframe->pkt->data + i);
}
RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
"====== demp packet end [len =%d]======\n",
DBG_8723A("#############################\n");
for (i = 0; i < 64; i = i + 8)
- DBG_8723A("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n",
- *(ptr + i), *(ptr + i + 1), *(ptr + i + 2),
- *(ptr + i + 3), *(ptr + i + 4),
- *(ptr + i + 5), *(ptr + i + 6),
- *(ptr + i + 7));
+ DBG_8723A("%*phC:\n", 8, ptr + i);
DBG_8723A("#############################\n");
}
}
for (i = 0; i < sta_cnt; i++) {
if (PWDB_rssi[i] != (0))
- rtl8723a_set_rssi_cmd(Adapter, (u8 *)&PWDB_rssi[i]);
+ rtl8723a_set_rssi_cmd(Adapter, PWDB_rssi[i]);
}
pdmpriv->EntryMaxUndecoratedSmoothedPWDB = MaxDB;
}
if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_CREATOR) {
- snprintf((char *)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 32, "AMP-%02x-%02x-%02x-%02x-%02x-%02x",
- padapter->eeprompriv.mac_addr[0],
- padapter->eeprompriv.mac_addr[1],
- padapter->eeprompriv.mac_addr[2],
- padapter->eeprompriv.mac_addr[3],
- padapter->eeprompriv.mac_addr[4],
- padapter->eeprompriv.mac_addr[5]);
+ snprintf((char *)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 32,
+ "AMP-%pMF", padapter->eeprompriv.mac_addr);
} else if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_JOINER) {
- snprintf((char *)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 32, "AMP-%02x-%02x-%02x-%02x-%02x-%02x",
- pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[0],
- pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[1],
- pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[2],
- pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[3],
- pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[4],
- pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[5]);
+ snprintf((char *)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 32,
+ "AMP-%pMF", pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr);
}
FillOctetString(pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsid, pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 21);
psTdmaCase = pHalData->bt_coexist.halCoex8723.btdm1Ant.curPsTdma;
else
psTdmaCase = pHalData->bt_coexist.halCoex8723.btdm2Ant.curPsTdma;
- snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %02x %02x %02x %02x %02x case-%d", "PS TDMA(0x3a)", \
- pHalData->bt_coexist.fw3aVal[0], pHalData->bt_coexist.fw3aVal[1],
- pHalData->bt_coexist.fw3aVal[2], pHalData->bt_coexist.fw3aVal[3],
- pHalData->bt_coexist.fw3aVal[4], psTdmaCase);
+ snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %*ph case-%d",
+ "PS TDMA(0x3a)", 5, pHalData->bt_coexist.fw3aVal, psTdmaCase);
DCMD_Printf(btCoexDbgBuf);
snprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "Decrease Bt Power", \
return ret;
}
-int rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u8 *param)
+int rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u32 param)
{
- *((u32 *)param) = cpu_to_le32(*((u32 *)param));
+ __le32 cmd = cpu_to_le32(param);
- FillH2CCmd(padapter, RSSI_SETTING_EID, 3, param);
+ FillH2CCmd(padapter, RSSI_SETTING_EID, 3, (void *)&cmd);
return _SUCCESS;
}
u8 val;
val = rtl8723au_read8(padapter, REG_LEDCFG2);
- /* Let 8051 take control antenna settting */
+ /* Let 8051 take control antenna setting */
val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
rtl8723au_write8(padapter, REG_LEDCFG2, val);
}
u8 val;
val = rtl8723au_read8(padapter, REG_LEDCFG2);
- /* Let 8051 take control antenna settting */
+ /* Let 8051 take control antenna setting */
if (!(val & BIT(7))) {
val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
rtl8723au_write8(padapter, REG_LEDCFG2, val);
u8 val;
val = rtl8723au_read8(padapter, REG_LEDCFG2);
- /* Let 8051 take control antenna settting */
+ /* Let 8051 take control antenna setting */
val &= ~BIT(7); /* DPDT_SEL_EN, clear 0x4C[23] */
rtl8723au_write8(padapter, REG_LEDCFG2, val);
}
/* If we want to SS mode, we can not reset 8051. */
if ((val8 & BIT(1)) && padapter->bFWReady) {
/* IF fw in RAM code, do reset */
- /* 2010/08/25 MH Accordign to RD alfred's
+ /* 2010/08/25 MH According to RD alfred's
suggestion, we need to disable other */
/* HRCV INT to influence 8051 reset. */
rtl8723au_write8(padapter, REG_FWIMR, 0x20);
}
RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
- "Hal_EfuseParseMACAddr_8723AU: Permanent Address =%02x:%02x:%02x:%02x:%02x:%02x\n",
- pEEPROM->mac_addr[0], pEEPROM->mac_addr[1],
- pEEPROM->mac_addr[2], pEEPROM->mac_addr[3],
- pEEPROM->mac_addr[4], pEEPROM->mac_addr[5]);
+ "Hal_EfuseParseMACAddr_8723AU: Permanent Address =%pM\n",
+ pEEPROM->mac_addr);
}
static void readAdapterInfo(struct rtw_adapter *padapter)
#else
#define rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(padapter) do {} while(0)
#endif
-int rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u8 *param);
+int rtl8723a_set_rssi_cmd(struct rtw_adapter *padapter, u32 param);
int rtl8723a_set_raid_cmd(struct rtw_adapter *padapter, u32 mask, u8 arg);
void rtl8723a_add_rateatid(struct rtw_adapter *padapter, u32 bitmap, u8 arg, u8 rssi_level);
rtsx_do_before_power_down(chip, PM_S3);
if (dev->irq >= 0) {
- synchronize_irq(dev->irq);
free_irq(dev->irq, (void *)dev);
dev->irq = -1;
}
rtsx_do_before_power_down(chip, PM_S1);
if (dev->irq >= 0) {
- synchronize_irq(dev->irq);
free_irq(dev->irq, (void *)dev);
dev->irq = -1;
}
else
return -ENXIO;
- addr = dma_map_single(&(rtsx->pci->dev), buf, len, dma_dir);
- if (!addr)
+ addr = dma_map_single(&rtsx->pci->dev, buf, len, dma_dir);
+ if (dma_mapping_error(&rtsx->pci->dev, addr))
return -ENOMEM;
if (card == SD_CARD)
return STATUS_SUCCESS;
}
-
int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val)
{
int retval;
return STATUS_SUCCESS;
}
-
int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
{
struct spi_info *spi = &(chip->spi);
u32 max_isr_xmits;
u32 rcv_interrupt_yields;
u32 intagg_period;
+ u32 intagg_delay;
+ u32 dynamic_intagg;
struct inicpm_state *inicpm_info;
void *pinicpm_info;
struct slic_ifevents if_events;
static char *slic_proc_version = "2.0.351 2006/07/14 12:26:00";
static struct base_driver slic_global = { {}, 0, 0, 0, 1, NULL, NULL };
-static int intagg_delay = 100;
-static u32 dynamic_intagg;
+#define DEFAULT_INTAGG_DELAY 100
static unsigned int rcv_count;
#define DRV_NAME "slicoss"
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_LICENSE("Dual BSD/GPL");
-module_param(dynamic_intagg, int, 0);
-MODULE_PARM_DESC(dynamic_intagg, "Dynamic Interrupt Aggregation Setting");
-module_param(intagg_delay, int, 0);
-MODULE_PARM_DESC(intagg_delay, "uSec Interrupt Aggregation Delay");
-
static const struct pci_device_id slic_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_1GB_DEVICE_ID) },
{ PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_2GB_DEVICE_ID) },
{ 0 }
};
+static struct ethtool_ops slic_ethtool_ops;
+
MODULE_DEVICE_TABLE(pci, slic_pci_tbl);
static inline void slic_reg32_write(void __iomem *reg, u32 value, bool flush)
if (slic_global.dynamic_intagg)
slic_intagg_set(adapter, 0);
else
- slic_intagg_set(adapter, intagg_delay);
+ slic_intagg_set(adapter, adapter->intagg_delay);
/*
* Initialize ping status to "ok"
return status;
}
+static int slic_get_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *coalesce)
+{
+ struct adapter *adapter = netdev_priv(dev);
+
+ adapter->intagg_delay = coalesce->rx_coalesce_usecs;
+ adapter->dynamic_intagg = coalesce->use_adaptive_rx_coalesce;
+ return 0;
+}
+
+static int slic_set_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *coalesce)
+{
+ struct adapter *adapter = netdev_priv(dev);
+
+ coalesce->rx_coalesce_usecs = adapter->intagg_delay;
+ coalesce->use_adaptive_rx_coalesce = adapter->dynamic_intagg;
+ return 0;
+}
+
static void slic_init_driver(void)
{
if (slic_first_init) {
struct sliccard *card = NULL;
int pci_using_dac = 0;
- slic_global.dynamic_intagg = dynamic_intagg;
-
err = pci_enable_device(pcidev);
if (err)
goto err_out_exit_slic_probe;
}
+ netdev->ethtool_ops = &slic_ethtool_ops;
SET_NETDEV_DEV(netdev, &pcidev->dev);
pci_set_drvdata(pcidev, netdev);
adapter = netdev_priv(netdev);
adapter->netdev = netdev;
adapter->pcidev = pcidev;
+ slic_global.dynamic_intagg = adapter->dynamic_intagg;
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
pci_unregister_driver(&slic_driver);
}
+static struct ethtool_ops slic_ethtool_ops = {
+ .get_coalesce = slic_get_coalesce,
+ .set_coalesce = slic_set_coalesce
+};
+
module_init(slic_module_init);
module_exit(slic_module_cleanup);
static void setMemoryClock(unsigned int frequency)
{
- unsigned int ulReg, divisor;
+ unsigned int reg, divisor;
/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
if (getChipType() == SM750LE)
divisor = roundedDiv(get_mxclk_freq(), frequency);
/* Set the corresponding divisor in the register. */
- ulReg = PEEK32(CURRENT_GATE);
+ reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK;
switch (divisor) {
default:
case 1:
- ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_1);
+ reg |= CURRENT_GATE_M2XCLK_DIV_1;
break;
case 2:
- ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_2);
+ reg |= CURRENT_GATE_M2XCLK_DIV_2;
break;
case 3:
- ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_3);
+ reg |= CURRENT_GATE_M2XCLK_DIV_3;
break;
case 4:
- ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_4);
+ reg |= CURRENT_GATE_M2XCLK_DIV_4;
break;
}
- setCurrentGate(ulReg);
+ setCurrentGate(reg);
}
}
*/
static void setMasterClock(unsigned int frequency)
{
- unsigned int ulReg, divisor;
+ unsigned int reg, divisor;
/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */
if (getChipType() == SM750LE)
divisor = roundedDiv(get_mxclk_freq(), frequency);
/* Set the corresponding divisor in the register. */
- ulReg = PEEK32(CURRENT_GATE);
+ reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK;
switch (divisor) {
default:
case 3:
- ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_3);
+ reg |= CURRENT_GATE_MCLK_DIV_3;
break;
case 4:
- ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_4);
+ reg |= CURRENT_GATE_MCLK_DIV_4;
break;
case 6:
- ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_6);
+ reg |= CURRENT_GATE_MCLK_DIV_6;
break;
case 8:
- ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_8);
+ reg |= CURRENT_GATE_MCLK_DIV_8;
break;
}
- setCurrentGate(ulReg);
+ setCurrentGate(reg);
}
}
/* for 750,always use power mode0*/
reg = PEEK32(MODE0_GATE);
- reg = FIELD_SET(reg, MODE0_GATE, GPIO, ON);
+ reg |= MODE0_GATE_GPIO;
POKE32(MODE0_GATE, reg);
/* get frame buffer size from GPIO */
- reg = FIELD_GET(PEEK32(MISC_CTRL), MISC_CTRL, LOCALMEM_SIZE);
+ reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK;
switch (reg) {
case MISC_CTRL_LOCALMEM_SIZE_8M:
data = SZ_8M; break; /* 8 Mega byte */
int ddk750_initHw(initchip_param_t *pInitParam)
{
- unsigned int ulReg;
+ unsigned int reg;
if (pInitParam->powerMode != 0)
pInitParam->powerMode = 0;
setPowerMode(pInitParam->powerMode);
/* Enable display power gate & LOCALMEM power gate*/
- ulReg = PEEK32(CURRENT_GATE);
- ulReg = FIELD_SET(ulReg, CURRENT_GATE, DISPLAY, ON);
- ulReg = FIELD_SET(ulReg, CURRENT_GATE, LOCALMEM, ON);
- setCurrentGate(ulReg);
+ reg = PEEK32(CURRENT_GATE);
+ reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM);
+ setCurrentGate(reg);
if (getChipType() != SM750LE) {
/* set panel pll and graphic mode via mmio_88 */
- ulReg = PEEK32(VGA_CONFIGURATION);
- ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, PLL, PANEL);
- ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, MODE, GRAPHIC);
- POKE32(VGA_CONFIGURATION, ulReg);
+ reg = PEEK32(VGA_CONFIGURATION);
+ reg = FIELD_SET(reg, VGA_CONFIGURATION, PLL, PANEL);
+ reg = FIELD_SET(reg, VGA_CONFIGURATION, MODE, GRAPHIC);
+ POKE32(VGA_CONFIGURATION, reg);
} else {
#if defined(__i386__) || defined(__x86_64__)
/* set graphic mode via IO method */
The memory should be resetted after changing the MXCLK.
*/
if (pInitParam->resetMemory == 1) {
- ulReg = PEEK32(MISC_CTRL);
- ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, RESET);
- POKE32(MISC_CTRL, ulReg);
+ reg = PEEK32(MISC_CTRL);
+ reg &= ~MISC_CTRL_LOCALMEM_RESET;
+ POKE32(MISC_CTRL, reg);
- ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, NORMAL);
- POKE32(MISC_CTRL, ulReg);
+ reg |= MISC_CTRL_LOCALMEM_RESET;
+ POKE32(MISC_CTRL, reg);
}
if (pInitParam->setAllEngOff == 1) {
enable2DEngine(0);
/* Disable Overlay, if a former application left it on */
- ulReg = PEEK32(VIDEO_DISPLAY_CTRL);
- ulReg = FIELD_SET(ulReg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE);
- POKE32(VIDEO_DISPLAY_CTRL, ulReg);
+ reg = PEEK32(VIDEO_DISPLAY_CTRL);
+ reg = FIELD_SET(reg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE);
+ POKE32(VIDEO_DISPLAY_CTRL, reg);
/* Disable video alpha, if a former application left it on */
- ulReg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
- ulReg = FIELD_SET(ulReg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
- POKE32(VIDEO_ALPHA_DISPLAY_CTRL, ulReg);
+ reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL);
+ reg = FIELD_SET(reg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
+ POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg);
/* Disable alpha plane, if a former application left it on */
- ulReg = PEEK32(ALPHA_DISPLAY_CTRL);
- ulReg = FIELD_SET(ulReg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
- POKE32(ALPHA_DISPLAY_CTRL, ulReg);
+ reg = PEEK32(ALPHA_DISPLAY_CTRL);
+ reg = FIELD_SET(reg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE);
+ POKE32(ALPHA_DISPLAY_CTRL, reg);
/* Disable DMA Channel, if a former application left it on */
- ulReg = PEEK32(DMA_ABORT_INTERRUPT);
- ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
- POKE32(DMA_ABORT_INTERRUPT, ulReg);
+ reg = PEEK32(DMA_ABORT_INTERRUPT);
+ reg = FIELD_SET(reg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT);
+ POKE32(DMA_ABORT_INTERRUPT, reg);
/* Disable DMA Power, if a former application left it on */
enableDMA(0);
while (delay-- > 0) {
/* Wait for end of vsync. */
do {
- status = FIELD_GET(PEEK32(SYSTEM_CTRL),
- SYSTEM_CTRL,
- PANEL_VSYNC);
- } while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
+ status = PEEK32(SYSTEM_CTRL);
+ } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
/* Wait for start of vsync. */
do {
- status = FIELD_GET(PEEK32(SYSTEM_CTRL),
- SYSTEM_CTRL,
- PANEL_VSYNC);
- } while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE);
+ status = PEEK32(SYSTEM_CTRL);
+ } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE));
}
} else {
while (delay-- > 0) {
/* Wait for end of vsync. */
do {
- status = FIELD_GET(PEEK32(SYSTEM_CTRL),
- SYSTEM_CTRL,
- CRT_VSYNC);
- } while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
+ status = PEEK32(SYSTEM_CTRL);
+ } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
/* Wait for start of vsync. */
do {
- status = FIELD_GET(PEEK32(SYSTEM_CTRL),
- SYSTEM_CTRL,
- CRT_VSYNC);
- } while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE);
+ status = PEEK32(SYSTEM_CTRL);
+ } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE));
}
}
}
/* Enable GPIO 30 & 31 as IIC clock & data */
value = PEEK32(GPIO_MUX);
- value = FIELD_SET(value, GPIO_MUX, 30, I2C) |
- FIELD_SET(0, GPIO_MUX, 31, I2C);
+ value |= (GPIO_MUX_30 | GPIO_MUX_31);
POKE32(GPIO_MUX, value);
/* Enable Hardware I2C power.
/* Set GPIO 30 & 31 back as GPIO pins */
value = PEEK32(GPIO_MUX);
- value = FIELD_SET(value, GPIO_MUX, 30, GPIO);
- value = FIELD_SET(value, GPIO_MUX, 31, GPIO);
+ value &= ~GPIO_MUX_30;
+ value &= ~GPIO_MUX_31;
POKE32(GPIO_MUX, value);
}
if (hw_i2c_wait_tx_done() != 0)
break;
- /* Substract length */
+ /* Subtract length */
length -= (count + 1);
/* Total byte written */
for (i = 0; i <= count; i++)
*buf++ = PEEK32(I2C_DATA0 + i);
- /* Substract length by 16 */
+ /* Subtract length by 16 */
length -= (count + 1);
/* Number of bytes read. */
| FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0));
POKE32(CRT_AUTO_CENTERING_BR,
- FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y-1)
- | FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x-1));
+ FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y - 1)
+ | FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x - 1));
/* Assume common fields in dispControl have been properly set before
calling this function.
dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK);
/* Set bit 29:27 of display control register for the right clock */
- /* Note that SM750LE only need to supported 7 resoluitons. */
+ /* Note that SM750LE only need to supported 7 resolutions. */
if (x == 800 && y == 600)
dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41);
else if (x == 1024 && y == 768)
| FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
- ulTmpValue = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)|
- FIELD_VALUE(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)|
- FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE)|
+ ulTmpValue = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity) |
+ FIELD_VALUE(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity) |
+ FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE) |
FIELD_SET(0, CRT_DISPLAY_CTRL, PLANE, ENABLE);
& FIELD_CLEAR(CRT_DISPLAY_CTRL, TIMING)
& FIELD_CLEAR(CRT_DISPLAY_CTRL, PLANE);
- POKE32(CRT_DISPLAY_CTRL, ulTmpValue|ulReg);
+ POKE32(CRT_DISPLAY_CTRL, ulTmpValue | ulReg);
}
} else if (pll->clockType == PRIMARY_PLL) {
FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
| FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
- ulTmpValue = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)|
- FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)|
- FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity)|
- FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE)|
+ ulTmpValue = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity) |
+ FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity) |
+ FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity) |
+ FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE) |
FIELD_SET(0, PANEL_DISPLAY_CTRL, PLANE, ENABLE);
ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) |
FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) |
- FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE)|
+ FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) |
FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW);
ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits)
* next vertical sync to turn on/off the plane.
*/
- POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
+ POKE32(PANEL_DISPLAY_CTRL, ulTmpValue | ulReg);
- while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) {
+ while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue | ulReg)) {
cnt++;
if (cnt > 1000)
break;
- POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
+ POKE32(PANEL_DISPLAY_CTRL, ulTmpValue | ulReg);
}
} else {
ret = -1;
DPMS, state));
} else {
value = PEEK32(SYSTEM_CTRL);
- value = FIELD_VALUE(value, SYSTEM_CTRL, DPMS, state);
+ value = (value & ~SYSTEM_CTRL_DPMS_MASK) | state;
POKE32(SYSTEM_CTRL, value);
}
}
{
if (getChipType() == SM750LE)
return 0;
- return FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE);
+ return PEEK32(POWER_MODE_CTRL) & POWER_MODE_CTRL_MODE_MASK;
}
{
unsigned int control_value = 0;
- control_value = PEEK32(POWER_MODE_CTRL);
+ control_value = PEEK32(POWER_MODE_CTRL) & ~POWER_MODE_CTRL_MODE_MASK;
if (getChipType() == SM750LE)
return;
switch (powerMode) {
case POWER_MODE_CTRL_MODE_MODE0:
- control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE,
- MODE0);
+ control_value |= POWER_MODE_CTRL_MODE_MODE0;
break;
case POWER_MODE_CTRL_MODE_MODE1:
- control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE,
- MODE1);
+ control_value |= POWER_MODE_CTRL_MODE_MODE1;
break;
case POWER_MODE_CTRL_MODE_SLEEP:
- control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE,
- SLEEP);
+ control_value |= POWER_MODE_CTRL_MODE_SLEEP;
break;
default:
/* Set up other fields in Power Control Register */
if (powerMode == POWER_MODE_CTRL_MODE_SLEEP) {
- control_value =
+ control_value &= ~POWER_MODE_CTRL_OSC_INPUT;
#ifdef VALIDATION_CHIP
- FIELD_SET(control_value, POWER_MODE_CTRL, 336CLK, OFF) |
+ control_value &= ~POWER_MODE_CTRL_336CLK;
#endif
- FIELD_SET(control_value, POWER_MODE_CTRL, OSC_INPUT, OFF);
} else {
- control_value =
+ control_value |= POWER_MODE_CTRL_OSC_INPUT;
#ifdef VALIDATION_CHIP
- FIELD_SET(control_value, POWER_MODE_CTRL, 336CLK, ON) |
+ control_value |= POWER_MODE_CTRL_336CLK;
#endif
- FIELD_SET(control_value, POWER_MODE_CTRL, OSC_INPUT, ON);
}
/* Program new power mode. */
gate = PEEK32(CURRENT_GATE);
if (enable) {
- gate = FIELD_SET(gate, CURRENT_GATE, DE, ON);
- gate = FIELD_SET(gate, CURRENT_GATE, CSC, ON);
+ gate |= (CURRENT_GATE_DE | CURRENT_GATE_CSC);
} else {
- gate = FIELD_SET(gate, CURRENT_GATE, DE, OFF);
- gate = FIELD_SET(gate, CURRENT_GATE, CSC, OFF);
+ gate &= ~(CURRENT_GATE_DE | CURRENT_GATE_CSC);
}
setCurrentGate(gate);
/* Enable DMA Gate */
gate = PEEK32(CURRENT_GATE);
if (enable)
- gate = FIELD_SET(gate, CURRENT_GATE, DMA, ON);
+ gate |= CURRENT_GATE_DMA;
else
- gate = FIELD_SET(gate, CURRENT_GATE, DMA, OFF);
+ gate &= ~CURRENT_GATE_DMA;
setCurrentGate(gate);
}
/* Enable GPIO Gate */
gate = PEEK32(CURRENT_GATE);
if (enable)
- gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON);
+ gate |= CURRENT_GATE_GPIO;
else
- gate = FIELD_SET(gate, CURRENT_GATE, GPIO, OFF);
+ gate &= ~CURRENT_GATE_GPIO;
setCurrentGate(gate);
}
/* Enable I2C Gate */
gate = PEEK32(CURRENT_GATE);
if (enable)
- gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON);
+ gate |= CURRENT_GATE_I2C;
else
- gate = FIELD_SET(gate, CURRENT_GATE, I2C, OFF);
+ gate &= ~CURRENT_GATE_I2C;
setCurrentGate(gate);
}
}
DPMS_t;
-#define setDAC(off) \
- { \
- POKE32(MISC_CTRL, FIELD_VALUE(PEEK32(MISC_CTRL), \
- MISC_CTRL, \
- DAC_POWER, \
- off)); \
- }
+#define setDAC(off) { \
+ POKE32(MISC_CTRL, \
+ (PEEK32(MISC_CTRL) & ~MISC_CTRL_DAC_POWER_OFF) | (off)); \
+}
void ddk750_setDPMS(DPMS_t);
/* New register for SM750LE */
#define DE_STATE1 0x100054
-#define DE_STATE1_DE_ABORT 0:0
-#define DE_STATE1_DE_ABORT_OFF 0
-#define DE_STATE1_DE_ABORT_ON 1
+#define DE_STATE1_DE_ABORT BIT(0)
#define DE_STATE2 0x100058
-#define DE_STATE2_DE_FIFO 3:3
-#define DE_STATE2_DE_FIFO_NOTEMPTY 0
-#define DE_STATE2_DE_FIFO_EMPTY 1
-#define DE_STATE2_DE_STATUS 2:2
-#define DE_STATE2_DE_STATUS_IDLE 0
-#define DE_STATE2_DE_STATUS_BUSY 1
-#define DE_STATE2_DE_MEM_FIFO 1:1
-#define DE_STATE2_DE_MEM_FIFO_NOTEMPTY 0
-#define DE_STATE2_DE_MEM_FIFO_EMPTY 1
-#define DE_STATE2_DE_RESERVED 0:0
-
-
+#define DE_STATE2_DE_FIFO_EMPTY BIT(3)
+#define DE_STATE2_DE_STATUS_BUSY BIT(2)
+#define DE_STATE2_DE_MEM_FIFO_EMPTY BIT(1)
#define SYSTEM_CTRL 0x000000
-#define SYSTEM_CTRL_DPMS 31:30
-#define SYSTEM_CTRL_DPMS_VPHP 0
-#define SYSTEM_CTRL_DPMS_VPHN 1
-#define SYSTEM_CTRL_DPMS_VNHP 2
-#define SYSTEM_CTRL_DPMS_VNHN 3
-#define SYSTEM_CTRL_PCI_BURST 29:29
-#define SYSTEM_CTRL_PCI_BURST_OFF 0
-#define SYSTEM_CTRL_PCI_BURST_ON 1
-#define SYSTEM_CTRL_PCI_MASTER 25:25
-#define SYSTEM_CTRL_PCI_MASTER_OFF 0
-#define SYSTEM_CTRL_PCI_MASTER_ON 1
-#define SYSTEM_CTRL_LATENCY_TIMER 24:24
-#define SYSTEM_CTRL_LATENCY_TIMER_ON 0
-#define SYSTEM_CTRL_LATENCY_TIMER_OFF 1
-#define SYSTEM_CTRL_DE_FIFO 23:23
-#define SYSTEM_CTRL_DE_FIFO_NOTEMPTY 0
-#define SYSTEM_CTRL_DE_FIFO_EMPTY 1
-#define SYSTEM_CTRL_DE_STATUS 22:22
-#define SYSTEM_CTRL_DE_STATUS_IDLE 0
-#define SYSTEM_CTRL_DE_STATUS_BUSY 1
-#define SYSTEM_CTRL_DE_MEM_FIFO 21:21
-#define SYSTEM_CTRL_DE_MEM_FIFO_NOTEMPTY 0
-#define SYSTEM_CTRL_DE_MEM_FIFO_EMPTY 1
-#define SYSTEM_CTRL_CSC_STATUS 20:20
-#define SYSTEM_CTRL_CSC_STATUS_IDLE 0
-#define SYSTEM_CTRL_CSC_STATUS_BUSY 1
-#define SYSTEM_CTRL_CRT_VSYNC 19:19
-#define SYSTEM_CTRL_CRT_VSYNC_INACTIVE 0
-#define SYSTEM_CTRL_CRT_VSYNC_ACTIVE 1
-#define SYSTEM_CTRL_PANEL_VSYNC 18:18
-#define SYSTEM_CTRL_PANEL_VSYNC_INACTIVE 0
-#define SYSTEM_CTRL_PANEL_VSYNC_ACTIVE 1
-#define SYSTEM_CTRL_CURRENT_BUFFER 17:17
-#define SYSTEM_CTRL_CURRENT_BUFFER_NORMAL 0
-#define SYSTEM_CTRL_CURRENT_BUFFER_FLIP_PENDING 1
-#define SYSTEM_CTRL_DMA_STATUS 16:16
-#define SYSTEM_CTRL_DMA_STATUS_IDLE 0
-#define SYSTEM_CTRL_DMA_STATUS_BUSY 1
-#define SYSTEM_CTRL_PCI_BURST_READ 15:15
-#define SYSTEM_CTRL_PCI_BURST_READ_OFF 0
-#define SYSTEM_CTRL_PCI_BURST_READ_ON 1
-#define SYSTEM_CTRL_DE_ABORT 13:13
-#define SYSTEM_CTRL_DE_ABORT_OFF 0
-#define SYSTEM_CTRL_DE_ABORT_ON 1
-#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK 11:11
-#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK_OFF 0
-#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK_ON 1
-#define SYSTEM_CTRL_PCI_RETRY 7:7
-#define SYSTEM_CTRL_PCI_RETRY_ON 0
-#define SYSTEM_CTRL_PCI_RETRY_OFF 1
-#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE 5:4
-#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_1 0
-#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_2 1
-#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_4 2
-#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_8 3
-#define SYSTEM_CTRL_CRT_TRISTATE 3:3
-#define SYSTEM_CTRL_CRT_TRISTATE_OFF 0
-#define SYSTEM_CTRL_CRT_TRISTATE_ON 1
-#define SYSTEM_CTRL_PCIMEM_TRISTATE 2:2
-#define SYSTEM_CTRL_PCIMEM_TRISTATE_OFF 0
-#define SYSTEM_CTRL_PCIMEM_TRISTATE_ON 1
-#define SYSTEM_CTRL_LOCALMEM_TRISTATE 1:1
-#define SYSTEM_CTRL_LOCALMEM_TRISTATE_OFF 0
-#define SYSTEM_CTRL_LOCALMEM_TRISTATE_ON 1
-#define SYSTEM_CTRL_PANEL_TRISTATE 0:0
-#define SYSTEM_CTRL_PANEL_TRISTATE_OFF 0
-#define SYSTEM_CTRL_PANEL_TRISTATE_ON 1
+#define SYSTEM_CTRL_DPMS_MASK (0x3 << 30)
+#define SYSTEM_CTRL_DPMS_VPHP (0x0 << 30)
+#define SYSTEM_CTRL_DPMS_VPHN (0x1 << 30)
+#define SYSTEM_CTRL_DPMS_VNHP (0x2 << 30)
+#define SYSTEM_CTRL_DPMS_VNHN (0x3 << 30)
+#define SYSTEM_CTRL_PCI_BURST BIT(29)
+#define SYSTEM_CTRL_PCI_MASTER BIT(25)
+#define SYSTEM_CTRL_LATENCY_TIMER_OFF BIT(24)
+#define SYSTEM_CTRL_DE_FIFO_EMPTY BIT(23)
+#define SYSTEM_CTRL_DE_STATUS_BUSY BIT(22)
+#define SYSTEM_CTRL_DE_MEM_FIFO_EMPTY BIT(21)
+#define SYSTEM_CTRL_CSC_STATUS_BUSY BIT(20)
+#define SYSTEM_CTRL_CRT_VSYNC_ACTIVE BIT(19)
+#define SYSTEM_CTRL_PANEL_VSYNC_ACTIVE BIT(18)
+#define SYSTEM_CTRL_CURRENT_BUFFER_FLIP_PENDING BIT(17)
+#define SYSTEM_CTRL_DMA_STATUS_BUSY BIT(16)
+#define SYSTEM_CTRL_PCI_BURST_READ BIT(15)
+#define SYSTEM_CTRL_DE_ABORT BIT(13)
+#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK BIT(11)
+#define SYSTEM_CTRL_PCI_RETRY_OFF BIT(7)
+#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_MASK (0x3 << 4)
+#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_1 (0x0 << 4)
+#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_2 (0x1 << 4)
+#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_4 (0x2 << 4)
+#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_8 (0x3 << 4)
+#define SYSTEM_CTRL_CRT_TRISTATE BIT(3)
+#define SYSTEM_CTRL_PCIMEM_TRISTATE BIT(2)
+#define SYSTEM_CTRL_LOCALMEM_TRISTATE BIT(1)
+#define SYSTEM_CTRL_PANEL_TRISTATE BIT(0)
#define MISC_CTRL 0x000004
-#define MISC_CTRL_DRAM_RERESH_COUNT 27:27
-#define MISC_CTRL_DRAM_RERESH_COUNT_1ROW 0
-#define MISC_CTRL_DRAM_RERESH_COUNT_3ROW 1
-#define MISC_CTRL_DRAM_REFRESH_TIME 26:25
-#define MISC_CTRL_DRAM_REFRESH_TIME_8 0
-#define MISC_CTRL_DRAM_REFRESH_TIME_16 1
-#define MISC_CTRL_DRAM_REFRESH_TIME_32 2
-#define MISC_CTRL_DRAM_REFRESH_TIME_64 3
-#define MISC_CTRL_INT_OUTPUT 24:24
-#define MISC_CTRL_INT_OUTPUT_NORMAL 0
-#define MISC_CTRL_INT_OUTPUT_INVERT 1
-#define MISC_CTRL_PLL_CLK_COUNT 23:23
-#define MISC_CTRL_PLL_CLK_COUNT_OFF 0
-#define MISC_CTRL_PLL_CLK_COUNT_ON 1
-#define MISC_CTRL_DAC_POWER 20:20
-#define MISC_CTRL_DAC_POWER_ON 0
-#define MISC_CTRL_DAC_POWER_OFF 1
-#define MISC_CTRL_CLK_SELECT 16:16
-#define MISC_CTRL_CLK_SELECT_OSC 0
-#define MISC_CTRL_CLK_SELECT_TESTCLK 1
-#define MISC_CTRL_DRAM_COLUMN_SIZE 15:14
-#define MISC_CTRL_DRAM_COLUMN_SIZE_256 0
-#define MISC_CTRL_DRAM_COLUMN_SIZE_512 1
-#define MISC_CTRL_DRAM_COLUMN_SIZE_1024 2
-#define MISC_CTRL_LOCALMEM_SIZE 13:12
-#define MISC_CTRL_LOCALMEM_SIZE_8M 3
-#define MISC_CTRL_LOCALMEM_SIZE_16M 0
-#define MISC_CTRL_LOCALMEM_SIZE_32M 1
-#define MISC_CTRL_LOCALMEM_SIZE_64M 2
-#define MISC_CTRL_DRAM_TWTR 11:11
-#define MISC_CTRL_DRAM_TWTR_2CLK 0
-#define MISC_CTRL_DRAM_TWTR_1CLK 1
-#define MISC_CTRL_DRAM_TWR 10:10
-#define MISC_CTRL_DRAM_TWR_3CLK 0
-#define MISC_CTRL_DRAM_TWR_2CLK 1
-#define MISC_CTRL_DRAM_TRP 9:9
-#define MISC_CTRL_DRAM_TRP_3CLK 0
-#define MISC_CTRL_DRAM_TRP_4CLK 1
-#define MISC_CTRL_DRAM_TRFC 8:8
-#define MISC_CTRL_DRAM_TRFC_12CLK 0
-#define MISC_CTRL_DRAM_TRFC_14CLK 1
-#define MISC_CTRL_DRAM_TRAS 7:7
-#define MISC_CTRL_DRAM_TRAS_7CLK 0
-#define MISC_CTRL_DRAM_TRAS_8CLK 1
-#define MISC_CTRL_LOCALMEM_RESET 6:6
-#define MISC_CTRL_LOCALMEM_RESET_RESET 0
-#define MISC_CTRL_LOCALMEM_RESET_NORMAL 1
-#define MISC_CTRL_LOCALMEM_STATE 5:5
-#define MISC_CTRL_LOCALMEM_STATE_ACTIVE 0
-#define MISC_CTRL_LOCALMEM_STATE_INACTIVE 1
-#define MISC_CTRL_CPU_CAS_LATENCY 4:4
-#define MISC_CTRL_CPU_CAS_LATENCY_2CLK 0
-#define MISC_CTRL_CPU_CAS_LATENCY_3CLK 1
-#define MISC_CTRL_DLL 3:3
-#define MISC_CTRL_DLL_ON 0
-#define MISC_CTRL_DLL_OFF 1
-#define MISC_CTRL_DRAM_OUTPUT 2:2
-#define MISC_CTRL_DRAM_OUTPUT_LOW 0
-#define MISC_CTRL_DRAM_OUTPUT_HIGH 1
-#define MISC_CTRL_LOCALMEM_BUS_SIZE 1:1
-#define MISC_CTRL_LOCALMEM_BUS_SIZE_32 0
-#define MISC_CTRL_LOCALMEM_BUS_SIZE_64 1
-#define MISC_CTRL_EMBEDDED_LOCALMEM 0:0
-#define MISC_CTRL_EMBEDDED_LOCALMEM_ON 0
-#define MISC_CTRL_EMBEDDED_LOCALMEM_OFF 1
+#define MISC_CTRL_DRAM_RERESH_COUNT BIT(27)
+#define MISC_CTRL_DRAM_REFRESH_TIME_MASK (0x3 << 25)
+#define MISC_CTRL_DRAM_REFRESH_TIME_8 (0x0 << 25)
+#define MISC_CTRL_DRAM_REFRESH_TIME_16 (0x1 << 25)
+#define MISC_CTRL_DRAM_REFRESH_TIME_32 (0x2 << 25)
+#define MISC_CTRL_DRAM_REFRESH_TIME_64 (0x3 << 25)
+#define MISC_CTRL_INT_OUTPUT_INVERT BIT(24)
+#define MISC_CTRL_PLL_CLK_COUNT BIT(23)
+#define MISC_CTRL_DAC_POWER_OFF BIT(20)
+#define MISC_CTRL_CLK_SELECT_TESTCLK BIT(16)
+#define MISC_CTRL_DRAM_COLUMN_SIZE_MASK (0x3 << 14)
+#define MISC_CTRL_DRAM_COLUMN_SIZE_256 (0x0 << 14)
+#define MISC_CTRL_DRAM_COLUMN_SIZE_512 (0x1 << 14)
+#define MISC_CTRL_DRAM_COLUMN_SIZE_1024 (0x2 << 14)
+#define MISC_CTRL_LOCALMEM_SIZE_MASK (0x3 << 12)
+#define MISC_CTRL_LOCALMEM_SIZE_8M (0x3 << 12)
+#define MISC_CTRL_LOCALMEM_SIZE_16M (0x0 << 12)
+#define MISC_CTRL_LOCALMEM_SIZE_32M (0x1 << 12)
+#define MISC_CTRL_LOCALMEM_SIZE_64M (0x2 << 12)
+#define MISC_CTRL_DRAM_TWTR BIT(11)
+#define MISC_CTRL_DRAM_TWR BIT(10)
+#define MISC_CTRL_DRAM_TRP BIT(9)
+#define MISC_CTRL_DRAM_TRFC BIT(8)
+#define MISC_CTRL_DRAM_TRAS BIT(7)
+#define MISC_CTRL_LOCALMEM_RESET BIT(6)
+#define MISC_CTRL_LOCALMEM_STATE_INACTIVE BIT(5)
+#define MISC_CTRL_CPU_CAS_LATENCY BIT(4)
+#define MISC_CTRL_DLL_OFF BIT(3)
+#define MISC_CTRL_DRAM_OUTPUT_HIGH BIT(2)
+#define MISC_CTRL_LOCALMEM_BUS_SIZE BIT(1)
+#define MISC_CTRL_EMBEDDED_LOCALMEM_OFF BIT(0)
#define GPIO_MUX 0x000008
-#define GPIO_MUX_31 31:31
-#define GPIO_MUX_31_GPIO 0
-#define GPIO_MUX_31_I2C 1
-#define GPIO_MUX_30 30:30
-#define GPIO_MUX_30_GPIO 0
-#define GPIO_MUX_30_I2C 1
-#define GPIO_MUX_29 29:29
-#define GPIO_MUX_29_GPIO 0
-#define GPIO_MUX_29_SSP1 1
-#define GPIO_MUX_28 28:28
-#define GPIO_MUX_28_GPIO 0
-#define GPIO_MUX_28_SSP1 1
-#define GPIO_MUX_27 27:27
-#define GPIO_MUX_27_GPIO 0
-#define GPIO_MUX_27_SSP1 1
-#define GPIO_MUX_26 26:26
-#define GPIO_MUX_26_GPIO 0
-#define GPIO_MUX_26_SSP1 1
-#define GPIO_MUX_25 25:25
-#define GPIO_MUX_25_GPIO 0
-#define GPIO_MUX_25_SSP1 1
-#define GPIO_MUX_24 24:24
-#define GPIO_MUX_24_GPIO 0
-#define GPIO_MUX_24_SSP0 1
-#define GPIO_MUX_23 23:23
-#define GPIO_MUX_23_GPIO 0
-#define GPIO_MUX_23_SSP0 1
-#define GPIO_MUX_22 22:22
-#define GPIO_MUX_22_GPIO 0
-#define GPIO_MUX_22_SSP0 1
-#define GPIO_MUX_21 21:21
-#define GPIO_MUX_21_GPIO 0
-#define GPIO_MUX_21_SSP0 1
-#define GPIO_MUX_20 20:20
-#define GPIO_MUX_20_GPIO 0
-#define GPIO_MUX_20_SSP0 1
-#define GPIO_MUX_19 19:19
-#define GPIO_MUX_19_GPIO 0
-#define GPIO_MUX_19_PWM 1
-#define GPIO_MUX_18 18:18
-#define GPIO_MUX_18_GPIO 0
-#define GPIO_MUX_18_PWM 1
-#define GPIO_MUX_17 17:17
-#define GPIO_MUX_17_GPIO 0
-#define GPIO_MUX_17_PWM 1
-#define GPIO_MUX_16 16:16
-#define GPIO_MUX_16_GPIO_ZVPORT 0
-#define GPIO_MUX_16_TEST_DATA 1
-#define GPIO_MUX_15 15:15
-#define GPIO_MUX_15_GPIO_ZVPORT 0
-#define GPIO_MUX_15_TEST_DATA 1
-#define GPIO_MUX_14 14:14
-#define GPIO_MUX_14_GPIO_ZVPORT 0
-#define GPIO_MUX_14_TEST_DATA 1
-#define GPIO_MUX_13 13:13
-#define GPIO_MUX_13_GPIO_ZVPORT 0
-#define GPIO_MUX_13_TEST_DATA 1
-#define GPIO_MUX_12 12:12
-#define GPIO_MUX_12_GPIO_ZVPORT 0
-#define GPIO_MUX_12_TEST_DATA 1
-#define GPIO_MUX_11 11:11
-#define GPIO_MUX_11_GPIO_ZVPORT 0
-#define GPIO_MUX_11_TEST_DATA 1
-#define GPIO_MUX_10 10:10
-#define GPIO_MUX_10_GPIO_ZVPORT 0
-#define GPIO_MUX_10_TEST_DATA 1
-#define GPIO_MUX_9 9:9
-#define GPIO_MUX_9_GPIO_ZVPORT 0
-#define GPIO_MUX_9_TEST_DATA 1
-#define GPIO_MUX_8 8:8
-#define GPIO_MUX_8_GPIO_ZVPORT 0
-#define GPIO_MUX_8_TEST_DATA 1
-#define GPIO_MUX_7 7:7
-#define GPIO_MUX_7_GPIO_ZVPORT 0
-#define GPIO_MUX_7_TEST_DATA 1
-#define GPIO_MUX_6 6:6
-#define GPIO_MUX_6_GPIO_ZVPORT 0
-#define GPIO_MUX_6_TEST_DATA 1
-#define GPIO_MUX_5 5:5
-#define GPIO_MUX_5_GPIO_ZVPORT 0
-#define GPIO_MUX_5_TEST_DATA 1
-#define GPIO_MUX_4 4:4
-#define GPIO_MUX_4_GPIO_ZVPORT 0
-#define GPIO_MUX_4_TEST_DATA 1
-#define GPIO_MUX_3 3:3
-#define GPIO_MUX_3_GPIO_ZVPORT 0
-#define GPIO_MUX_3_TEST_DATA 1
-#define GPIO_MUX_2 2:2
-#define GPIO_MUX_2_GPIO_ZVPORT 0
-#define GPIO_MUX_2_TEST_DATA 1
-#define GPIO_MUX_1 1:1
-#define GPIO_MUX_1_GPIO_ZVPORT 0
-#define GPIO_MUX_1_TEST_DATA 1
-#define GPIO_MUX_0 0:0
-#define GPIO_MUX_0_GPIO_ZVPORT 0
-#define GPIO_MUX_0_TEST_DATA 1
+#define GPIO_MUX_31 BIT(31)
+#define GPIO_MUX_30 BIT(30)
+#define GPIO_MUX_29 BIT(29)
+#define GPIO_MUX_28 BIT(28)
+#define GPIO_MUX_27 BIT(27)
+#define GPIO_MUX_26 BIT(26)
+#define GPIO_MUX_25 BIT(25)
+#define GPIO_MUX_24 BIT(24)
+#define GPIO_MUX_23 BIT(23)
+#define GPIO_MUX_22 BIT(22)
+#define GPIO_MUX_21 BIT(21)
+#define GPIO_MUX_20 BIT(20)
+#define GPIO_MUX_19 BIT(19)
+#define GPIO_MUX_18 BIT(18)
+#define GPIO_MUX_17 BIT(17)
+#define GPIO_MUX_16 BIT(16)
+#define GPIO_MUX_15 BIT(15)
+#define GPIO_MUX_14 BIT(14)
+#define GPIO_MUX_13 BIT(13)
+#define GPIO_MUX_12 BIT(12)
+#define GPIO_MUX_11 BIT(11)
+#define GPIO_MUX_10 BIT(10)
+#define GPIO_MUX_9 BIT(9)
+#define GPIO_MUX_8 BIT(8)
+#define GPIO_MUX_7 BIT(7)
+#define GPIO_MUX_6 BIT(6)
+#define GPIO_MUX_5 BIT(5)
+#define GPIO_MUX_4 BIT(4)
+#define GPIO_MUX_3 BIT(3)
+#define GPIO_MUX_2 BIT(2)
+#define GPIO_MUX_1 BIT(1)
+#define GPIO_MUX_0 BIT(0)
#define LOCALMEM_ARBITRATION 0x00000C
#define LOCALMEM_ARBITRATION_ROTATE 28:28
#define INT_MASK_VGA_VSYNC_ENABLE 1
#define CURRENT_GATE 0x000040
-#define CURRENT_GATE_MCLK 15:14
+#define CURRENT_GATE_MCLK_MASK (0x3 << 14)
#ifdef VALIDATION_CHIP
- #define CURRENT_GATE_MCLK_112MHZ 0
- #define CURRENT_GATE_MCLK_84MHZ 1
- #define CURRENT_GATE_MCLK_56MHZ 2
- #define CURRENT_GATE_MCLK_42MHZ 3
+ #define CURRENT_GATE_MCLK_112MHZ (0x0 << 14)
+ #define CURRENT_GATE_MCLK_84MHZ (0x1 << 14)
+ #define CURRENT_GATE_MCLK_56MHZ (0x2 << 14)
+ #define CURRENT_GATE_MCLK_42MHZ (0x3 << 14)
#else
- #define CURRENT_GATE_MCLK_DIV_3 0
- #define CURRENT_GATE_MCLK_DIV_4 1
- #define CURRENT_GATE_MCLK_DIV_6 2
- #define CURRENT_GATE_MCLK_DIV_8 3
+ #define CURRENT_GATE_MCLK_DIV_3 (0x0 << 14)
+ #define CURRENT_GATE_MCLK_DIV_4 (0x1 << 14)
+ #define CURRENT_GATE_MCLK_DIV_6 (0x2 << 14)
+ #define CURRENT_GATE_MCLK_DIV_8 (0x3 << 14)
#endif
-#define CURRENT_GATE_M2XCLK 13:12
+#define CURRENT_GATE_M2XCLK_MASK (0x3 << 12)
#ifdef VALIDATION_CHIP
- #define CURRENT_GATE_M2XCLK_336MHZ 0
- #define CURRENT_GATE_M2XCLK_168MHZ 1
- #define CURRENT_GATE_M2XCLK_112MHZ 2
- #define CURRENT_GATE_M2XCLK_84MHZ 3
+ #define CURRENT_GATE_M2XCLK_336MHZ (0x0 << 12)
+ #define CURRENT_GATE_M2XCLK_168MHZ (0x1 << 12)
+ #define CURRENT_GATE_M2XCLK_112MHZ (0x2 << 12)
+ #define CURRENT_GATE_M2XCLK_84MHZ (0x3 << 12)
#else
- #define CURRENT_GATE_M2XCLK_DIV_1 0
- #define CURRENT_GATE_M2XCLK_DIV_2 1
- #define CURRENT_GATE_M2XCLK_DIV_3 2
- #define CURRENT_GATE_M2XCLK_DIV_4 3
+ #define CURRENT_GATE_M2XCLK_DIV_1 (0x0 << 12)
+ #define CURRENT_GATE_M2XCLK_DIV_2 (0x1 << 12)
+ #define CURRENT_GATE_M2XCLK_DIV_3 (0x2 << 12)
+ #define CURRENT_GATE_M2XCLK_DIV_4 (0x3 << 12)
#endif
-#define CURRENT_GATE_VGA 10:10
-#define CURRENT_GATE_VGA_OFF 0
-#define CURRENT_GATE_VGA_ON 1
-#define CURRENT_GATE_PWM 9:9
-#define CURRENT_GATE_PWM_OFF 0
-#define CURRENT_GATE_PWM_ON 1
-#define CURRENT_GATE_I2C 8:8
-#define CURRENT_GATE_I2C_OFF 0
-#define CURRENT_GATE_I2C_ON 1
-#define CURRENT_GATE_SSP 7:7
-#define CURRENT_GATE_SSP_OFF 0
-#define CURRENT_GATE_SSP_ON 1
-#define CURRENT_GATE_GPIO 6:6
-#define CURRENT_GATE_GPIO_OFF 0
-#define CURRENT_GATE_GPIO_ON 1
-#define CURRENT_GATE_ZVPORT 5:5
-#define CURRENT_GATE_ZVPORT_OFF 0
-#define CURRENT_GATE_ZVPORT_ON 1
-#define CURRENT_GATE_CSC 4:4
-#define CURRENT_GATE_CSC_OFF 0
-#define CURRENT_GATE_CSC_ON 1
-#define CURRENT_GATE_DE 3:3
-#define CURRENT_GATE_DE_OFF 0
-#define CURRENT_GATE_DE_ON 1
-#define CURRENT_GATE_DISPLAY 2:2
-#define CURRENT_GATE_DISPLAY_OFF 0
-#define CURRENT_GATE_DISPLAY_ON 1
-#define CURRENT_GATE_LOCALMEM 1:1
-#define CURRENT_GATE_LOCALMEM_OFF 0
-#define CURRENT_GATE_LOCALMEM_ON 1
-#define CURRENT_GATE_DMA 0:0
-#define CURRENT_GATE_DMA_OFF 0
-#define CURRENT_GATE_DMA_ON 1
+#define CURRENT_GATE_VGA BIT(10)
+#define CURRENT_GATE_PWM BIT(9)
+#define CURRENT_GATE_I2C BIT(8)
+#define CURRENT_GATE_SSP BIT(7)
+#define CURRENT_GATE_GPIO BIT(6)
+#define CURRENT_GATE_ZVPORT BIT(5)
+#define CURRENT_GATE_CSC BIT(4)
+#define CURRENT_GATE_DE BIT(3)
+#define CURRENT_GATE_DISPLAY BIT(2)
+#define CURRENT_GATE_LOCALMEM BIT(1)
+#define CURRENT_GATE_DMA BIT(0)
#define MODE0_GATE 0x000044
-#define MODE0_GATE_MCLK 15:14
-#define MODE0_GATE_MCLK_112MHZ 0
-#define MODE0_GATE_MCLK_84MHZ 1
-#define MODE0_GATE_MCLK_56MHZ 2
-#define MODE0_GATE_MCLK_42MHZ 3
-#define MODE0_GATE_M2XCLK 13:12
-#define MODE0_GATE_M2XCLK_336MHZ 0
-#define MODE0_GATE_M2XCLK_168MHZ 1
-#define MODE0_GATE_M2XCLK_112MHZ 2
-#define MODE0_GATE_M2XCLK_84MHZ 3
-#define MODE0_GATE_VGA 10:10
-#define MODE0_GATE_VGA_OFF 0
-#define MODE0_GATE_VGA_ON 1
-#define MODE0_GATE_PWM 9:9
-#define MODE0_GATE_PWM_OFF 0
-#define MODE0_GATE_PWM_ON 1
-#define MODE0_GATE_I2C 8:8
-#define MODE0_GATE_I2C_OFF 0
-#define MODE0_GATE_I2C_ON 1
-#define MODE0_GATE_SSP 7:7
-#define MODE0_GATE_SSP_OFF 0
-#define MODE0_GATE_SSP_ON 1
-#define MODE0_GATE_GPIO 6:6
-#define MODE0_GATE_GPIO_OFF 0
-#define MODE0_GATE_GPIO_ON 1
-#define MODE0_GATE_ZVPORT 5:5
-#define MODE0_GATE_ZVPORT_OFF 0
-#define MODE0_GATE_ZVPORT_ON 1
-#define MODE0_GATE_CSC 4:4
-#define MODE0_GATE_CSC_OFF 0
-#define MODE0_GATE_CSC_ON 1
-#define MODE0_GATE_DE 3:3
-#define MODE0_GATE_DE_OFF 0
-#define MODE0_GATE_DE_ON 1
-#define MODE0_GATE_DISPLAY 2:2
-#define MODE0_GATE_DISPLAY_OFF 0
-#define MODE0_GATE_DISPLAY_ON 1
-#define MODE0_GATE_LOCALMEM 1:1
-#define MODE0_GATE_LOCALMEM_OFF 0
-#define MODE0_GATE_LOCALMEM_ON 1
-#define MODE0_GATE_DMA 0:0
-#define MODE0_GATE_DMA_OFF 0
-#define MODE0_GATE_DMA_ON 1
+#define MODE0_GATE_MCLK_MASK (0x3 << 14)
+#define MODE0_GATE_MCLK_112MHZ (0x0 << 14)
+#define MODE0_GATE_MCLK_84MHZ (0x1 << 14)
+#define MODE0_GATE_MCLK_56MHZ (0x2 << 14)
+#define MODE0_GATE_MCLK_42MHZ (0x3 << 14)
+#define MODE0_GATE_M2XCLK_MASK (0x3 << 12)
+#define MODE0_GATE_M2XCLK_336MHZ (0x0 << 12)
+#define MODE0_GATE_M2XCLK_168MHZ (0x1 << 12)
+#define MODE0_GATE_M2XCLK_112MHZ (0x2 << 12)
+#define MODE0_GATE_M2XCLK_84MHZ (0x3 << 12)
+#define MODE0_GATE_VGA BIT(10)
+#define MODE0_GATE_PWM BIT(9)
+#define MODE0_GATE_I2C BIT(8)
+#define MODE0_GATE_SSP BIT(7)
+#define MODE0_GATE_GPIO BIT(6)
+#define MODE0_GATE_ZVPORT BIT(5)
+#define MODE0_GATE_CSC BIT(4)
+#define MODE0_GATE_DE BIT(3)
+#define MODE0_GATE_DISPLAY BIT(2)
+#define MODE0_GATE_LOCALMEM BIT(1)
+#define MODE0_GATE_DMA BIT(0)
#define MODE1_GATE 0x000048
#define MODE1_GATE_MCLK 15:14
#define POWER_MODE_CTRL 0x00004C
#ifdef VALIDATION_CHIP
- #define POWER_MODE_CTRL_336CLK 4:4
- #define POWER_MODE_CTRL_336CLK_OFF 0
- #define POWER_MODE_CTRL_336CLK_ON 1
+ #define POWER_MODE_CTRL_336CLK BIT(4)
#endif
-#define POWER_MODE_CTRL_OSC_INPUT 3:3
-#define POWER_MODE_CTRL_OSC_INPUT_OFF 0
-#define POWER_MODE_CTRL_OSC_INPUT_ON 1
-#define POWER_MODE_CTRL_ACPI 2:2
-#define POWER_MODE_CTRL_ACPI_OFF 0
-#define POWER_MODE_CTRL_ACPI_ON 1
-#define POWER_MODE_CTRL_MODE 1:0
-#define POWER_MODE_CTRL_MODE_MODE0 0
-#define POWER_MODE_CTRL_MODE_MODE1 1
-#define POWER_MODE_CTRL_MODE_SLEEP 2
+#define POWER_MODE_CTRL_OSC_INPUT BIT(3)
+#define POWER_MODE_CTRL_ACPI BIT(2)
+#define POWER_MODE_CTRL_MODE_MASK (0x3 << 0)
+#define POWER_MODE_CTRL_MODE_MODE0 (0x0 << 0)
+#define POWER_MODE_CTRL_MODE_MODE1 (0x1 << 0)
+#define POWER_MODE_CTRL_MODE_SLEEP (0x2 << 0)
#define PCI_MASTER_BASE 0x000050
#define PCI_MASTER_BASE_ADDRESS 7:0
#define i2cWriteReg sm750_hw_i2c_write_reg
#define i2cReadReg sm750_hw_i2c_read_reg
#else
- #define i2cWriteReg swI2CWriteReg
- #define i2cReadReg swI2CReadReg
+ #define i2cWriteReg sm750_sw_i2c_write_reg
+ #define i2cReadReg sm750_sw_i2c_read_reg
#endif
/* SII164 Vendor and Device ID */
unsigned char sii164CheckInterrupt(void);
void sii164ClearInterrupt(void);
#endif
-/* below register definination is used for Silicon Image SiI164 DVI controller chip */
+/*
+ * below register definition is used for
+ * Silicon Image SiI164 DVI controller chip
+ */
/*
* Vendor ID registers
*/
* If not use spin_lock,system will die if user load driver
* and immediately unload driver frequently (dual)
*/
- if (sm750_dev->dual)
+ if (sm750_dev->fb_count > 1)
spin_lock(&sm750_dev->slock);
sm750_dev->accel.de_fillrect(&sm750_dev->accel,
region->dx, region->dy,
region->width, region->height,
color, rop);
- if (sm750_dev->dual)
+ if (sm750_dev->fb_count > 1)
spin_unlock(&sm750_dev->slock);
}
* If not use spin_lock, system will die if user load driver
* and immediately unload driver frequently (dual)
*/
- if (sm750_dev->dual)
+ if (sm750_dev->fb_count > 1)
spin_lock(&sm750_dev->slock);
sm750_dev->accel.de_copyarea(&sm750_dev->accel,
base, pitch, Bpp, region->dx, region->dy,
region->width, region->height,
HW_ROP2_COPY);
- if (sm750_dev->dual)
+ if (sm750_dev->fb_count > 1)
spin_unlock(&sm750_dev->slock);
}
* If not use spin_lock, system will die if user load driver
* and immediately unload driver frequently (dual)
*/
- if (sm750_dev->dual)
+ if (sm750_dev->fb_count > 1)
spin_lock(&sm750_dev->slock);
sm750_dev->accel.de_imageblit(&sm750_dev->accel,
image->dx, image->dy,
image->width, image->height,
fgcol, bgcol, HW_ROP2_COPY);
- if (sm750_dev->dual)
+ if (sm750_dev->fb_count > 1)
spin_unlock(&sm750_dev->slock);
}
var = &info->var;
fix = &info->fix;
- /* fix structur is not so FIX ... */
+ /* fix structure is not so FIX ... */
line_length = var->xres_virtual * var->bits_per_pixel / 8;
line_length = ALIGN(line_length, crtc->line_pad);
fix->line_length = line_length;
output = &par->output;
crtc = &par->crtc;
- crtc->vidmem_size = (sm750_dev->dual) ? sm750_dev->vidmem_size >> 1 :
- sm750_dev->vidmem_size;
+ crtc->vidmem_size = sm750_dev->vidmem_size;
+ if (sm750_dev->fb_count > 1)
+ crtc->vidmem_size >>= 1;
+
/* setup crtc and output member */
sm750_dev->hwCursor = g_hwcursor;
NO_PARAM:
if (sm750_dev->revid != SM750LE_REVISION_ID) {
- if (sm750_dev->dual) {
+ if (sm750_dev->fb_count > 1) {
if (swap)
sm750_dev->dataflow = sm750_dual_swap;
else
}
}
+static void sm750fb_frambuffer_release(struct sm750_dev *sm750_dev)
+{
+ struct fb_info *fb_info;
+
+ while (sm750_dev->fb_count) {
+ fb_info = sm750_dev->fbinfo[sm750_dev->fb_count - 1];
+ unregister_framebuffer(fb_info);
+ framebuffer_release(fb_info);
+ sm750_dev->fb_count--;
+ }
+}
+
+static int sm750fb_frambuffer_alloc(struct sm750_dev *sm750_dev, int fbidx)
+{
+ struct fb_info *fb_info;
+ struct lynxfb_par *par;
+ int err;
+
+ fb_info = framebuffer_alloc(sizeof(struct lynxfb_par),
+ &sm750_dev->pdev->dev);
+ if (!fb_info)
+ return -ENOMEM;
+
+ sm750_dev->fbinfo[fbidx] = fb_info;
+ par = fb_info->par;
+ par->dev = sm750_dev;
+
+ err = lynxfb_set_fbinfo(fb_info, fbidx);
+ if (err)
+ goto release_fb;
+
+ err = register_framebuffer(fb_info);
+ if (err < 0)
+ goto release_fb;
+
+ sm750_dev->fb_count++;
+
+ return 0;
+
+release_fb:
+ framebuffer_release(fb_info);
+ return err;
+}
+
static int lynxfb_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- struct fb_info *info[] = {NULL, NULL};
struct sm750_dev *sm750_dev = NULL;
+ int max_fb;
int fbidx;
+ int err;
/* enable device */
- if (pci_enable_device(pdev)) {
- pr_err("can not enable device.\n");
- goto err_enable;
- }
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+ err = -ENOMEM;
sm750_dev = kzalloc(sizeof(*sm750_dev), GFP_KERNEL);
- if (!sm750_dev) {
- pr_err("Could not allocate memory for share.\n");
- goto err_share;
- }
+ if (!sm750_dev)
+ goto disable_pci;
sm750_dev->fbinfo[0] = sm750_dev->fbinfo[1] = NULL;
sm750_dev->devid = pdev->device;
sm750_dev->revid = pdev->revision;
-
- pr_info("share->revid = %02x\n", sm750_dev->revid);
sm750_dev->pdev = pdev;
sm750_dev->mtrr_off = g_nomtrr;
sm750_dev->mtrr.vram = 0;
sm750_dev->accel_off = g_noaccel;
- sm750_dev->dual = g_dualview;
spin_lock_init(&sm750_dev->slock);
if (!sm750_dev->accel_off) {
sm750_dev->accel.de_fillrect = hw_fillrect;
sm750_dev->accel.de_copyarea = hw_copyarea;
sm750_dev->accel.de_imageblit = hw_imageblit;
- pr_info("enable 2d acceleration\n");
- } else {
- pr_info("disable 2d acceleration\n");
}
/* call chip specific setup routine */
sm750fb_setup(sm750_dev, g_settings);
/* call chip specific mmap routine */
- if (hw_sm750_map(sm750_dev, pdev)) {
- pr_err("Memory map failed\n");
- goto err_map;
- }
+ err = hw_sm750_map(sm750_dev, pdev);
+ if (err)
+ goto free_sm750_dev;
if (!sm750_dev->mtrr_off)
sm750_dev->mtrr.vram = arch_phys_wc_add(sm750_dev->vidmem_start,
memset_io(sm750_dev->pvMem, 0, sm750_dev->vidmem_size);
- pr_info("sm%3x mmio address = %p\n", sm750_dev->devid,
- sm750_dev->pvReg);
-
pci_set_drvdata(pdev, sm750_dev);
/* call chipInit routine */
hw_sm750_inithw(sm750_dev, pdev);
- /* allocate frame buffer info structor according to g_dualview */
- fbidx = 0;
-ALLOC_FB:
- info[fbidx] = framebuffer_alloc(sizeof(struct lynxfb_par), &pdev->dev);
- if (!info[fbidx]) {
- pr_err("Could not allocate framebuffer #%d.\n", fbidx);
- if (fbidx == 0)
- goto err_info0_alloc;
- else
- goto err_info1_alloc;
- } else {
- struct lynxfb_par *par;
- int errno;
-
- pr_info("framebuffer #%d alloc okay\n", fbidx);
- sm750_dev->fbinfo[fbidx] = info[fbidx];
- par = info[fbidx]->par;
- par->dev = sm750_dev;
-
- /* set fb_info structure */
- if (lynxfb_set_fbinfo(info[fbidx], fbidx)) {
- pr_err("Failed to initial fb_info #%d.\n", fbidx);
- if (fbidx == 0)
- goto err_info0_set;
- else
- goto err_info1_set;
- }
-
- /* register frame buffer */
- pr_info("Ready to register framebuffer #%d.\n", fbidx);
- errno = register_framebuffer(info[fbidx]);
- if (errno < 0) {
- pr_err("Failed to register fb_info #%d. err %d\n",
- fbidx,
- errno);
- if (fbidx == 0)
- goto err_register0;
- else
- goto err_register1;
- }
- pr_info("Accomplished register framebuffer #%d.\n", fbidx);
+ /* allocate frame buffer info structures according to g_dualview */
+ max_fb = g_dualview ? 2 : 1;
+ for (fbidx = 0; fbidx < max_fb; fbidx++) {
+ err = sm750fb_frambuffer_alloc(sm750_dev, fbidx);
+ if (err)
+ goto release_fb;
}
- /* no dual view by far */
- fbidx++;
- if (sm750_dev->dual && fbidx < 2)
- goto ALLOC_FB;
-
return 0;
-err_register1:
-err_info1_set:
- framebuffer_release(info[1]);
-err_info1_alloc:
- unregister_framebuffer(info[0]);
-err_register0:
-err_info0_set:
- framebuffer_release(info[0]);
-err_info0_alloc:
-err_map:
+release_fb:
+ sm750fb_frambuffer_release(sm750_dev);
+free_sm750_dev:
kfree(sm750_dev);
-err_share:
-err_enable:
- return -ENODEV;
+disable_pci:
+ pci_disable_device(pdev);
+ return err;
}
static void lynxfb_pci_remove(struct pci_dev *pdev)
{
- struct fb_info *info;
struct sm750_dev *sm750_dev;
- struct lynxfb_par *par;
- int cnt;
- cnt = 2;
sm750_dev = pci_get_drvdata(pdev);
- while (cnt-- > 0) {
- info = sm750_dev->fbinfo[cnt];
- if (!info)
- continue;
- par = info->par;
-
- unregister_framebuffer(info);
- /* release frame buffer */
- framebuffer_release(info);
- }
+ sm750fb_frambuffer_release(sm750_dev);
arch_phys_wc_del(sm750_dev->mtrr.vram);
iounmap(sm750_dev->pvReg);
/* base virtual address of de data port */
volatile unsigned char __iomem *dpPortBase;
- /* function fointers */
+ /* function pointers */
void (*de_init)(struct lynx_accel *);
int (*de_wait)(void);/* see if hardware ready to work */
struct fb_info *fbinfo[2];
struct lynx_accel accel;
int accel_off;
- int dual;
+ int fb_count;
int mtrr_off;
struct{
int vram;
FIELD_CLEAR(DE_STRETCH_FORMAT, ADDRESSING)&
FIELD_CLEAR(DE_STRETCH_FORMAT, SOURCE_HEIGHT);
- /* DE_STRETCH bpp format need be initilized in setMode routine */
+ /* DE_STRETCH bpp format need be initialized in setMode routine */
write_dpr(accel, DE_STRETCH_FORMAT, (read_dpr(accel, DE_STRETCH_FORMAT) & clr) | reg);
/* disable clipping and transparent */
u32 dx,
u32 dy, /* Starting coordinate of destination surface */
u32 width,
- u32 height, /* width and height of rectange in pixel value */
+ u32 height, /* width and height of rectangle in pixel value */
u32 fColor, /* Foreground color (corresponding to a 1 in the monochrome data */
u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */
u32 rop2) /* ROP value */
u32 dx,
u32 dy, /* Starting coordinate of destination surface */
u32 width,
- u32 height, /* width and height of rectange in pixel value */
+ u32 height, /* width and height of rectangle in pixel value */
u32 fColor, /* Foreground color (corresponding to a 1 in the monochrome data */
u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */
u32 rop2);
iowrite16(data, pbuffer);
/* assume pitch is 1,2,4,8,...*/
- if ((i+1) % pitch == 0)
- {
+ if ((i + 1) % pitch == 0) {
/* need a return */
pstart += offset;
pbuffer = pstart;
/* for sm718,open pci burst */
if (sm750_dev->devid == 0x718) {
POKE32(SYSTEM_CTRL,
- FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON));
+ PEEK32(SYSTEM_CTRL) | SYSTEM_CTRL_PCI_BURST);
}
if (getChipType() != SM750LE) {
+ unsigned int val;
/* does user need CRT ?*/
if (sm750_dev->nocrt) {
POKE32(MISC_CTRL,
- FIELD_SET(PEEK32(MISC_CTRL),
- MISC_CTRL,
- DAC_POWER, OFF));
+ PEEK32(MISC_CTRL) | MISC_CTRL_DAC_POWER_OFF);
/* shut off dpms */
- POKE32(SYSTEM_CTRL,
- FIELD_SET(PEEK32(SYSTEM_CTRL),
- SYSTEM_CTRL,
- DPMS, VNHN));
+ val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
+ val |= SYSTEM_CTRL_DPMS_VPHN;
+ POKE32(SYSTEM_CTRL, val);
} else {
POKE32(MISC_CTRL,
- FIELD_SET(PEEK32(MISC_CTRL),
- MISC_CTRL,
- DAC_POWER, ON));
+ PEEK32(MISC_CTRL) & ~MISC_CTRL_DAC_POWER_OFF);
/* turn on dpms */
- POKE32(SYSTEM_CTRL,
- FIELD_SET(PEEK32(SYSTEM_CTRL),
- SYSTEM_CTRL,
- DPMS, VPHP));
+ val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
+ val |= SYSTEM_CTRL_DPMS_VPHP;
+ POKE32(SYSTEM_CTRL, val);
}
switch (sm750_dev->pnltype) {
break;
}
} else {
- /* for 750LE ,no DVI chip initilization makes Monitor no signal */
+ /* for 750LE ,no DVI chip initialization makes Monitor no signal */
/* Set up GPIO for software I2C to program DVI chip in the
Xilinx SP605 board, in order to have video signal.
*/
}
if (output->paths & sm750_crt) {
+ unsigned int val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK;
- POKE32(SYSTEM_CTRL, FIELD_VALUE(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, DPMS, dpms));
+ POKE32(SYSTEM_CTRL, val | dpms);
POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
}
if (getChipType() == SM750LE) {
reg = PEEK32(DE_STATE1);
- reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, ON);
+ reg |= DE_STATE1_DE_ABORT;
POKE32(DE_STATE1, reg);
reg = PEEK32(DE_STATE1);
- reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, OFF);
+ reg &= ~DE_STATE1_DE_ABORT;
POKE32(DE_STATE1, reg);
} else {
/* engine reset */
reg = PEEK32(SYSTEM_CTRL);
- reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, ON);
+ reg |= SYSTEM_CTRL_DE_ABORT;
POKE32(SYSTEM_CTRL, reg);
reg = PEEK32(SYSTEM_CTRL);
- reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, OFF);
+ reg &= ~SYSTEM_CTRL_DE_ABORT;
POKE32(SYSTEM_CTRL, reg);
}
int hw_sm750le_deWait(void)
{
int i = 0x10000000;
+ unsigned int mask = DE_STATE2_DE_STATUS_BUSY | DE_STATE2_DE_FIFO_EMPTY |
+ DE_STATE2_DE_MEM_FIFO_EMPTY;
while (i--) {
- unsigned int dwVal = PEEK32(DE_STATE2);
+ unsigned int val = PEEK32(DE_STATE2);
- if ((FIELD_GET(dwVal, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) &&
- (FIELD_GET(dwVal, DE_STATE2, DE_FIFO) == DE_STATE2_DE_FIFO_EMPTY) &&
- (FIELD_GET(dwVal, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) {
+ if ((val & mask) ==
+ (DE_STATE2_DE_FIFO_EMPTY | DE_STATE2_DE_MEM_FIFO_EMPTY))
return 0;
- }
}
/* timeout error */
return -1;
int hw_sm750_deWait(void)
{
int i = 0x10000000;
+ unsigned int mask = SYSTEM_CTRL_DE_STATUS_BUSY |
+ SYSTEM_CTRL_DE_FIFO_EMPTY |
+ SYSTEM_CTRL_DE_MEM_FIFO_EMPTY;
while (i--) {
- unsigned int dwVal = PEEK32(SYSTEM_CTRL);
+ unsigned int val = PEEK32(SYSTEM_CTRL);
- if ((FIELD_GET(dwVal, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) &&
- (FIELD_GET(dwVal, SYSTEM_CTRL, DE_FIFO) == SYSTEM_CTRL_DE_FIFO_EMPTY) &&
- (FIELD_GET(dwVal, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) {
+ if ((val & mask) ==
+ (SYSTEM_CTRL_DE_FIFO_EMPTY | SYSTEM_CTRL_DE_MEM_FIFO_EMPTY))
return 0;
- }
}
/* timeout error */
return -1;
for (i = 0; i < MAX_NR_CONSOLES; i++) {
if (speakup_console[i] && speakup_console[i]->tty_stopped)
continue;
- if ((vc_cons[i].d != NULL) && (vc_cons[i].d->port.tty != NULL))
+ if ((vc_cons[i].d) && (vc_cons[i].d->port.tty))
start_tty(vc_cons[i].d->port.tty);
}
}
int i;
for (i = 0; i < MAX_NR_CONSOLES; i++)
- if ((vc_cons[i].d != NULL) && (vc_cons[i].d->port.tty != NULL))
+ if ((vc_cons[i].d && (vc_cons[i].d->port.tty)))
stop_tty(vc_cons[i].d->port.tty);
}
if (misc_registered != 0)
return;
/* zero it so if register fails, deregister will not ref invalid ptrs */
- if (misc_register(&synth_device))
+ if (misc_register(&synth_device)) {
pr_warn("Couldn't initialize miscdevice /dev/synth.\n");
- else {
+ } else {
pr_info("initialized device: /dev/synth, node (MAJOR %d, MINOR %d)\n",
MISC_MAJOR, SYNTH_MINOR);
misc_registered = 1;
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/types.h>
#include <linux/slab.h>
#define PRESSED 1
#define RELEASED 0
-static DEFINE_PER_CPU(bool, reporting_keystroke);
+static DEFINE_PER_CPU(int, reporting_keystroke);
static struct input_dev *virt_keyboard;
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/keyboard.h>
for (i = 0; i < nstates; i++, kp++) {
if (!*kp)
continue;
- if ((state_tbl[i]&16) != 0 && *kp == SPK_KEY)
+ if ((state_tbl[i] & 16) != 0 && *kp == SPK_KEY)
continue;
counters[*kp]++;
}
if (counters[i] == 0)
continue;
key_offsets[i] = offset;
- offset += (counters[i]+1);
+ offset += (counters[i] + 1);
if (offset >= MAXKEYS)
break;
}
ch1 = *kp++;
if (!ch1)
continue;
- if ((state_tbl[i]&16) != 0 && ch1 == SPK_KEY)
+ if ((state_tbl[i] & 16) != 0 && ch1 == SPK_KEY)
continue;
key = (state_tbl[i] << 8) + ch;
counters[ch1]--;
int i;
int num_funcs = MSG_FUNCNAMES_END - MSG_FUNCNAMES_START + 1;
- state_tbl = spk_our_keys[0]+SHIFT_TBL_SIZE+2;
+ state_tbl = spk_our_keys[0] + SHIFT_TBL_SIZE + 2;
for (i = 0; i < num_funcs; i++) {
char *cur_funcname = spk_msg_get(MSG_FUNCNAMES_START + i);
if (start == *cur_funcname)
continue;
start = *cur_funcname;
- letter_offsets[(start&31)-1] = i;
+ letter_offsets[(start & 31) - 1] = i;
}
return 0;
}
ch |= 32; /* lower case */
if (ch < 'a' || ch > 'z')
return -1;
- if (letter_offsets[ch-'a'] == -1) {
+ if (letter_offsets[ch - 'a'] == -1) {
synth_printf(spk_msg_get(MSG_NO_COMMAND), ch);
synth_printf("\n");
return 1;
}
- cur_item = letter_offsets[ch-'a'];
+ cur_item = letter_offsets[ch - 'a'];
} else if (type == KT_CUR) {
if (ch == 0
&& (MSG_FUNCNAMES_START + cur_item + 1) <=
name = NULL;
if ((type != KT_SPKUP) && (key > 0) && (key <= num_key_names)) {
synth_printf("%s\n",
- spk_msg_get(MSG_KEYNAMES_START + key-1));
+ spk_msg_get(MSG_KEYNAMES_START + key - 1));
return 1;
}
for (i = 0; funcvals[i] != 0 && !name; i++) {
}
if (!name)
return -1;
- kp = spk_our_keys[key]+1;
+ kp = spk_our_keys[key] + 1;
for (i = 0; i < nstates; i++) {
if (ch == kp[i])
break;
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* this code is specificly written as a driver for the speakup screenreview
* package and is not a general device driver.
* This driver is for the Aicom Acent PC internal synthesizer.
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* this code is specificly written as a driver for the speakup screenreview
* package and is not a general device driver.
*/
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* this code is specificly written as a driver for the speakup screenreview
* package and is not a general device driver.
*/
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* specificly written as a driver for the speakup screenreview
* s not a general device driver.
*/
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* this code is specificly written as a driver for the speakup screenreview
* package and is not a general device driver.
*/
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* specificly written as a driver for the speakup screenreview
* s not a general device driver.
*/
* These attributes will appear in /sys/accessibility/speakup/decext.
*/
static struct kobj_attribute caps_start_attribute =
- __ATTR(caps_start, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(caps_start, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute caps_stop_attribute =
- __ATTR(caps_stop, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(caps_stop, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute pitch_attribute =
- __ATTR(pitch, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(pitch, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute punct_attribute =
- __ATTR(punct, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(punct, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute rate_attribute =
- __ATTR(rate, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(rate, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute voice_attribute =
- __ATTR(voice, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(voice, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute vol_attribute =
- __ATTR(vol, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(vol, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute delay_time_attribute =
- __ATTR(delay_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(delay_time, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute direct_attribute =
- __ATTR(direct, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(direct, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute full_time_attribute =
- __ATTR(full_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(full_time, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute jiffy_delta_attribute =
- __ATTR(jiffy_delta, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(jiffy_delta, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute trigger_time_attribute =
- __ATTR(trigger_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
+ __ATTR(trigger_time, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store);
/*
* Create a group of attributes so that we can create and destroy them all
* 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 <linux/jiffies.h>
#include <linux/sched.h>
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* specificly written as a driver for the speakup screenreview
* s not a general device driver.
*/
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* specificly written as a driver for the speakup screenreview
* package it's not a general device driver.
* This driver is for the RC Systems DoubleTalk PC internal synthesizer.
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* specificly written as a driver for the speakup screenreview
* s not a general device driver.
*/
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* specificly written as a driver for the speakup screenreview
* package it's not a general device driver.
* This driver is for the Keynote Gold internal synthesizer.
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* specificly written as a driver for the speakup screenreview
* s not a general device driver.
*/
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* this code is specificly written as a driver for the speakup screenreview
* package and is not a general device driver.
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* specificly written as a driver for the speakup screenreview
* s not a general device driver.
*/
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
* specificly written as a driver for the speakup screenreview
* s not a general device driver.
*/
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _SPEAKUP_PRIVATE_H
#define _SPEAKUP_PRIVATE_H
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _SPEAKUP_KEYINFO_H
Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
int spk_set_num_var(int input, struct st_var_header *var, int how)
{
int val;
- short ret = 0;
int *p_val = var->p_val;
int l;
char buf[32];
if (!var_data)
return -ENODATA;
- if (how == E_NEW_DEFAULT) {
+ val = var_data->u.n.value;
+ switch (how) {
+ case E_NEW_DEFAULT:
if (input < var_data->u.n.low || input > var_data->u.n.high)
return -ERANGE;
var_data->u.n.default_val = input;
return 0;
- }
- if (how == E_DEFAULT) {
+ case E_DEFAULT:
val = var_data->u.n.default_val;
- ret = -ERESTART;
- } else {
- if (how == E_SET)
- val = input;
- else
- val = var_data->u.n.value;
- if (how == E_INC)
- val += input;
- else if (how == E_DEC)
- val -= input;
- if (val < var_data->u.n.low || val > var_data->u.n.high)
- return -ERANGE;
+ break;
+ case E_SET:
+ val = input;
+ break;
+ case E_INC:
+ val += input;
+ break;
+ case E_DEC:
+ val -= input;
+ break;
}
+
+ if (val < var_data->u.n.low || val > var_data->u.n.high)
+ return -ERANGE;
+
var_data->u.n.value = val;
if (var->var_type == VAR_TIME && p_val != NULL) {
*p_val = msecs_to_jiffies(val);
- return ret;
+ return 0;
}
if (p_val != NULL)
*p_val = val;
if (var->var_id == PUNC_LEVEL) {
spk_punc_mask = spk_punc_masks[val];
- return ret;
+ return 0;
}
if (var_data->u.n.multiplier != 0)
val *= var_data->u.n.multiplier;
val += var_data->u.n.offset;
if (var->var_id < FIRST_SYNTH_VAR || !synth)
- return ret;
- if (synth->synth_adjust) {
- int status = synth->synth_adjust(var);
+ return 0;
+ if (synth->synth_adjust)
+ return synth->synth_adjust(var);
- return (status != 0) ? status : ret;
- }
if (!var_data->u.n.synth_fmt)
- return ret;
+ return 0;
if (var->var_id == PITCH)
cp = spk_pitch_buff;
else
l = sprintf(cp,
var_data->u.n.synth_fmt, var_data->u.n.out_str[val]);
synth_printf("%s", cp);
- return ret;
+ return 0;
}
int spk_set_string_var(const char *page, struct st_var_header *var, int len)
+++ /dev/null
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-static int __init staging_init(void)
-{
- return 0;
-}
-
-static void __exit staging_exit(void)
-{
-}
-
-module_init(staging_init);
-module_exit(staging_exit);
-
-MODULE_AUTHOR("Greg Kroah-Hartman");
-MODULE_DESCRIPTION("Staging Core");
-MODULE_LICENSE("GPL");
* Descriptor structure.
* Describes the number of i2c devices on the bus that speak RMI.
*/
-static struct synaptics_rmi4_platform_data synaptics_rmi4_platformdata = {
+static const struct synaptics_rmi4_platform_data synaptics_rmi4_platformdata = {
.irq_type = (IRQF_TRIGGER_FALLING | IRQF_SHARED),
.x_flip = false,
.y_flip = true,
return 0;
}
-#ifdef CONFIG_PM
/**
* synaptics_rmi4_suspend() - suspend the touch screen controller
* @dev: pointer to device structure
* This function is used to suspend the
* touch panel controller and returns integer
*/
-static int synaptics_rmi4_suspend(struct device *dev)
+static int __maybe_unused synaptics_rmi4_suspend(struct device *dev)
{
/* Touch sleep mode */
int retval;
* This function is used to resume the touch panel
* controller and returns integer.
*/
-static int synaptics_rmi4_resume(struct device *dev)
+static int __maybe_unused synaptics_rmi4_resume(struct device *dev)
{
int retval;
unsigned char intr_status;
return 0;
}
-#endif
-
static SIMPLE_DEV_PM_OPS(synaptics_rmi4_dev_pm_ops, synaptics_rmi4_suspend,
synaptics_rmi4_resume);
#define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1
#define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100
-#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128)
+#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128)
#define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000
u8 tool_action;
visorchannel_read(controlvm_channel,
- offsetof(struct spar_controlvm_channel_protocol,
- tool_action), &tool_action, sizeof(u8));
+ offsetof(struct spar_controlvm_channel_protocol,
+ tool_action), &tool_action, sizeof(u8));
return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action);
}
}
most_recent_message_jiffies = jiffies;
poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST;
- rc = queue_delayed_work(periodic_controlvm_workqueue,
- &periodic_controlvm_work, poll_jiffies);
- if (rc < 0) {
- POSTCODE_LINUX_2(QUEUE_DELAYED_WORK_PC,
- DIAG_SEVERITY_ERR);
- goto cleanup;
- }
+ queue_delayed_work(periodic_controlvm_workqueue,
+ &periodic_controlvm_work, poll_jiffies);
visorchipset_platform_device.dev.devt = major_dev;
if (platform_device_register(&visorchipset_platform_device) < 0) {
{
/* used to stop the thread */
init_completion(&thrinfo->has_stopped);
- thrinfo->task = kthread_run(threadfn, thrcontext, name);
+ thrinfo->task = kthread_run(threadfn, thrcontext, "%s", name);
if (IS_ERR(thrinfo->task)) {
thrinfo->id = 0;
return PTR_ERR(thrinfo->task);
* = 163840 bytes
*/
#define MAX_BUF 163840
+#define NAPI_WEIGHT 64
static int visornic_probe(struct visor_device *dev);
static void visornic_remove(struct visor_device *dev);
{
if (!devdata)
return NULL;
- memset(devdata, '\0', sizeof(struct visornic_devdata));
devdata->dev = dev;
devdata->incarnation_id = get_jiffies_64();
return devdata;
*/
static void
service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata,
- int *rx_work_done)
+ int *rx_work_done, int budget)
{
unsigned long flags;
struct net_device *netdev;
- /* TODO: CLIENT ACQUIRE -- Don't really need this at the
- * moment */
- for (;;) {
+ while (*rx_work_done < budget) {
if (!visorchannel_signalremove(devdata->dev->visorchannel,
IOCHAN_FROM_IOPART,
cmdrsp))
int rx_count = 0;
send_rcv_posts_if_needed(devdata);
- service_resp_queue(devdata->cmdrsp, devdata, &rx_count);
+ service_resp_queue(devdata->cmdrsp, devdata, &rx_count, budget);
/*
* If there aren't any more packets to receive
goto cleanup_napi_add;
}
+ /* Let's start our threads to get responses */
+ netif_napi_add(netdev, &devdata->napi, visornic_poll, NAPI_WEIGHT);
+
+ /*
+ * Note: Interupts have to be enable before the while
+ * loop below because the napi routine is responsible for
+ * setting enab_dis_acked
+ */
+ visorbus_enable_channel_interrupts(dev);
+
err = register_netdev(netdev);
if (err) {
dev_err(&dev->device,
}
/* set MAC TD pointer */
- MACvSetCurrTXDescAddr(TYPE_TXDMA0, priv->PortOffset,
- (priv->td0_pool_dma));
+ MACvSetCurrTXDescAddr(TYPE_TXDMA0, priv, priv->td0_pool_dma);
- MACvSetCurrTXDescAddr(TYPE_AC0DMA, priv->PortOffset,
- (priv->td1_pool_dma));
+ MACvSetCurrTXDescAddr(TYPE_AC0DMA, priv, priv->td1_pool_dma);
/* set MAC Beacon TX pointer */
MACvSetCurrBCNTxDescAddr(priv->PortOffset,
MACvRx0PerPktMode(priv->PortOffset);
MACvRx1PerPktMode(priv->PortOffset);
/* set MAC RD pointer */
- MACvSetCurrRx0DescAddr(priv->PortOffset,
- priv->rd0_pool_dma);
+ MACvSetCurrRx0DescAddr(priv, priv->rd0_pool_dma);
- MACvSetCurrRx1DescAddr(priv->PortOffset,
- priv->rd1_pool_dma);
+ MACvSetCurrRx1DescAddr(priv, priv->rd1_pool_dma);
}
/*
*/
void CARDvSetLoopbackMode(struct vnt_private *priv, unsigned short wLoopbackMode)
{
- void __iomem *dwIoBase = priv->PortOffset;
-
switch (wLoopbackMode) {
case CARD_LB_NONE:
case CARD_LB_MAC:
break;
}
/* set MAC loopback */
- MACvSetLoopbackMode(dwIoBase, LOBYTE(wLoopbackMode));
+ MACvSetLoopbackMode(priv, LOBYTE(wLoopbackMode));
/* set Baseband loopback */
}
{
/* reset MAC */
- if (!MACbSafeSoftwareReset(priv->PortOffset))
+ if (!MACbSafeSoftwareReset(priv))
return false;
return true;
* Return Value: true if succeeded; false if failed.
*
*/
-bool set_channel(void *pDeviceHandler, struct ieee80211_channel *ch)
+bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch)
{
- struct vnt_private *pDevice = pDeviceHandler;
- bool bResult = true;
+ bool ret = true;
- if (pDevice->byCurrentCh == ch->hw_value)
- return bResult;
+ if (priv->byCurrentCh == ch->hw_value)
+ return ret;
/* Set VGA to max sensitivity */
- if (pDevice->bUpdateBBVGA &&
- pDevice->byBBVGACurrent != pDevice->abyBBVGA[0]) {
- pDevice->byBBVGACurrent = pDevice->abyBBVGA[0];
+ if (priv->bUpdateBBVGA &&
+ priv->byBBVGACurrent != priv->abyBBVGA[0]) {
+ priv->byBBVGACurrent = priv->abyBBVGA[0];
- BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent);
+ BBvSetVGAGainOffset(priv, priv->byBBVGACurrent);
}
/* clear NAV */
- MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MACCR, MACCR_CLRNAV);
+ MACvRegBitsOn(priv->PortOffset, MAC_REG_MACCR, MACCR_CLRNAV);
/* TX_PE will reserve 3 us for MAX2829 A mode only,
it is for better TX throughput */
- if (pDevice->byRFType == RF_AIROHA7230)
- RFbAL7230SelectChannelPostProcess(pDevice, pDevice->byCurrentCh,
+ if (priv->byRFType == RF_AIROHA7230)
+ RFbAL7230SelectChannelPostProcess(priv, priv->byCurrentCh,
ch->hw_value);
- pDevice->byCurrentCh = ch->hw_value;
- bResult &= RFbSelectChannel(pDevice, pDevice->byRFType,
- ch->hw_value);
+ priv->byCurrentCh = ch->hw_value;
+ ret &= RFbSelectChannel(priv, priv->byRFType,
+ ch->hw_value);
/* Init Synthesizer Table */
- if (pDevice->bEnablePSMode)
- RFvWriteWakeProgSyn(pDevice, pDevice->byRFType, ch->hw_value);
+ if (priv->bEnablePSMode)
+ RFvWriteWakeProgSyn(priv, priv->byRFType, ch->hw_value);
- BBvSoftwareReset(pDevice);
+ BBvSoftwareReset(priv);
- if (pDevice->byLocalID > REV_ID_VT3253_B1) {
+ if (priv->byLocalID > REV_ID_VT3253_B1) {
unsigned long flags;
- spin_lock_irqsave(&pDevice->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
/* set HW default power register */
- MACvSelectPage1(pDevice->PortOffset);
- RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh);
- VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWRCCK,
- pDevice->byCurPwr);
- RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh);
- VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWROFDM,
- pDevice->byCurPwr);
- MACvSelectPage0(pDevice->PortOffset);
-
- spin_unlock_irqrestore(&pDevice->lock, flags);
+ MACvSelectPage1(priv->PortOffset);
+ RFbSetPower(priv, RATE_1M, priv->byCurrentCh);
+ VNSvOutPortB(priv->PortOffset + MAC_REG_PWRCCK,
+ priv->byCurPwr);
+ RFbSetPower(priv, RATE_6M, priv->byCurrentCh);
+ VNSvOutPortB(priv->PortOffset + MAC_REG_PWROFDM,
+ priv->byCurPwr);
+ MACvSelectPage0(priv->PortOffset);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
}
- if (pDevice->byBBType == BB_TYPE_11B)
- RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh);
+ if (priv->byBBType == BB_TYPE_11B)
+ RFbSetPower(priv, RATE_1M, priv->byCurrentCh);
else
- RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh);
+ RFbSetPower(priv, RATE_6M, priv->byCurrentCh);
- return bResult;
+ return ret;
}
void vnt_init_bands(struct vnt_private *);
-bool set_channel(void *pDeviceHandler, struct ieee80211_channel *);
+bool set_channel(struct vnt_private *, struct ieee80211_channel *);
#endif /* _CHANNEL_H_ */
unsigned char byCCKPwrdBm = 0;
unsigned char byOFDMPwrdBm = 0;
- MACbShutdown(priv->PortOffset);
+ MACbShutdown(priv);
BBvSoftwareReset(priv);
/* Do MACbSoftwareReset in MACvInitialize */
- MACbSoftwareReset(priv->PortOffset);
+ MACbSoftwareReset(priv);
priv->bAES = false;
priv->byTopCCKBasicRate = RATE_1M;
/* init MAC */
- MACvInitialize(priv->PortOffset);
+ MACvInitialize(priv);
/* Get Local ID */
VNSvInPortB(priv->PortOffset + MAC_REG_LOCALID, &priv->byLocalID);
MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT));
/* set performance parameter by registry */
- MACvSetShortRetryLimit(priv->PortOffset, priv->byShortRetryLimit);
- MACvSetLongRetryLimit(priv->PortOffset, priv->byLongRetryLimit);
+ MACvSetShortRetryLimit(priv, priv->byShortRetryLimit);
+ MACvSetLongRetryLimit(priv, priv->byLongRetryLimit);
/* reset TSF counter */
VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
if (status & ISR_FETALERR) {
dev_err(&priv->pcid->dev, "Hardware fatal error\n");
- MACbShutdown(priv->PortOffset);
+ MACbShutdown(priv);
return;
}
}
if ((priv->op_mode == NL80211_IFTYPE_AP ||
priv->op_mode == NL80211_IFTYPE_ADHOC) &&
priv->vif->bss_conf.enable_beacon) {
- MACvOneShotTimer1MicroSec(priv->PortOffset,
+ MACvOneShotTimer1MicroSec(priv,
(priv->vif->bss_conf.beacon_int - MAKE_BEACON_RESERVED) << 10);
}
cancel_work_sync(&priv->interrupt_work);
- MACbShutdown(priv->PortOffset);
- MACbSoftwareReset(priv->PortOffset);
+ MACbShutdown(priv);
+ MACbSoftwareReset(priv);
CARDbRadioPowerOff(priv);
device_free_td0_ring(priv);
INIT_WORK(&priv->interrupt_work, vnt_interrupt_work);
/* do reset */
- if (!MACbSoftwareReset(priv->PortOffset)) {
+ if (!MACbSoftwareReset(priv)) {
dev_err(&pcid->dev, ": Failed to access MAC hardware..\n");
device_free_info(priv);
return -ENODEV;
}
/* initial to reload eeprom */
- MACvInitialize(priv->PortOffset);
+ MACvInitialize(priv);
MACvReadEtherAddress(priv->PortOffset, priv->abyCurrentNetAddr);
/* Get RFType */
pci_save_state(pcid);
- MACbShutdown(priv->PortOffset);
+ MACbShutdown(priv);
pci_disable_device(pcid);
pci_set_power_state(pcid, pci_choose_state(pcid, state));
u32 i;
for (i = 0; i < MAX_KEY_TABLE; i++)
- MACvDisableKeyEntry(priv->PortOffset, i);
+ MACvDisableKeyEntry(priv, i);
return 0;
}
key->key[15] |= 0x80;
}
- MACvSetKeyEntry(priv->PortOffset, key_mode, entry, key_inx,
+ MACvSetKeyEntry(priv, key_mode, entry, key_inx,
bssid, (u32 *)key->key, priv->byLocalID);
return 0;
switch (key->cipher) {
case 0:
for (u = 0 ; u < MAX_KEY_TABLE; u++)
- MACvDisableKeyEntry(priv->PortOffset, u);
+ MACvDisableKeyEntry(priv, u);
return ret;
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
for (u = 0; u < MAX_KEY_TABLE; u++)
- MACvDisableKeyEntry(priv->PortOffset, u);
+ MACvDisableKeyEntry(priv, u);
vnt_set_keymode(hw, mac_addr,
key, VNT_KEY_DEFAULTKEY, KEY_CTL_WEP, true);
* Return Value: true if all test bits On; otherwise false
*
*/
-bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs,
+bool MACbIsRegBitsOn(struct vnt_private *priv, unsigned char byRegOfs,
unsigned char byTestBits)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned char byData;
VNSvInPortB(dwIoBase + byRegOfs, &byData);
* Return Value: true if all test bits Off; otherwise false
*
*/
-bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs,
+bool MACbIsRegBitsOff(struct vnt_private *priv, unsigned char byRegOfs,
unsigned char byTestBits)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned char byData;
VNSvInPortB(dwIoBase + byRegOfs, &byData);
* Return Value: true if interrupt is disable; otherwise false
*
*/
-bool MACbIsIntDisable(void __iomem *dwIoBase)
+bool MACbIsIntDisable(struct vnt_private *priv)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned long dwData;
VNSvInPortD(dwIoBase + MAC_REG_IMR, &dwData);
* Return Value: none
*
*/
-void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit)
+void MACvSetShortRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit)
{
+ void __iomem *dwIoBase = priv->PortOffset;
/* set SRT */
VNSvOutPortB(dwIoBase + MAC_REG_SRT, byRetryLimit);
}
* Return Value: none
*
*/
-void MACvSetLongRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit)
+void MACvSetLongRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit)
{
+ void __iomem *dwIoBase = priv->PortOffset;
/* set LRT */
VNSvOutPortB(dwIoBase + MAC_REG_LRT, byRetryLimit);
}
* Return Value: none
*
*/
-void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode)
+void MACvSetLoopbackMode(struct vnt_private *priv, unsigned char byLoopbackMode)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned char byOrgValue;
byLoopbackMode <<= 6;
* Return Value: none
*
*/
-void MACvSaveContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf)
+void MACvSaveContext(struct vnt_private *priv, unsigned char *pbyCxtBuf)
{
+ void __iomem *dwIoBase = priv->PortOffset;
int ii;
/* read page0 register */
* Return Value: none
*
*/
-void MACvRestoreContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf)
+void MACvRestoreContext(struct vnt_private *priv, unsigned char *pbyCxtBuf)
{
+ void __iomem *dwIoBase = priv->PortOffset;
int ii;
MACvSelectPage1(dwIoBase);
* Return Value: true if Reset Success; otherwise false
*
*/
-bool MACbSoftwareReset(void __iomem *dwIoBase)
+bool MACbSoftwareReset(struct vnt_private *priv)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned char byData;
unsigned short ww;
* Return Value: true if success; otherwise false
*
*/
-bool MACbSafeSoftwareReset(void __iomem *dwIoBase)
+bool MACbSafeSoftwareReset(struct vnt_private *priv)
{
unsigned char abyTmpRegData[MAC_MAX_CONTEXT_SIZE_PAGE0+MAC_MAX_CONTEXT_SIZE_PAGE1];
bool bRetVal;
* reset, then restore register's value
*/
/* save MAC context */
- MACvSaveContext(dwIoBase, abyTmpRegData);
+ MACvSaveContext(priv, abyTmpRegData);
/* do reset */
- bRetVal = MACbSoftwareReset(dwIoBase);
+ bRetVal = MACbSoftwareReset(priv);
/* restore MAC context, except CR0 */
- MACvRestoreContext(dwIoBase, abyTmpRegData);
+ MACvRestoreContext(priv, abyTmpRegData);
return bRetVal;
}
* Return Value: true if success; otherwise false
*
*/
-bool MACbSafeRxOff(void __iomem *dwIoBase)
+bool MACbSafeRxOff(struct vnt_private *priv)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned short ww;
unsigned long dwData;
unsigned char byData;
* Return Value: true if success; otherwise false
*
*/
-bool MACbSafeTxOff(void __iomem *dwIoBase)
+bool MACbSafeTxOff(struct vnt_private *priv)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned short ww;
unsigned long dwData;
unsigned char byData;
* Return Value: true if success; otherwise false
*
*/
-bool MACbSafeStop(void __iomem *dwIoBase)
+bool MACbSafeStop(struct vnt_private *priv)
{
+ void __iomem *dwIoBase = priv->PortOffset;
MACvRegBitsOff(dwIoBase, MAC_REG_TCR, TCR_AUTOBCNTX);
- if (!MACbSafeRxOff(dwIoBase)) {
+ if (!MACbSafeRxOff(priv)) {
pr_debug(" MACbSafeRxOff == false)\n");
- MACbSafeSoftwareReset(dwIoBase);
+ MACbSafeSoftwareReset(priv);
return false;
}
- if (!MACbSafeTxOff(dwIoBase)) {
+ if (!MACbSafeTxOff(priv)) {
pr_debug(" MACbSafeTxOff == false)\n");
- MACbSafeSoftwareReset(dwIoBase);
+ MACbSafeSoftwareReset(priv);
return false;
}
* Return Value: true if success; otherwise false
*
*/
-bool MACbShutdown(void __iomem *dwIoBase)
+bool MACbShutdown(struct vnt_private *priv)
{
+ void __iomem *dwIoBase = priv->PortOffset;
/* disable MAC IMR */
MACvIntDisable(dwIoBase);
- MACvSetLoopbackMode(dwIoBase, MAC_LB_INTERNAL);
+ MACvSetLoopbackMode(priv, MAC_LB_INTERNAL);
/* stop the adapter */
- if (!MACbSafeStop(dwIoBase)) {
- MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE);
+ if (!MACbSafeStop(priv)) {
+ MACvSetLoopbackMode(priv, MAC_LB_NONE);
return false;
}
- MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE);
+ MACvSetLoopbackMode(priv, MAC_LB_NONE);
return true;
}
* Return Value: none
*
*/
-void MACvInitialize(void __iomem *dwIoBase)
+void MACvInitialize(struct vnt_private *priv)
{
+ void __iomem *dwIoBase = priv->PortOffset;
/* clear sticky bits */
MACvClearStckDS(dwIoBase);
/* disable force PME-enable */
/* only 3253 A */
/* do reset */
- MACbSoftwareReset(dwIoBase);
+ MACbSoftwareReset(priv);
/* reset TSF counter */
VNSvOutPortB(dwIoBase + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
* Return Value: none
*
*/
-void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr)
+void MACvSetCurrRx0DescAddr(struct vnt_private *priv, unsigned long dwCurrDescAddr)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned short ww;
unsigned char byData;
unsigned char byOrgDMACtl;
* Return Value: none
*
*/
-void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr)
+void MACvSetCurrRx1DescAddr(struct vnt_private *priv, unsigned long dwCurrDescAddr)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned short ww;
unsigned char byData;
unsigned char byOrgDMACtl;
* Return Value: none
*
*/
-void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase,
+void MACvSetCurrTx0DescAddrEx(struct vnt_private *priv,
unsigned long dwCurrDescAddr)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned short ww;
unsigned char byData;
unsigned char byOrgDMACtl;
*
*/
/* TxDMA1 = AC0DMA */
-void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase,
+void MACvSetCurrAC0DescAddrEx(struct vnt_private *priv,
unsigned long dwCurrDescAddr)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned short ww;
unsigned char byData;
unsigned char byOrgDMACtl;
VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_RUN);
}
-void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase,
+void MACvSetCurrTXDescAddr(int iTxType, struct vnt_private *priv,
unsigned long dwCurrDescAddr)
{
if (iTxType == TYPE_AC0DMA)
- MACvSetCurrAC0DescAddrEx(dwIoBase, dwCurrDescAddr);
+ MACvSetCurrAC0DescAddrEx(priv, dwCurrDescAddr);
else if (iTxType == TYPE_TXDMA0)
- MACvSetCurrTx0DescAddrEx(dwIoBase, dwCurrDescAddr);
+ MACvSetCurrTx0DescAddrEx(priv, dwCurrDescAddr);
}
/*
* Return Value: none
*
*/
-void MACvTimer0MicroSDelay(void __iomem *dwIoBase, unsigned int uDelay)
+void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned char byValue;
unsigned int uu, ii;
* Return Value: none
*
*/
-void MACvOneShotTimer1MicroSec(void __iomem *dwIoBase, unsigned int uDelayTime)
+void MACvOneShotTimer1MicroSec(struct vnt_private *priv, unsigned int uDelayTime)
{
+ void __iomem *dwIoBase = priv->PortOffset;
+
VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, 0);
VNSvOutPortD(dwIoBase + MAC_REG_TMDATA1, uDelayTime);
VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, (TMCTL_TMD | TMCTL_TE));
}
-void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset,
+void MACvSetMISCFifo(struct vnt_private *priv, unsigned short wOffset,
unsigned long dwData)
{
+ void __iomem *dwIoBase = priv->PortOffset;
+
if (wOffset > 273)
return;
VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset);
VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE);
}
-bool MACbPSWakeup(void __iomem *dwIoBase)
+bool MACbPSWakeup(struct vnt_private *priv)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned char byOrgValue;
unsigned int ww;
/* Read PSCTL */
- if (MACbIsRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PS))
+ if (MACbIsRegBitsOff(priv, MAC_REG_PSCTL, PSCTL_PS))
return true;
/* Disable PS */
*
*/
-void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl,
+void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl,
unsigned int uEntryIdx, unsigned int uKeyIdx,
unsigned char *pbyAddr, u32 *pdwKey,
unsigned char byLocalID)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned short wOffset;
u32 dwData;
int ii;
* Return Value: none
*
*/
-void MACvDisableKeyEntry(void __iomem *dwIoBase, unsigned int uEntryIdx)
+void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx)
{
+ void __iomem *dwIoBase = priv->PortOffset;
unsigned short wOffset;
wOffset = MISCFIFO_KEYETRY0;
#define MACvSetRFLE_LatchBase(dwIoBase) \
MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT)
-bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs,
+bool MACbIsRegBitsOn(struct vnt_private *, unsigned char byRegOfs,
unsigned char byTestBits);
-bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs,
+bool MACbIsRegBitsOff(struct vnt_private *, unsigned char byRegOfs,
unsigned char byTestBits);
-bool MACbIsIntDisable(void __iomem *dwIoBase);
+bool MACbIsIntDisable(struct vnt_private *);
-void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit);
+void MACvSetShortRetryLimit(struct vnt_private *, unsigned char byRetryLimit);
-void MACvSetLongRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit);
-void MACvGetLongRetryLimit(void __iomem *dwIoBase,
+void MACvSetLongRetryLimit(struct vnt_private *, unsigned char byRetryLimit);
+void MACvGetLongRetryLimit(struct vnt_private *,
unsigned char *pbyRetryLimit);
-void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode);
+void MACvSetLoopbackMode(struct vnt_private *, unsigned char byLoopbackMode);
-void MACvSaveContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf);
-void MACvRestoreContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf);
+void MACvSaveContext(struct vnt_private *, unsigned char *pbyCxtBuf);
+void MACvRestoreContext(struct vnt_private *, unsigned char *pbyCxtBuf);
-bool MACbSoftwareReset(void __iomem *dwIoBase);
-bool MACbSafeSoftwareReset(void __iomem *dwIoBase);
-bool MACbSafeRxOff(void __iomem *dwIoBase);
-bool MACbSafeTxOff(void __iomem *dwIoBase);
-bool MACbSafeStop(void __iomem *dwIoBase);
-bool MACbShutdown(void __iomem *dwIoBase);
-void MACvInitialize(void __iomem *dwIoBase);
-void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase,
+bool MACbSoftwareReset(struct vnt_private *);
+bool MACbSafeSoftwareReset(struct vnt_private *);
+bool MACbSafeRxOff(struct vnt_private *);
+bool MACbSafeTxOff(struct vnt_private *);
+bool MACbSafeStop(struct vnt_private *);
+bool MACbShutdown(struct vnt_private *);
+void MACvInitialize(struct vnt_private *);
+void MACvSetCurrRx0DescAddr(struct vnt_private *,
unsigned long dwCurrDescAddr);
-void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase,
+void MACvSetCurrRx1DescAddr(struct vnt_private *,
unsigned long dwCurrDescAddr);
-void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase,
+void MACvSetCurrTXDescAddr(int iTxType, struct vnt_private *,
unsigned long dwCurrDescAddr);
-void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase,
+void MACvSetCurrTx0DescAddrEx(struct vnt_private *,
unsigned long dwCurrDescAddr);
-void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase,
+void MACvSetCurrAC0DescAddrEx(struct vnt_private *,
unsigned long dwCurrDescAddr);
-void MACvSetCurrSyncDescAddrEx(void __iomem *dwIoBase,
+void MACvSetCurrSyncDescAddrEx(struct vnt_private *,
unsigned long dwCurrDescAddr);
-void MACvSetCurrATIMDescAddrEx(void __iomem *dwIoBase,
+void MACvSetCurrATIMDescAddrEx(struct vnt_private *,
unsigned long dwCurrDescAddr);
-void MACvTimer0MicroSDelay(void __iomem *dwIoBase, unsigned int uDelay);
-void MACvOneShotTimer1MicroSec(void __iomem *dwIoBase, unsigned int uDelayTime);
+void MACvTimer0MicroSDelay(struct vnt_private *, unsigned int uDelay);
+void MACvOneShotTimer1MicroSec(struct vnt_private *, unsigned int uDelayTime);
-void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset,
+void MACvSetMISCFifo(struct vnt_private *, unsigned short wOffset,
unsigned long dwData);
-bool MACbPSWakeup(void __iomem *dwIoBase);
+bool MACbPSWakeup(struct vnt_private *);
-void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl,
+void MACvSetKeyEntry(struct vnt_private *, unsigned short wKeyCtl,
unsigned int uEntryIdx, unsigned int uKeyIdx,
unsigned char *pbyAddr, u32 *pdwKey,
unsigned char byLocalID);
-void MACvDisableKeyEntry(void __iomem *dwIoBase, unsigned int uEntryIdx);
+void MACvDisableKeyEntry(struct vnt_private *, unsigned int uEntryIdx);
#endif /* __MAC_H__ */
void
PSvEnablePowerSaving(
- void *hDeviceContext,
+ struct vnt_private *priv,
unsigned short wListenInterval
)
{
- struct vnt_private *pDevice = hDeviceContext;
- u16 wAID = pDevice->current_aid | BIT(14) | BIT(15);
+ u16 wAID = priv->current_aid | BIT(14) | BIT(15);
/* set period of power up before TBTT */
- VNSvOutPortW(pDevice->PortOffset + MAC_REG_PWBT, C_PWBT);
- if (pDevice->op_mode != NL80211_IFTYPE_ADHOC) {
+ VNSvOutPortW(priv->PortOffset + MAC_REG_PWBT, C_PWBT);
+ if (priv->op_mode != NL80211_IFTYPE_ADHOC) {
/* set AID */
- VNSvOutPortW(pDevice->PortOffset + MAC_REG_AIDATIM, wAID);
+ VNSvOutPortW(priv->PortOffset + MAC_REG_AIDATIM, wAID);
} else {
/* set ATIM Window */
#if 0 /* TODO atim window */
- MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow);
+ MACvWriteATIMW(priv->PortOffset, pMgmt->wCurrATIMWindow);
#endif
}
/* Set AutoSleep */
- MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
+ MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
/* Set HWUTSF */
- MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
+ MACvRegBitsOn(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
if (wListenInterval >= 2) {
/* clear always listen beacon */
- MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
+ MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
/* first time set listen next beacon */
- MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN);
+ MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN);
} else {
/* always listen beacon */
- MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
+ MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
}
/* enable power saving hw function */
- MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN);
- pDevice->bEnablePSMode = true;
+ MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN);
+ priv->bEnablePSMode = true;
- pDevice->bPWBitOn = true;
+ priv->bPWBitOn = true;
pr_debug("PS:Power Saving Mode Enable...\n");
}
void
PSvDisablePowerSaving(
- void *hDeviceContext
+ struct vnt_private *priv
)
{
- struct vnt_private *pDevice = hDeviceContext;
-
/* disable power saving hw function */
- MACbPSWakeup(pDevice->PortOffset);
+ MACbPSWakeup(priv);
/* clear AutoSleep */
- MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
+ MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
/* clear HWUTSF */
- MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
+ MACvRegBitsOff(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
/* set always listen beacon */
- MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
+ MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN);
- pDevice->bEnablePSMode = false;
+ priv->bEnablePSMode = false;
- pDevice->bPWBitOn = false;
+ priv->bPWBitOn = false;
}
bool
PSbIsNextTBTTWakeUp(
- void *hDeviceContext
+ struct vnt_private *priv
)
{
- struct vnt_private *pDevice = hDeviceContext;
- struct ieee80211_hw *hw = pDevice->hw;
+ struct ieee80211_hw *hw = priv->hw;
struct ieee80211_conf *conf = &hw->conf;
- bool bWakeUp = false;
+ bool wake_up = false;
if (conf->listen_interval > 1) {
- if (!pDevice->wake_up_count)
- pDevice->wake_up_count = conf->listen_interval;
+ if (!priv->wake_up_count)
+ priv->wake_up_count = conf->listen_interval;
- --pDevice->wake_up_count;
+ --priv->wake_up_count;
- if (pDevice->wake_up_count == 1) {
+ if (priv->wake_up_count == 1) {
/* Turn on wake up to listen next beacon */
- MACvRegBitsOn(pDevice->PortOffset,
+ MACvRegBitsOn(priv->PortOffset,
MAC_REG_PSCTL, PSCTL_LNBCN);
- bWakeUp = true;
+ wake_up = true;
}
}
- return bWakeUp;
+ return wake_up;
}
#ifndef __POWER_H__
#define __POWER_H__
+#include "device.h"
+
#define C_PWBT 1000 /* micro sec. power up before TBTT */
#define PS_FAST_INTERVAL 1 /* Fast power saving listen interval */
#define PS_MAX_INTERVAL 4 /* MAX power saving listen interval */
void
PSvDisablePowerSaving(
- void *hDeviceContext
+ struct vnt_private *
);
void
PSvEnablePowerSaving(
- void *hDeviceContext,
+ struct vnt_private *,
unsigned short wListenInterval
);
bool
PSbIsNextTBTTWakeUp(
- void *hDeviceContext
+ struct vnt_private *
);
#endif /* __POWER_H__ */
{
void __iomem *dwIoBase = priv->PortOffset;
int ii;
- bool bResult;
+ bool ret;
- bResult = true;
+ ret = true;
/* 3-wire control for normal mode */
VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0);
BBvPowerSaveModeOFF(priv); /* RobertYu:20050106, have DC value for Calibration */
for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++)
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[ii]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[ii]);
/* PLL On */
MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
/* Calibration */
- MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */
+ MACvTimer0MicroSDelay(priv, 150);/* 150us */
/* TXDCOC:active, RCK:disable */
- bResult &= IFRFbWriteEmbedded(priv, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW));
- MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
+ ret &= IFRFbWriteEmbedded(priv, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW));
+ MACvTimer0MicroSDelay(priv, 30);/* 30us */
/* TXDCOC:disable, RCK:active */
- bResult &= IFRFbWriteEmbedded(priv, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW));
- MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
+ ret &= IFRFbWriteEmbedded(priv, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW));
+ MACvTimer0MicroSDelay(priv, 30);/* 30us */
/* TXDCOC:disable, RCK:disable */
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]);
MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 |
SOFTPWRCTL_SWPE2 |
/* 3-wire control for power saving mode */
VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */
- return bResult;
+ return ret;
}
/* Need to Pull PLLON low when writing channel registers through
static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byChannel)
{
void __iomem *dwIoBase = priv->PortOffset;
- bool bResult;
+ bool ret;
- bResult = true;
+ ret = true;
/* PLLON Off */
MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable0[byChannel - 1]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable1[byChannel - 1]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable2[byChannel - 1]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable0[byChannel - 1]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable1[byChannel - 1]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable2[byChannel - 1]);
/* PLLOn On */
MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
/* Set Channel[7] = 0 to tell H/W channel is changing now. */
VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F));
- MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL7230);
+ MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL7230);
/* Set Channel[7] = 1 to tell H/W channel change is done. */
VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80));
- return bResult;
+ return ret;
}
/*
{
void __iomem *dwIoBase = priv->PortOffset;
int ii;
- bool bResult;
+ bool ret;
- bResult = true;
+ ret = true;
/* 3-wire control for normal mode */
VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0);
IFRFbWriteEmbedded(priv, (0x07168700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++)
- bResult &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]);
- MACvTimer0MicroSDelay(dwIoBase, 30); /* delay 30 us */
+ ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]);
+ MACvTimer0MicroSDelay(priv, 30); /* delay 30 us */
/* PLL On */
MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
- MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */
- bResult &= IFRFbWriteEmbedded(priv, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
- MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
- bResult &= IFRFbWriteEmbedded(priv, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
- MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
- bResult &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]);
+ MACvTimer0MicroSDelay(priv, 150);/* 150us */
+ ret &= IFRFbWriteEmbedded(priv, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
+ MACvTimer0MicroSDelay(priv, 30);/* 30us */
+ ret &= IFRFbWriteEmbedded(priv, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
+ MACvTimer0MicroSDelay(priv, 30);/* 30us */
+ ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]);
MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 |
SOFTPWRCTL_SWPE2 |
/* 3-wire control for power saving mode */
VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */
- return bResult;
+ return ret;
}
static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byChannel)
{
void __iomem *dwIoBase = priv->PortOffset;
- bool bResult;
+ bool ret;
- bResult = true;
+ ret = true;
- bResult &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable0[byChannel - 1]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable1[byChannel - 1]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable0[byChannel - 1]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable1[byChannel - 1]);
/* Set Channel[7] = 0 to tell H/W channel is changing now. */
VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F));
- MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL2230);
+ MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL2230);
/* Set Channel[7] = 1 to tell H/W channel change is done. */
VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80));
- return bResult;
+ return ret;
}
/*
struct vnt_private *priv
)
{
- bool bResult = true;
+ bool ret = true;
switch (priv->byRFType) {
case RF_AIROHA:
case RF_AL2230S:
priv->byMaxPwrLevel = AL2230_PWR_IDX_LEN;
- bResult = RFbAL2230Init(priv);
+ ret = RFbAL2230Init(priv);
break;
case RF_AIROHA7230:
priv->byMaxPwrLevel = AL7230_PWR_IDX_LEN;
- bResult = s_bAL7230Init(priv);
+ ret = s_bAL7230Init(priv);
break;
case RF_NOTHING:
- bResult = true;
+ ret = true;
break;
default:
- bResult = false;
+ ret = false;
break;
}
- return bResult;
+ return ret;
}
/*
bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType,
u16 byChannel)
{
- bool bResult = true;
+ bool ret = true;
switch (byRFType) {
case RF_AIROHA:
case RF_AL2230S:
- bResult = RFbAL2230SelectChannel(priv, byChannel);
+ ret = RFbAL2230SelectChannel(priv, byChannel);
break;
/*{{ RobertYu: 20050104 */
case RF_AIROHA7230:
- bResult = s_bAL7230SelectChannel(priv, byChannel);
+ ret = s_bAL7230SelectChannel(priv, byChannel);
break;
/*}} RobertYu */
case RF_NOTHING:
- bResult = true;
+ ret = true;
break;
default:
- bResult = false;
+ ret = false;
break;
}
- return bResult;
+ return ret;
}
/*
return false;
for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++)
- MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230InitTable[ii]);
+ MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230InitTable[ii]);
- MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable0[uChannel-1]);
+ MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable0[uChannel-1]);
ii++;
- MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable1[uChannel-1]);
+ MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable1[uChannel-1]);
break;
/* Need to check, PLLON need to be low for channel setting */
if (uChannel <= CB_MAX_CHANNEL_24G) {
for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++)
- MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTable[ii]);
+ MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTable[ii]);
} else {
for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++)
- MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTableAMode[ii]);
+ MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTableAMode[ii]);
}
- MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable0[uChannel-1]);
+ MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable0[uChannel-1]);
ii++;
- MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable1[uChannel-1]);
+ MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable1[uChannel-1]);
ii++;
- MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable2[uChannel-1]);
+ MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable2[uChannel-1]);
break;
case RF_NOTHING:
return false;
}
- MACvSetMISCFifo(dwIoBase, MISCFIFO_SYNINFO_IDX, (unsigned long)MAKEWORD(bySleepCount, byInitCount));
+ MACvSetMISCFifo(priv, MISCFIFO_SYNINFO_IDX, (unsigned long)MAKEWORD(bySleepCount, byInitCount));
return true;
}
u16 uCH
)
{
- bool bResult = true;
+ bool ret = true;
unsigned char byPwr = 0;
unsigned char byDec = 0;
if (priv->byCurPwr == byPwr)
return true;
- bResult = RFbRawSetPower(priv, byPwr, rate);
- if (bResult)
+ ret = RFbRawSetPower(priv, byPwr, rate);
+ if (ret)
priv->byCurPwr = byPwr;
- return bResult;
+ return ret;
}
/*
unsigned int rate
)
{
- bool bResult = true;
+ bool ret = true;
unsigned long dwMax7230Pwr = 0;
if (byPwr >= priv->byMaxPwrLevel)
switch (priv->byRFType) {
case RF_AIROHA:
- bResult &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]);
if (rate <= RATE_11M)
- bResult &= IFRFbWriteEmbedded(priv, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+ ret &= IFRFbWriteEmbedded(priv, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
else
- bResult &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+ ret &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
break;
case RF_AL2230S:
- bResult &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]);
if (rate <= RATE_11M) {
- bResult &= IFRFbWriteEmbedded(priv, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
- bResult &= IFRFbWriteEmbedded(priv, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+ ret &= IFRFbWriteEmbedded(priv, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+ ret &= IFRFbWriteEmbedded(priv, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
} else {
- bResult &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
- bResult &= IFRFbWriteEmbedded(priv, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+ ret &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
+ ret &= IFRFbWriteEmbedded(priv, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW);
}
break;
dwMax7230Pwr = 0x080C0B00 | ((byPwr) << 12) |
(BY_AL7230_REG_LEN << 3) | IFREGCTL_REGW;
- bResult &= IFRFbWriteEmbedded(priv, dwMax7230Pwr);
+ ret &= IFRFbWriteEmbedded(priv, dwMax7230Pwr);
break;
default:
break;
}
- return bResult;
+ return ret;
}
/*+
u16 byOldChannel,
u16 byNewChannel)
{
- bool bResult;
+ bool ret;
- bResult = true;
+ ret = true;
/* if change between 11 b/g and 11a need to update the following
* register
* Channel Index 1~14 */
if ((byOldChannel <= CB_MAX_CHANNEL_24G) && (byNewChannel > CB_MAX_CHANNEL_24G)) {
/* Change from 2.4G to 5G [Reg] */
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[2]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[3]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[5]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[7]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[10]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[12]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[15]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[2]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[3]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[5]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[7]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[10]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[12]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[15]);
} else if ((byOldChannel > CB_MAX_CHANNEL_24G) && (byNewChannel <= CB_MAX_CHANNEL_24G)) {
/* Change from 5G to 2.4G [Reg] */
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[2]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[3]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[5]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[7]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[10]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[12]);
- bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[15]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[2]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[3]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[5]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[7]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[10]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[12]);
+ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[15]);
}
- return bResult;
+ return ret;
}
};
/* flags for options */
-#define DEVICE_FLAGS_UNPLUG BIT(0)
-#define DEVICE_FLAGS_DISCONNECTED BIT(1)
+#define DEVICE_FLAGS_UNPLUG 0
+#define DEVICE_FLAGS_DISCONNECTED 1
struct vnt_private {
/* mac80211 */
#define LONG_RETRY_DEF 4
/* BasebandType[] baseband type selected
- 0: indicate 802.11a type
- 1: indicate 802.11b type
- 2: indicate 802.11g type
-*/
+ * 0: indicate 802.11a type
+ * 1: indicate 802.11b type
+ * 2: indicate 802.11g type
+ */
#define BBP_TYPE_DEF 2
calib_rx_iq = priv->eeprom[EEP_OFS_CALIB_RX_IQ];
if (calib_tx_iq || calib_tx_dc || calib_rx_iq) {
/* CR255, enable TX/RX IQ and
- DC compensation mode */
+ * DC compensation mode
+ */
vnt_control_out_u8(priv,
MESSAGE_REQUEST_BBREG,
0xff,
calib_rx_iq);
} else {
/* CR255, turn off
- BB Calibration compensation */
+ * BB Calibration compensation
+ */
vnt_control_out_u8(priv,
MESSAGE_REQUEST_BBREG,
0xff,
/* disable power saving hw function */
vnt_control_out(priv, MESSAGE_TYPE_DISABLE_PS, 0,
- 0, 0, NULL);
+ 0, 0, NULL);
/* clear AutoSleep */
vnt_mac_reg_bits_off(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
obj-$(CONFIG_WILC1000) += wilc1000.o
-ccflags-y += -DSTA_FIRMWARE=\"atmel/wilc1000_fw.bin\" \
- -DAP_FIRMWARE=\"atmel/wilc1000_ap_fw.bin\" \
- -DP2P_CONCURRENCY_FIRMWARE=\"atmel/wilc1000_p2p_fw.bin\"
+ccflags-y += -DFIRMWARE_1002=\"atmel/wilc1002_firmware.bin\" \
+ -DFIRMWARE_1003=\"atmel/wilc1003_firmware.bin\"
ccflags-y += -I$(src)/ -DWILC_ASIC_A0 -DWILC_DEBUGFS
-#ccflags-y += -DTCP_ACK_FILTER
wilc1000-objs := wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \
wilc_msgqueue.o \
-
-/*!
- * @file coreconfigurator.c
- * @brief
- * @author
- * @sa coreconfigurator.h
- * @date 1 Mar 2012
- * @version 1.0
- */
-
#include "coreconfigurator.h"
#include "wilc_wlan_if.h"
#include "wilc_wlan.h"
#include <linux/errno.h>
#include <linux/slab.h>
#define TAG_PARAM_OFFSET (MAC_HDR_LEN + TIME_STAMP_LEN + \
- BEACON_INTERVAL_LEN + CAP_INFO_LEN)
+ BEACON_INTERVAL_LEN + CAP_INFO_LEN)
-/* Basic Frame Type Codes (2-bit) */
enum basic_frame_type {
FRAME_TYPE_CONTROL = 0x04,
FRAME_TYPE_DATA = 0x08,
FRAME_TYPE_FORCE_32BIT = 0xFFFFFFFF
};
-/* Frame Type and Subtype Codes (6-bit) */
enum sub_frame_type {
ASSOC_REQ = 0x00,
ASSOC_RSP = 0x10,
FRAME_SUBTYPE_FORCE_32BIT = 0xFFFFFFFF
};
-/* Element ID of various Information Elements */
enum info_element_id {
ISSID = 0, /* Service Set Identifier */
ISUPRATES = 1, /* Supported Rates */
INFOELEM_ID_FORCE_32BIT = 0xFFFFFFFF
};
-/* This function extracts the beacon period field from the beacon or probe */
-/* response frame. */
static inline u16 get_beacon_period(u8 *data)
{
u16 bcn_per;
return time_stamp;
}
-/* This function extracts the 'frame type and sub type' bits from the MAC */
-/* header of the input frame. */
-/* Returns the value in the LSB of the returned value. */
static inline enum sub_frame_type get_sub_type(u8 *header)
{
return ((enum sub_frame_type)(header[0] & 0xFC));
}
-/* This function extracts the 'to ds' bit from the MAC header of the input */
-/* frame. */
-/* Returns the value in the LSB of the returned value. */
static inline u8 get_to_ds(u8 *header)
{
return (header[1] & 0x01);
}
-/* This function extracts the 'from ds' bit from the MAC header of the input */
-/* frame. */
-/* Returns the value in the LSB of the returned value. */
static inline u8 get_from_ds(u8 *header)
{
return ((header[1] & 0x02) >> 1);
}
-/* This function extracts the MAC Address in 'address1' field of the MAC */
-/* header and updates the MAC Address in the allocated 'addr' variable. */
static inline void get_address1(u8 *pu8msa, u8 *addr)
{
memcpy(addr, pu8msa + 4, 6);
}
-/* This function extracts the MAC Address in 'address2' field of the MAC */
-/* header and updates the MAC Address in the allocated 'addr' variable. */
static inline void get_address2(u8 *pu8msa, u8 *addr)
{
memcpy(addr, pu8msa + 10, 6);
}
-/* This function extracts the MAC Address in 'address3' field of the MAC */
-/* header and updates the MAC Address in the allocated 'addr' variable. */
static inline void get_address3(u8 *pu8msa, u8 *addr)
{
memcpy(addr, pu8msa + 16, 6);
}
-/* This function extracts the BSSID from the incoming WLAN packet based on */
-/* the 'from ds' bit, and updates the MAC Address in the allocated 'addr' */
-/* variable. */
static inline void get_BSSID(u8 *data, u8 *bssid)
{
if (get_from_ds(data) == 1)
get_address3(data, bssid);
}
-/* This function extracts the SSID from a beacon/probe response frame */
static inline void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len)
{
u8 len = 0;
j = MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN +
CAP_INFO_LEN + 2;
- /* If the SSID length field is set wrongly to a value greater than the */
- /* allowed maximum SSID length limit, reset the length to 0 */
if (len >= MAX_SSID_LEN)
len = 0;
*p_ssid_len = len;
}
-/* This function extracts the capability info field from the beacon or probe */
-/* response frame. */
static inline u16 get_cap_info(u8 *data)
{
u16 cap_info = 0;
st = get_sub_type(data);
- /* Location of the Capability field is different for Beacon and */
- /* Association frames. */
if ((st == BEACON) || (st == PROBE_RSP))
index += TIME_STAMP_LEN + BEACON_INTERVAL_LEN;
return cap_info;
}
-/* This function extracts the capability info field from the Association */
-/* response frame. */
static inline u16 get_assoc_resp_cap_info(u8 *data)
{
u16 cap_info;
return cap_info;
}
-/* This function extracts the association status code from the incoming */
-/* association response frame and returns association status code */
static inline u16 get_asoc_status(u8 *data)
{
u16 asoc_status;
return asoc_status;
}
-/* This function extracts association ID from the incoming association */
-/* response frame */
static inline u16 get_asoc_id(u8 *data)
{
u16 asoc_id;
return asoc_id;
}
-static u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset)
+static u8 *get_tim_elm(u8 *pu8msa, u16 rx_len, u16 tag_param_offset)
{
- u16 u16index;
-
- /*************************************************************************/
- /* Beacon Frame - Frame Body */
- /* --------------------------------------------------------------------- */
- /* |Timestamp |BeaconInt |CapInfo |SSID |SupRates |DSParSet |TIM elm | */
- /* --------------------------------------------------------------------- */
- /* |8 |2 |2 |2-34 |3-10 |3 |4-256 | */
- /* --------------------------------------------------------------------- */
- /* */
- /*************************************************************************/
-
- u16index = u16TagParamOffset;
-
- /* Search for the TIM Element Field and return if the element is found */
- while (u16index < (u16RxLen - FCS_LEN)) {
- if (pu8msa[u16index] == ITIM)
- return &pu8msa[u16index];
- u16index += (IE_HDR_LEN + pu8msa[u16index + 1]);
+ u16 index;
+
+ index = tag_param_offset;
+
+ while (index < (rx_len - FCS_LEN)) {
+ if (pu8msa[index] == ITIM)
+ return &pu8msa[index];
+ index += (IE_HDR_LEN + pu8msa[index + 1]);
}
return NULL;
}
-/* This function gets the current channel information from
- * the 802.11n beacon/probe response frame */
-static u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen)
+static u8 get_current_channel_802_11n(u8 *pu8msa, u16 rx_len)
{
u16 index;
index = TAG_PARAM_OFFSET;
- while (index < (u16RxLen - FCS_LEN)) {
+ while (index < (rx_len - FCS_LEN)) {
if (pu8msa[index] == IDSPARMS)
return pu8msa[index + 2];
- /* Increment index by length information and header */
index += pu8msa[index + 1] + IE_HDR_LEN;
}
- /* Return current channel information from the MIB, if beacon/probe */
- /* response frame does not contain the DS parameter set IE */
- /* return (mget_CurrentChannel() + 1); */
- return 0; /* no MIB here */
+ return 0;
}
-/**
- * @brief parses the received 'N' message
- * @details
- * @param[in] pu8MsgBuffer The message to be parsed
- * @param[out] ppstrNetworkInfo pointer to pointer to the structure containing the parsed Network Info
- * @return Error code indicating success/failure
- * @note
- * @author mabubakr
- * @date 1 Mar 2012
- * @version 1.0
- */
-s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo)
+s32 wilc_parse_network_info(u8 *msg_buffer,
+ struct network_info **ret_network_info)
{
- tstrNetworkInfo *pstrNetworkInfo = NULL;
- u8 u8MsgType = 0;
- u8 u8MsgID = 0;
- u16 u16MsgLen = 0;
+ struct network_info *network_info = NULL;
+ u8 msg_type = 0;
+ u8 msg_id = 0;
+ u16 msg_len = 0;
- u16 u16WidID = (u16)WID_NIL;
- u16 u16WidLen = 0;
- u8 *pu8WidVal = NULL;
+ u16 wid_id = (u16)WID_NIL;
+ u16 wid_len = 0;
+ u8 *wid_val = NULL;
- u8MsgType = pu8MsgBuffer[0];
+ msg_type = msg_buffer[0];
- /* Check whether the received message type is 'N' */
- if ('N' != u8MsgType) {
+ if ('N' != msg_type) {
PRINT_ER("Received Message format incorrect.\n");
return -EFAULT;
}
- /* Extract message ID */
- u8MsgID = pu8MsgBuffer[1];
-
- /* Extract message Length */
- u16MsgLen = MAKE_WORD16(pu8MsgBuffer[2], pu8MsgBuffer[3]);
-
- /* Extract WID ID */
- u16WidID = MAKE_WORD16(pu8MsgBuffer[4], pu8MsgBuffer[5]);
-
- /* Extract WID Length */
- u16WidLen = MAKE_WORD16(pu8MsgBuffer[6], pu8MsgBuffer[7]);
-
- /* Assign a pointer to the WID value */
- pu8WidVal = &pu8MsgBuffer[8];
+ msg_id = msg_buffer[1];
+ msg_len = MAKE_WORD16(msg_buffer[2], msg_buffer[3]);
+ wid_id = MAKE_WORD16(msg_buffer[4], msg_buffer[5]);
+ wid_len = MAKE_WORD16(msg_buffer[6], msg_buffer[7]);
+ wid_val = &msg_buffer[8];
- /* parse the WID value of the WID "WID_NEWORK_INFO" */
{
- u8 *pu8msa = NULL;
- u16 u16RxLen = 0;
- u8 *pu8TimElm = NULL;
- u8 *pu8IEs = NULL;
- u16 u16IEsLen = 0;
- u8 u8index = 0;
- u32 u32Tsf_Lo;
- u32 u32Tsf_Hi;
-
- pstrNetworkInfo = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL);
- if (!pstrNetworkInfo)
+ u8 *msa = NULL;
+ u16 rx_len = 0;
+ u8 *tim_elm = NULL;
+ u8 *ies = NULL;
+ u16 ies_len = 0;
+ u8 index = 0;
+ u32 tsf_lo;
+ u32 tsf_hi;
+
+ network_info = kzalloc(sizeof(*network_info), GFP_KERNEL);
+ if (!network_info)
return -ENOMEM;
- pstrNetworkInfo->s8rssi = pu8WidVal[0];
+ network_info->rssi = wid_val[0];
- /* Assign a pointer to msa "Mac Header Start Address" */
- pu8msa = &pu8WidVal[1];
+ msa = &wid_val[1];
- u16RxLen = u16WidLen - 1;
+ rx_len = wid_len - 1;
+ network_info->cap_info = get_cap_info(msa);
+ network_info->tsf_lo = get_beacon_timestamp_lo(msa);
- /* parse msa*/
+ tsf_lo = get_beacon_timestamp_lo(msa);
+ tsf_hi = get_beacon_timestamp_hi(msa);
- /* Get the cap_info */
- pstrNetworkInfo->u16CapInfo = get_cap_info(pu8msa);
- /* Get time-stamp [Low only 32 bit] */
- pstrNetworkInfo->u32Tsf = get_beacon_timestamp_lo(pu8msa);
- PRINT_D(CORECONFIG_DBG, "TSF :%x\n", pstrNetworkInfo->u32Tsf);
+ network_info->tsf_hi = tsf_lo | ((u64)tsf_hi << 32);
- /* Get full time-stamp [Low and High 64 bit] */
- u32Tsf_Lo = get_beacon_timestamp_lo(pu8msa);
- u32Tsf_Hi = get_beacon_timestamp_hi(pu8msa);
+ get_ssid(msa, network_info->ssid, &network_info->ssid_len);
+ get_BSSID(msa, network_info->bssid);
- pstrNetworkInfo->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32);
+ network_info->ch = get_current_channel_802_11n(msa,
+ rx_len + FCS_LEN);
- /* Get SSID */
- get_ssid(pu8msa, pstrNetworkInfo->au8ssid, &pstrNetworkInfo->u8SsidLen);
+ index = MAC_HDR_LEN + TIME_STAMP_LEN;
- /* Get BSSID */
- get_BSSID(pu8msa, pstrNetworkInfo->au8bssid);
+ network_info->beacon_period = get_beacon_period(msa + index);
- /*
- * Extract current channel information from
- * the beacon/probe response frame
- */
- pstrNetworkInfo->u8channel = get_current_channel_802_11n(pu8msa,
- u16RxLen + FCS_LEN);
+ index += BEACON_INTERVAL_LEN + CAP_INFO_LEN;
- /* Get beacon period */
- u8index = MAC_HDR_LEN + TIME_STAMP_LEN;
+ tim_elm = get_tim_elm(msa, rx_len + FCS_LEN, index);
+ if (tim_elm)
+ network_info->dtim_period = tim_elm[3];
+ ies = &msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN +
+ CAP_INFO_LEN];
+ ies_len = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN +
+ BEACON_INTERVAL_LEN + CAP_INFO_LEN);
- pstrNetworkInfo->u16BeaconPeriod = get_beacon_period(pu8msa + u8index);
-
- u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN;
-
- /* Get DTIM Period */
- pu8TimElm = get_tim_elm(pu8msa, u16RxLen + FCS_LEN, u8index);
- if (pu8TimElm)
- pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3];
- pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN];
- u16IEsLen = u16RxLen - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN);
-
- if (u16IEsLen > 0) {
- pstrNetworkInfo->pu8IEs = kmemdup(pu8IEs, u16IEsLen,
- GFP_KERNEL);
- if (!pstrNetworkInfo->pu8IEs)
+ if (ies_len > 0) {
+ network_info->ies = kmemdup(ies, ies_len, GFP_KERNEL);
+ if (!network_info->ies)
return -ENOMEM;
}
- pstrNetworkInfo->u16IEsLen = u16IEsLen;
-
+ network_info->ies_len = ies_len;
}
- *ppstrNetworkInfo = pstrNetworkInfo;
+ *ret_network_info = network_info;
return 0;
}
-/**
- * @brief Deallocates the parsed Network Info
- * @details
- * @param[in] pstrNetworkInfo Network Info to be deallocated
- * @return Error code indicating success/failure
- * @note
- * @author mabubakr
- * @date 1 Mar 2012
- * @version 1.0
- */
-s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo)
+s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
+ struct connect_resp_info **ret_connect_resp_info)
{
- s32 s32Error = 0;
-
- if (pstrNetworkInfo) {
- if (pstrNetworkInfo->pu8IEs) {
- kfree(pstrNetworkInfo->pu8IEs);
- pstrNetworkInfo->pu8IEs = NULL;
- } else {
- s32Error = -EFAULT;
- }
-
- kfree(pstrNetworkInfo);
- pstrNetworkInfo = NULL;
-
- } else {
- s32Error = -EFAULT;
- }
-
- return s32Error;
-}
+ struct connect_resp_info *connect_resp_info = NULL;
+ u16 assoc_resp_len = 0;
+ u8 *ies = NULL;
+ u16 ies_len = 0;
-/**
- * @brief parses the received Association Response frame
- * @details
- * @param[in] pu8Buffer The Association Response frame to be parsed
- * @param[out] ppstrConnectRespInfo pointer to pointer to the structure containing the parsed Association Response Info
- * @return Error code indicating success/failure
- * @note
- * @author mabubakr
- * @date 2 Apr 2012
- * @version 1.0
- */
-s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen,
- tstrConnectRespInfo **ppstrConnectRespInfo)
-{
- s32 s32Error = 0;
- tstrConnectRespInfo *pstrConnectRespInfo = NULL;
- u16 u16AssocRespLen = 0;
- u8 *pu8IEs = NULL;
- u16 u16IEsLen = 0;
-
- pstrConnectRespInfo = kzalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL);
- if (!pstrConnectRespInfo)
+ connect_resp_info = kzalloc(sizeof(*connect_resp_info), GFP_KERNEL);
+ if (!connect_resp_info)
return -ENOMEM;
- /* u16AssocRespLen = pu8Buffer[0]; */
- u16AssocRespLen = (u16)u32BufferLen;
-
- /* get the status code */
- pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(pu8Buffer);
- if (pstrConnectRespInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE) {
-
- /* get the capability */
- pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(pu8Buffer);
+ assoc_resp_len = (u16)buffer_len;
- /* get the Association ID */
- pstrConnectRespInfo->u16AssocID = get_asoc_id(pu8Buffer);
+ connect_resp_info->status = get_asoc_status(buffer);
+ if (connect_resp_info->status == SUCCESSFUL_STATUSCODE) {
+ connect_resp_info->capability = get_assoc_resp_cap_info(buffer);
+ connect_resp_info->assoc_id = get_asoc_id(buffer);
- /* get the Information Elements */
- pu8IEs = &pu8Buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN];
- u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN);
+ ies = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN];
+ ies_len = assoc_resp_len - (CAP_INFO_LEN + STATUS_CODE_LEN +
+ AID_LEN);
- pstrConnectRespInfo->pu8RespIEs = kmemdup(pu8IEs, u16IEsLen, GFP_KERNEL);
- if (!pstrConnectRespInfo->pu8RespIEs)
+ connect_resp_info->ies = kmemdup(ies, ies_len, GFP_KERNEL);
+ if (!connect_resp_info->ies)
return -ENOMEM;
- pstrConnectRespInfo->u16RespIEsLen = u16IEsLen;
- }
-
- *ppstrConnectRespInfo = pstrConnectRespInfo;
-
- return s32Error;
-}
-
-/**
- * @brief Deallocates the parsed Association Response Info
- * @details
- * @param[in] pstrNetworkInfo Network Info to be deallocated
- * @return Error code indicating success/failure
- * @note
- * @author mabubakr
- * @date 2 Apr 2012
- * @version 1.0
- */
-s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo)
-{
- s32 s32Error = 0;
-
- if (pstrConnectRespInfo) {
- if (pstrConnectRespInfo->pu8RespIEs) {
- kfree(pstrConnectRespInfo->pu8RespIEs);
- pstrConnectRespInfo->pu8RespIEs = NULL;
- } else {
- s32Error = -EFAULT;
- }
-
- kfree(pstrConnectRespInfo);
- pstrConnectRespInfo = NULL;
-
- } else {
- s32Error = -EFAULT;
+ connect_resp_info->ies_len = ies_len;
}
- return s32Error;
-}
-
-/**
- * @brief sends certain Configuration Packet based on the input WIDs pstrWIDs
- * using driver config layer
- *
- * @details
- * @param[in] pstrWIDs WIDs to be sent in the configuration packet
- * @param[in] u32WIDsCount number of WIDs to be sent in the configuration packet
- * @param[out] pu8RxResp The received Packet Response
- * @param[out] ps32RxRespLen Length of the received Packet Response
- * @return Error code indicating success/failure
- * @note
- * @author mabubakr
- * @date 1 Mar 2012
- * @version 1.0
- */
-s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids,
- u32 count, u32 drv)
-{
- s32 counter = 0, ret = 0;
-
- if (mode == GET_CFG) {
- for (counter = 0; counter < count; counter++) {
- PRINT_INFO(CORECONFIG_DBG, "Sending CFG packet [%d][%d]\n", !counter,
- (counter == count - 1));
- if (!wilc_wlan_cfg_get(wilc, !counter,
- wids[counter].id,
- (counter == count - 1),
- drv)) {
- ret = -ETIMEDOUT;
- printk("[Sendconfigpkt]Get Timed out\n");
- break;
- }
- }
- counter = 0;
- for (counter = 0; counter < count; counter++) {
- wids[counter].size = wilc_wlan_cfg_get_val(
- wids[counter].id,
- wids[counter].val,
- wids[counter].size);
- }
- } else if (mode == SET_CFG) {
- for (counter = 0; counter < count; counter++) {
- PRINT_D(CORECONFIG_DBG, "Sending config SET PACKET WID:%x\n", wids[counter].id);
- if (!wilc_wlan_cfg_set(wilc, !counter,
- wids[counter].id,
- wids[counter].val,
- wids[counter].size,
- (counter == count - 1),
- drv)) {
- ret = -ETIMEDOUT;
- printk("[Sendconfigpkt]Set Timed out\n");
- break;
- }
- }
- }
+ *ret_connect_resp_info = connect_resp_info;
- return ret;
+ return 0;
}
CONNECT_STS_FORCE_16_BIT = 0xFFFF
} tenuConnectSts;
-struct wid {
- u16 id;
- enum wid_type type;
- s32 size;
- s8 *val;
-};
-
typedef struct {
u8 u8Full;
u8 u8Index;
s8 as8RSSI[NUM_RSSI];
} tstrRSSI;
-typedef struct {
- s8 s8rssi;
- u16 u16CapInfo;
- u8 au8ssid[MAX_SSID_LEN];
- u8 u8SsidLen;
- u8 au8bssid[6];
- u16 u16BeaconPeriod;
- u8 u8DtimPeriod;
- u8 u8channel;
- unsigned long u32TimeRcvdInScanCached;
- unsigned long u32TimeRcvdInScan;
- bool bNewNetwork;
- u8 u8Found;
- u32 u32Tsf;
- u8 *pu8IEs;
- u16 u16IEsLen;
- void *pJoinParams;
- tstrRSSI strRssi;
- u64 u64Tsf;
-} tstrNetworkInfo;
+struct network_info {
+ s8 rssi;
+ u16 cap_info;
+ u8 ssid[MAX_SSID_LEN];
+ u8 ssid_len;
+ u8 bssid[6];
+ u16 beacon_period;
+ u8 dtim_period;
+ u8 ch;
+ unsigned long time_scan_cached;
+ unsigned long time_scan;
+ bool new_network;
+ u8 found;
+ u32 tsf_lo;
+ u8 *ies;
+ u16 ies_len;
+ void *join_params;
+ tstrRSSI str_rssi;
+ u64 tsf_hi;
+};
-typedef struct {
- u16 u16capability;
- u16 u16ConnectStatus;
- u16 u16AssocID;
- u8 *pu8RespIEs;
- u16 u16RespIEsLen;
-} tstrConnectRespInfo;
+struct connect_resp_info {
+ u16 capability;
+ u16 status;
+ u16 assoc_id;
+ u8 *ies;
+ u16 ies_len;
+};
typedef struct {
u8 au8bssid[6];
size_t ie_len;
} tstrDisconnectNotifInfo;
-s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids,
- u32 count, u32 drv);
-s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo);
-s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo);
-
-s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen,
- tstrConnectRespInfo **ppstrConnectRespInfo);
-s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo);
+s32 wilc_parse_network_info(u8 *msg_buffer,
+ struct network_info **ret_network_info);
+s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
+ struct connect_resp_info **ret_connect_resp_info);
void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer,
u32 u32Length);
void wilc_network_info_received(struct wilc *wilc, u8 *pu8Buffer,
#define HOST_IF_MSG_DEL_BA_SESSION 34
#define HOST_IF_MSG_Q_IDLE 35
#define HOST_IF_MSG_DEL_ALL_STA 36
-#define HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS 34
+#define HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS 37
+#define HOST_IF_MSG_SET_TX_POWER 38
+#define HOST_IF_MSG_GET_TX_POWER 39
#define HOST_IF_MSG_EXIT 100
#define HOST_IF_SCAN_TIMEOUT 4000
#define BLOCK_ACK_REQ_SIZE 0x14
#define FALSE_FRMWR_CHANNEL 100
+#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54
+#define DEFAULT_LINK_SPEED 72
+
struct cfg_param_attr {
struct cfg_param_val cfg_attr_info;
};
u8 mac[6];
};
+struct tx_power {
+ u8 tx_pwr;
+};
+
union message_body {
struct scan_attr scan_info;
struct connect_attr con_info;
struct reg_frame reg_frame;
char *data;
struct del_all_sta del_all_sta_info;
+ struct tx_power tx_power;
};
struct host_if_msg {
u8 start_time[4];
};
-struct host_if_drv *terminated_handle;
+static struct host_if_drv *terminated_handle;
bool wilc_optaining_ip;
static u8 P2P_LISTEN_STATE;
static struct task_struct *hif_thread_handler;
-static WILC_MsgQueueHandle hif_msg_q;
+static struct message_queue hif_msg_q;
static struct semaphore hif_sema_thread;
static struct semaphore hif_sema_driver;
static struct semaphore hif_sema_wait_response;
#define FLUSHED_JOIN_REQ 1
#define FLUSHED_BYTE_POS 79
-static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo);
+static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo);
+static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx);
/* The u8IfIdx starts from 0 to NUM_CONCURRENT_IFC -1, but 0 index used as
* special purpose in wilc device, so we add 1 to the index to starts from 1.
*/
int wilc_get_vif_idx(struct wilc_vif *vif)
{
- return vif->u8IfIdx + 1;
+ return vif->idx + 1;
}
/* We need to minus 1 from idx which is from wilc device to get real index
wid.val = (char *)&hif_set_ch->set_ch;
wid.size = sizeof(char);
- PRINT_D(HOSTINF_DBG, "Setting channel\n");
-
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
PRINT_ER("Failed to set channel\n");
struct wid wid;
wid.id = (u16)WID_SET_DRV_HANDLER;
- wid.type = WID_INT;
- wid.val = (s8 *)&hif_drv_handler->handler;
- wid.size = sizeof(u32);
+ wid.type = WID_STR;
+ wid.val = (s8 *)hif_drv_handler;
+ wid.size = sizeof(*hif_drv_handler);
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
hif_drv_handler->handler);
if (!hif_drv_handler->handler)
wid.val = (s8 *)&hif_op_mode->mode;
wid.size = sizeof(u32);
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if ((hif_op_mode->mode) == IDLE_MODE)
up(&hif_sema_driver);
return result;
}
-static s32 host_int_get_ipaddress(struct wilc_vif *vif,
- struct host_if_drv *hif_drv,
- u8 *u16ipadd, u8 idx);
-
static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
{
s32 result = 0;
struct wid wid;
char firmware_ip_addr[4] = {0};
- struct host_if_drv *hif_drv = vif->hif_drv;
if (ip_addr[0] < 192)
ip_addr[0] = 0;
- PRINT_INFO(HOSTINF_DBG, "Indx = %d, Handling set IP = %pI4\n",
- idx, ip_addr);
-
memcpy(set_ip[idx], ip_addr, IP_ALEN);
wid.id = (u16)WID_IP_ADDRESS;
wid.val = (u8 *)ip_addr;
wid.size = IP_ALEN;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
- host_int_get_ipaddress(vif, hif_drv, firmware_ip_addr, idx);
+ host_int_get_ipaddress(vif, firmware_ip_addr, idx);
if (result) {
PRINT_ER("Failed to set IP address\n");
return -EINVAL;
}
- PRINT_INFO(HOSTINF_DBG, "IP address set\n");
-
return result;
}
wid.val = kmalloc(IP_ALEN, GFP_KERNEL);
wid.size = IP_ALEN;
- result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
-
- PRINT_INFO(HOSTINF_DBG, "%pI4\n", wid.val);
+ result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
memcpy(get_ip[idx], wid.val, IP_ALEN);
return -EINVAL;
}
- PRINT_INFO(HOSTINF_DBG, "IP address retrieved:: u8IfIdx = %d\n", idx);
- PRINT_INFO(HOSTINF_DBG, "%pI4\n", get_ip[idx]);
- PRINT_INFO(HOSTINF_DBG, "\n");
-
return result;
}
wid.type = WID_STR;
wid.val = mac_buf;
wid.size = ETH_ALEN;
- PRINT_D(GENERIC_DBG, "mac addr = :%pM\n", wid.val);
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
PRINT_ER("Failed to set mac address\n");
result = -EFAULT;
wid.val = get_mac_addr->mac_addr;
wid.size = ETH_ALEN;
- result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
PRINT_ER("Failed to get mac address\n");
down(&hif_drv->sem_cfg_values);
- PRINT_D(HOSTINF_DBG, "Setting CFG params\n");
-
if (cfg_param_attr->cfg_attr_info.flag & BSS_TYPE) {
if (cfg_param_attr->cfg_attr_info.bss_type < 6) {
wid_list[wid_cnt].id = WID_BSS_TYPE;
wid_cnt++;
}
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, wid_list,
+ result = wilc_send_config_pkt(vif, SET_CFG, wid_list,
wid_cnt, wilc_get_vif_idx(vif));
if (result)
u8 *pu8HdnNtwrksWidVal = NULL;
struct host_if_drv *hif_drv = vif->hif_drv;
- PRINT_D(HOSTINF_DBG, "Setting SCAN params\n");
- PRINT_D(HOSTINF_DBG, "Scanning: In [%d] state\n", hif_drv->hif_state);
-
hif_drv->usr_scan_req.scan_result = pstrHostIFscanAttr->result;
hif_drv->usr_scan_req.arg = pstrHostIFscanAttr->arg;
if ((hif_drv->hif_state >= HOST_IF_SCANNING) &&
(hif_drv->hif_state < HOST_IF_CONNECTED)) {
- PRINT_D(GENERIC_DBG, "Don't scan already in [%d] state\n",
- hif_drv->hif_state);
PRINT_ER("Already scan\n");
result = -EBUSY;
goto ERRORHANDLER;
}
if (wilc_optaining_ip || wilc_connecting) {
- PRINT_D(GENERIC_DBG, "[handle_scan]: Don't do obss scan until IP adresss is obtained\n");
PRINT_ER("Don't do obss scan\n");
result = -EBUSY;
goto ERRORHANDLER;
}
- PRINT_D(HOSTINF_DBG, "Setting SCAN params\n");
-
hif_drv->usr_scan_req.rcvd_ch_cnt = 0;
strWIDList[u32WidsCount].id = (u16)WID_SSID_PROBE_REQ;
strWIDList[u32WidsCount].type = WID_STR;
- for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++)
- valuesize += ((pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen) + 1);
+ for (i = 0; i < pstrHostIFscanAttr->hidden_network.n_ssids; i++)
+ valuesize += ((pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len) + 1);
pu8HdnNtwrksWidVal = kmalloc(valuesize + 1, GFP_KERNEL);
strWIDList[u32WidsCount].val = pu8HdnNtwrksWidVal;
if (strWIDList[u32WidsCount].val) {
pu8Buffer = strWIDList[u32WidsCount].val;
- *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.u8ssidnum;
+ *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.n_ssids;
- PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->hidden_network.u8ssidnum);
-
- for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) {
- *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen;
- memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].pu8ssid, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen);
- pu8Buffer += pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen;
+ for (i = 0; i < pstrHostIFscanAttr->hidden_network.n_ssids; i++) {
+ *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len;
+ memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.net_info[i].ssid, pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len);
+ pu8Buffer += pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len;
}
strWIDList[u32WidsCount].size = (s32)(valuesize + 1);
else if (hif_drv->hif_state == HOST_IF_IDLE)
scan_while_connected = false;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, strWIDList,
+ result = wilc_send_config_pkt(vif, SET_CFG, strWIDList,
u32WidsCount,
wilc_get_vif_idx(vif));
if (result)
PRINT_ER("Failed to send scan paramters config packet\n");
- else
- PRINT_D(HOSTINF_DBG, "Successfully sent SCAN params config packet\n");
ERRORHANDLER:
if (result) {
kfree(pstrHostIFscanAttr->ies);
pstrHostIFscanAttr->ies = NULL;
- kfree(pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo);
- pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo = NULL;
+ kfree(pstrHostIFscanAttr->hidden_network.net_info);
+ pstrHostIFscanAttr->hidden_network.net_info = NULL;
kfree(pu8HdnNtwrksWidVal);
struct wid wid;
struct host_if_drv *hif_drv = vif->hif_drv;
- PRINT_D(HOSTINF_DBG, "in Handle_ScanDone()\n");
-
if (enuEvent == SCAN_EVENT_ABORTED) {
- PRINT_D(GENERIC_DBG, "Abort running scan\n");
u8abort_running_scan = 1;
wid.id = (u16)WID_ABORT_RUNNING_SCAN;
wid.type = WID_CHAR;
wid.val = (s8 *)&u8abort_running_scan;
wid.size = sizeof(char);
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
PRINT_ER("Failed to set abort running scan\n");
struct join_bss_param *ptstrJoinBssParam;
struct host_if_drv *hif_drv = vif->hif_drv;
- PRINT_D(GENERIC_DBG, "Handling connect request\n");
-
if (memcmp(pstrHostIFconnectAttr->bssid, wilc_connected_ssid, ETH_ALEN) == 0) {
result = 0;
PRINT_ER("Trying to connect to an already connected AP, Discard connect request\n");
return result;
}
- PRINT_INFO(HOSTINF_DBG, "Saving connection parameters in global structure\n");
-
ptstrJoinBssParam = (struct join_bss_param *)pstrHostIFconnectAttr->params;
if (!ptstrJoinBssParam) {
PRINT_ER("Required BSSID not found\n");
if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7))
mode_11i = hif_drv->usr_conn_req.u8security;
- PRINT_INFO(HOSTINF_DBG, "Encrypt Mode = %x\n", hif_drv->usr_conn_req.u8security);
-
strWIDList[u32WidsCount].id = (u16)WID_AUTH_TYPE;
strWIDList[u32WidsCount].type = WID_CHAR;
strWIDList[u32WidsCount].size = sizeof(char);
if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7))
auth_type = (u8)hif_drv->usr_conn_req.auth_type;
- PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n",
- hif_drv->usr_conn_req.auth_type);
- PRINT_D(HOSTINF_DBG, "Connecting to network of SSID %s on channel %d\n",
- hif_drv->usr_conn_req.pu8ssid, pstrHostIFconnectAttr->ch);
-
strWIDList[u32WidsCount].id = (u16)WID_JOIN_REQ_EXTENDED;
strWIDList[u32WidsCount].type = WID_STR;
strWIDList[u32WidsCount].size = 112;
}
*(pu8CurrByte++) = (ptstrJoinBssParam->cap_info) & 0xFF;
*(pu8CurrByte++) = ((ptstrJoinBssParam->cap_info) >> 8) & 0xFF;
- PRINT_D(HOSTINF_DBG, "* Cap Info %0x*\n", (*(pu8CurrByte - 2) | ((*(pu8CurrByte - 1)) << 8)));
if (pstrHostIFconnectAttr->bssid)
memcpy(pu8CurrByte, pstrHostIFconnectAttr->bssid, 6);
*(pu8CurrByte++) = (ptstrJoinBssParam->beacon_period) & 0xFF;
*(pu8CurrByte++) = ((ptstrJoinBssParam->beacon_period) >> 8) & 0xFF;
- PRINT_D(HOSTINF_DBG, "* Beacon Period %d*\n", (*(pu8CurrByte - 2) | ((*(pu8CurrByte - 1)) << 8)));
*(pu8CurrByte++) = ptstrJoinBssParam->dtim_period;
- PRINT_D(HOSTINF_DBG, "* DTIM Period %d*\n", (*(pu8CurrByte - 1)));
memcpy(pu8CurrByte, ptstrJoinBssParam->supp_rates, MAX_RATES_SUPPORTED + 1);
pu8CurrByte += (MAX_RATES_SUPPORTED + 1);
*(pu8CurrByte++) = ptstrJoinBssParam->wmm_cap;
- PRINT_D(HOSTINF_DBG, "* wmm cap%d*\n", (*(pu8CurrByte - 1)));
*(pu8CurrByte++) = ptstrJoinBssParam->uapsd_cap;
*(pu8CurrByte++) = ptstrJoinBssParam->ht_capable;
hif_drv->usr_conn_req.ht_capable = ptstrJoinBssParam->ht_capable;
*(pu8CurrByte++) = ptstrJoinBssParam->rsn_found;
- PRINT_D(HOSTINF_DBG, "* rsn found %d*\n", *(pu8CurrByte - 1));
*(pu8CurrByte++) = ptstrJoinBssParam->rsn_grp_policy;
- PRINT_D(HOSTINF_DBG, "* rsn group policy %0x*\n", (*(pu8CurrByte - 1)));
*(pu8CurrByte++) = ptstrJoinBssParam->mode_802_11i;
- PRINT_D(HOSTINF_DBG, "* mode_802_11i %d*\n", (*(pu8CurrByte - 1)));
memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_pcip_policy, sizeof(ptstrJoinBssParam->rsn_pcip_policy));
pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_pcip_policy);
*(pu8CurrByte++) = ptstrJoinBssParam->noa_enabled;
if (ptstrJoinBssParam->noa_enabled) {
- PRINT_D(HOSTINF_DBG, "NOA present\n");
-
*(pu8CurrByte++) = (ptstrJoinBssParam->tsf) & 0xFF;
*(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 8) & 0xFF;
*(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 16) & 0xFF;
memcpy(pu8CurrByte, ptstrJoinBssParam->start_time, sizeof(ptstrJoinBssParam->start_time));
pu8CurrByte += sizeof(ptstrJoinBssParam->start_time);
- } else
- PRINT_D(HOSTINF_DBG, "NOA not present\n");
+ }
pu8CurrByte = strWIDList[u32WidsCount].val;
u32WidsCount++;
join_req_vif = vif;
}
- PRINT_D(GENERIC_DBG, "send HOST_IF_WAITING_CONN_RESP\n");
-
- if (pstrHostIFconnectAttr->bssid) {
+ if (pstrHostIFconnectAttr->bssid)
memcpy(wilc_connected_ssid,
pstrHostIFconnectAttr->bssid, ETH_ALEN);
- PRINT_D(GENERIC_DBG, "save Bssid = %pM\n",
- pstrHostIFconnectAttr->bssid);
- PRINT_D(GENERIC_DBG, "save bssid = %pM\n", wilc_connected_ssid);
- }
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, strWIDList,
+ result = wilc_send_config_pkt(vif, SET_CFG, strWIDList,
u32WidsCount,
wilc_get_vif_idx(vif));
if (result) {
result = -EFAULT;
goto ERRORHANDLER;
} else {
- PRINT_D(GENERIC_DBG, "set HOST_IF_WAITING_CONN_RESP\n");
hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
}
del_timer(&hif_drv->connect_timer);
- PRINT_D(HOSTINF_DBG, "could not start wilc_connecting to the required network\n");
-
memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
if (pstrHostIFconnectAttr->result) {
}
}
- PRINT_D(HOSTINF_DBG, "Deallocating connection parameters\n");
kfree(pstrHostIFconnectAttr->bssid);
pstrHostIFconnectAttr->bssid = NULL;
u32WidsCount++;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, strWIDList,
+ result = wilc_send_config_pkt(vif, SET_CFG, strWIDList,
u32WidsCount,
wilc_get_vif_idx(join_req_vif));
if (result) {
wid.val = (s8 *)&u16DummyReasonCode;
wid.size = sizeof(char);
- PRINT_D(HOSTINF_DBG, "Sending disconnect request\n");
-
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result)
PRINT_ER("Failed to send dissconect config packet\n");
u32 i;
bool bNewNtwrkFound;
s32 result = 0;
- tstrNetworkInfo *pstrNetworkInfo = NULL;
+ struct network_info *pstrNetworkInfo = NULL;
void *pJoinParams = NULL;
struct host_if_drv *hif_drv = vif->hif_drv;
bNewNtwrkFound = true;
- PRINT_INFO(HOSTINF_DBG, "Handling received network info\n");
if (hif_drv->usr_scan_req.scan_result) {
- PRINT_D(HOSTINF_DBG, "State: Scanning, parsing network information received\n");
wilc_parse_network_info(pstrRcvdNetworkInfo->buffer, &pstrNetworkInfo);
if ((!pstrNetworkInfo) ||
(!hif_drv->usr_scan_req.scan_result)) {
for (i = 0; i < hif_drv->usr_scan_req.rcvd_ch_cnt; i++) {
if ((hif_drv->usr_scan_req.net_info[i].au8bssid) &&
- (pstrNetworkInfo->au8bssid)) {
+ (pstrNetworkInfo->bssid)) {
if (memcmp(hif_drv->usr_scan_req.net_info[i].au8bssid,
- pstrNetworkInfo->au8bssid, 6) == 0) {
- if (pstrNetworkInfo->s8rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) {
- PRINT_D(HOSTINF_DBG, "Network previously discovered\n");
+ pstrNetworkInfo->bssid, 6) == 0) {
+ if (pstrNetworkInfo->rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) {
goto done;
} else {
- hif_drv->usr_scan_req.net_info[i].s8rssi = pstrNetworkInfo->s8rssi;
+ hif_drv->usr_scan_req.net_info[i].s8rssi = pstrNetworkInfo->rssi;
bNewNtwrkFound = false;
break;
}
}
if (bNewNtwrkFound) {
- PRINT_D(HOSTINF_DBG, "New network found\n");
-
if (hif_drv->usr_scan_req.rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) {
- hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->s8rssi;
+ hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->rssi;
if (hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid &&
- pstrNetworkInfo->au8bssid) {
+ pstrNetworkInfo->bssid) {
memcpy(hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid,
- pstrNetworkInfo->au8bssid, 6);
+ pstrNetworkInfo->bssid, 6);
hif_drv->usr_scan_req.rcvd_ch_cnt++;
- pstrNetworkInfo->bNewNetwork = true;
+ pstrNetworkInfo->new_network = true;
pJoinParams = host_int_ParseJoinBssParam(pstrNetworkInfo);
hif_drv->usr_scan_req.scan_result(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo,
hif_drv->usr_scan_req.arg,
pJoinParams);
}
- } else {
- PRINT_WRN(HOSTINF_DBG, "Discovered networks exceeded max. limit\n");
}
} else {
- pstrNetworkInfo->bNewNetwork = false;
+ pstrNetworkInfo->new_network = false;
hif_drv->usr_scan_req.scan_result(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo,
hif_drv->usr_scan_req.arg, NULL);
}
pstrRcvdNetworkInfo->buffer = NULL;
if (pstrNetworkInfo) {
- wilc_dealloc_network_info(pstrNetworkInfo);
- pstrNetworkInfo = NULL;
+ kfree(pstrNetworkInfo->ies);
+ kfree(pstrNetworkInfo);
}
return result;
PRINT_ER("Driver handler is NULL\n");
return -ENODEV;
}
- PRINT_D(GENERIC_DBG, "Current State = %d,Received state = %d\n",
- hif_drv->hif_state, pstrRcvdGnrlAsyncInfo->buffer[7]);
if ((hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) ||
(hif_drv->hif_state == HOST_IF_CONNECTED) ||
u8MacStatus = pstrRcvdGnrlAsyncInfo->buffer[7];
u8MacStatusReasonCode = pstrRcvdGnrlAsyncInfo->buffer[8];
u8MacStatusAdditionalInfo = pstrRcvdGnrlAsyncInfo->buffer[9];
- PRINT_INFO(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Info = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo);
if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
u32 u32RcvdAssocRespInfoLen = 0;
- tstrConnectRespInfo *pstrConnectRespInfo = NULL;
-
- PRINT_D(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Code = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo);
+ struct connect_resp_info *pstrConnectRespInfo = NULL;
memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
MAX_ASSOC_RESP_FRAME_SIZE,
&u32RcvdAssocRespInfoLen);
- PRINT_INFO(HOSTINF_DBG, "Received association response with length = %d\n", u32RcvdAssocRespInfoLen);
-
if (u32RcvdAssocRespInfoLen != 0) {
- PRINT_D(HOSTINF_DBG, "Parsing association response\n");
s32Err = wilc_parse_assoc_resp_info(rcv_assoc_resp, u32RcvdAssocRespInfoLen,
&pstrConnectRespInfo);
if (s32Err) {
PRINT_ER("wilc_parse_assoc_resp_info() returned error %d\n", s32Err);
} else {
- strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->u16ConnectStatus;
+ strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->status;
if (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE) {
- PRINT_INFO(HOSTINF_DBG, "Association response received : Successful connection status\n");
- if (pstrConnectRespInfo->pu8RespIEs) {
- strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->u16RespIEsLen;
- strConnectInfo.pu8RespIEs = kmalloc(pstrConnectRespInfo->u16RespIEsLen, GFP_KERNEL);
- memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->pu8RespIEs,
- pstrConnectRespInfo->u16RespIEsLen);
+ if (pstrConnectRespInfo->ies) {
+ strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->ies_len;
+ strConnectInfo.pu8RespIEs = kmalloc(pstrConnectRespInfo->ies_len, GFP_KERNEL);
+ memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->ies,
+ pstrConnectRespInfo->ies_len);
}
}
if (pstrConnectRespInfo) {
- wilc_dealloc_assoc_resp_info(pstrConnectRespInfo);
- pstrConnectRespInfo = NULL;
+ kfree(pstrConnectRespInfo->ies);
+ kfree(pstrConnectRespInfo);
}
}
}
}
if (hif_drv->usr_conn_req.pu8bssid) {
- PRINT_D(HOSTINF_DBG, "Retrieving actual BSSID from AP\n");
memcpy(strConnectInfo.au8bssid, hif_drv->usr_conn_req.pu8bssid, 6);
if ((u8MacStatus == MAC_CONNECTED) &&
(strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
wilc_set_power_mgmt(vif, 0, 0);
- PRINT_D(HOSTINF_DBG, "MAC status : CONNECTED and Connect Status : Successful\n");
hif_drv->hif_state = HOST_IF_CONNECTED;
- PRINT_D(GENERIC_DBG, "Obtaining an IP, Disable Scan\n");
wilc_optaining_ip = true;
mod_timer(&wilc_during_ip_timer,
jiffies + msecs_to_jiffies(10000));
} else {
- PRINT_D(HOSTINF_DBG, "MAC status : %d and Connect Status : %d\n", u8MacStatus, strConnectInfo.u16ConnectStatus);
hif_drv->hif_state = HOST_IF_IDLE;
scan_while_connected = false;
}
hif_drv->usr_conn_req.ies = NULL;
} else if ((u8MacStatus == MAC_DISCONNECTED) &&
(hif_drv->hif_state == HOST_IF_CONNECTED)) {
- PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW\n");
-
memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
if (hif_drv->usr_scan_req.scan_result) {
- PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running OBSS Scan >>\n\n");
del_timer(&hif_drv->scan_timer);
Handle_ScanDone(vif, SCAN_EVENT_ABORTED);
}
} else if ((u8MacStatus == MAC_DISCONNECTED) &&
(hif_drv->usr_scan_req.scan_result)) {
- PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW while scanning\n");
- PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running Scan >>\n\n");
-
del_timer(&hif_drv->scan_timer);
if (hif_drv->usr_scan_req.scan_result)
Handle_ScanDone(vif, SCAN_EVENT_ABORTED);
case WEP:
if (pstrHostIFkeyAttr->action & ADDKEY_AP) {
- PRINT_D(HOSTINF_DBG, "Handling WEP key\n");
- PRINT_D(GENERIC_DBG, "ID Hostint is %d\n", pstrHostIFkeyAttr->attr.wep.index);
strWIDList[0].id = (u16)WID_11I_MODE;
strWIDList[0].type = WID_CHAR;
strWIDList[0].size = sizeof(char);
strWIDList[1].size = sizeof(char);
strWIDList[1].val = (s8 *)&pstrHostIFkeyAttr->attr.wep.auth_type;
- strWIDList[2].id = (u16)WID_KEY_ID;
- strWIDList[2].type = WID_CHAR;
-
- strWIDList[2].val = (s8 *)&pstrHostIFkeyAttr->attr.wep.index;
- strWIDList[2].size = sizeof(char);
-
- pu8keybuf = kmemdup(pstrHostIFkeyAttr->attr.wep.key,
- pstrHostIFkeyAttr->attr.wep.key_len,
+ pu8keybuf = kmalloc(pstrHostIFkeyAttr->attr.wep.key_len + 2,
GFP_KERNEL);
if (pu8keybuf == NULL) {
return -ENOMEM;
}
+ pu8keybuf[0] = pstrHostIFkeyAttr->attr.wep.index;
+ pu8keybuf[1] = pstrHostIFkeyAttr->attr.wep.key_len;
+
+ memcpy(&pu8keybuf[2], pstrHostIFkeyAttr->attr.wep.key,
+ pstrHostIFkeyAttr->attr.wep.key_len);
+
kfree(pstrHostIFkeyAttr->attr.wep.key);
- strWIDList[3].id = (u16)WID_WEP_KEY_VALUE;
- strWIDList[3].type = WID_STR;
- strWIDList[3].size = pstrHostIFkeyAttr->attr.wep.key_len;
- strWIDList[3].val = (s8 *)pu8keybuf;
+ strWIDList[2].id = (u16)WID_WEP_KEY_VALUE;
+ strWIDList[2].type = WID_STR;
+ strWIDList[2].size = pstrHostIFkeyAttr->attr.wep.key_len + 2;
+ strWIDList[2].val = (s8 *)pu8keybuf;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG,
- strWIDList, 4,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG,
+ strWIDList, 3,
+ wilc_get_vif_idx(vif));
kfree(pu8keybuf);
} else if (pstrHostIFkeyAttr->action & ADDKEY) {
- PRINT_D(HOSTINF_DBG, "Handling WEP key\n");
pu8keybuf = kmalloc(pstrHostIFkeyAttr->attr.wep.key_len + 2, GFP_KERNEL);
if (!pu8keybuf) {
PRINT_ER("No buffer to send Key\n");
wid.val = (s8 *)pu8keybuf;
wid.size = pstrHostIFkeyAttr->attr.wep.key_len + 2;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG,
- &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG,
+ &wid, 1,
+ wilc_get_vif_idx(vif));
kfree(pu8keybuf);
} else if (pstrHostIFkeyAttr->action & REMOVEKEY) {
- PRINT_D(HOSTINF_DBG, "Removing key\n");
wid.id = (u16)WID_REMOVE_WEP_KEY;
wid.type = WID_STR;
wid.val = s8idxarray;
wid.size = 1;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG,
- &wid, 1,
- wilc_get_vif_idx(vif));
- } else {
+ result = wilc_send_config_pkt(vif, SET_CFG,
+ &wid, 1,
+ wilc_get_vif_idx(vif));
+ } else if (pstrHostIFkeyAttr->action & DEFAULTKEY) {
wid.id = (u16)WID_KEY_ID;
wid.type = WID_CHAR;
wid.val = (s8 *)&pstrHostIFkeyAttr->attr.wep.index;
wid.size = sizeof(char);
- PRINT_D(HOSTINF_DBG, "Setting default key index\n");
-
- result = wilc_send_config_pkt(vif->wilc, SET_CFG,
- &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG,
+ &wid, 1,
+ wilc_get_vif_idx(vif));
}
up(&hif_drv->sem_test_key_block);
break;
strWIDList[1].val = (s8 *)pu8keybuf;
strWIDList[1].size = RX_MIC_KEY_MSG_LEN;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG,
- strWIDList, 2,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG,
+ strWIDList, 2,
+ wilc_get_vif_idx(vif));
kfree(pu8keybuf);
up(&hif_drv->sem_test_key_block);
} else if (pstrHostIFkeyAttr->action & ADDKEY) {
- PRINT_D(HOSTINF_DBG, "Handling group key(Rx) function\n");
-
pu8keybuf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL);
if (pu8keybuf == NULL) {
PRINT_ER("No buffer to send RxGTK Key\n");
wid.val = (s8 *)pu8keybuf;
wid.size = RX_MIC_KEY_MSG_LEN;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG,
- &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG,
+ &wid, 1,
+ wilc_get_vif_idx(vif));
kfree(pu8keybuf);
up(&hif_drv->sem_test_key_block);
strWIDList[1].val = (s8 *)pu8keybuf;
strWIDList[1].size = PTK_KEY_MSG_LEN + 1;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG,
- strWIDList, 2,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG,
+ strWIDList, 2,
+ wilc_get_vif_idx(vif));
kfree(pu8keybuf);
up(&hif_drv->sem_test_key_block);
} else if (pstrHostIFkeyAttr->action & ADDKEY) {
wid.val = (s8 *)pu8keybuf;
wid.size = PTK_KEY_MSG_LEN;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG,
- &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG,
+ &wid, 1,
+ wilc_get_vif_idx(vif));
kfree(pu8keybuf);
up(&hif_drv->sem_test_key_block);
}
break;
case PMKSA:
-
- PRINT_D(HOSTINF_DBG, "Handling PMKSA key\n");
-
pu8keybuf = kmalloc((pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1, GFP_KERNEL);
if (!pu8keybuf) {
PRINT_ER("No buffer to send PMKSA Key\n");
wid.val = (s8 *)pu8keybuf;
wid.size = (pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
kfree(pu8keybuf);
break;
wid.val = (s8 *)&u16DummyReasonCode;
wid.size = sizeof(char);
- PRINT_D(HOSTINF_DBG, "Sending disconnect request\n");
-
wilc_optaining_ip = false;
wilc_set_power_mgmt(vif, 0, 0);
eth_zero_addr(wilc_connected_ssid);
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
PRINT_ER("Failed to send dissconect config packet\n");
}
if (hif_drv->usr_conn_req.conn_result) {
- if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
- PRINT_D(HOSTINF_DBG, "Upper layer requested termination of connection\n");
+ if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
del_timer(&hif_drv->connect_timer);
- }
hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
NULL,
if (!vif->hif_drv)
return;
if ((vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) ||
- (vif->hif_drv->hif_state == HOST_IF_CONNECTING)) {
- PRINT_D(HOSTINF_DBG, "\n\n<< correcting Supplicant state machine >>\n\n");
+ (vif->hif_drv->hif_state == HOST_IF_CONNECTING))
wilc_disconnect(vif, 1);
- }
}
static s32 Handle_GetChnl(struct wilc_vif *vif)
wid.val = (s8 *)&ch_no;
wid.size = sizeof(char);
- PRINT_D(HOSTINF_DBG, "Getting channel value\n");
-
- result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
PRINT_ER("Failed to get channel number\n");
wid.val = &rssi;
wid.size = sizeof(char);
- PRINT_D(HOSTINF_DBG, "Getting RSSI value\n");
-
- result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
PRINT_ER("Failed to get RSSI value\n");
result = -EFAULT;
wid.val = &link_speed;
wid.size = sizeof(char);
- PRINT_D(HOSTINF_DBG, "Getting LINKSPEED value\n");
-
- result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
PRINT_ER("Failed to get LINKSPEED value\n");
result = -EFAULT;
strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->tx_fail_cnt;
u32WidsCount++;
- result = wilc_send_config_pkt(vif->wilc, GET_CFG, strWIDList,
- u32WidsCount,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, GET_CFG, strWIDList,
+ u32WidsCount,
+ wilc_get_vif_idx(vif));
if (result)
PRINT_ER("Failed to send scan paramters config packet\n");
- up(&hif_sema_wait_response);
+ if (pstrStatistics->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
+ pstrStatistics->link_speed != DEFAULT_LINK_SPEED)
+ wilc_enable_tcp_ack_filter(true);
+ else if (pstrStatistics->link_speed != DEFAULT_LINK_SPEED)
+ wilc_enable_tcp_ack_filter(false);
+
+ if (pstrStatistics != &vif->wilc->dummy_statistics)
+ up(&hif_sema_wait_response);
return 0;
}
PRINT_D(CFG80211_DBG, "SETING STA inactive time\n");
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
PRINT_ER("Failed to SET incative time\n");
wid.val = (s8 *)&inactive_time;
wid.size = sizeof(u32);
- result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
PRINT_ER("Failed to get incative time\n");
struct wid wid;
u8 *pu8CurrByte;
- PRINT_D(HOSTINF_DBG, "Adding BEACON\n");
-
wid.id = (u16)WID_ADD_BEACON;
wid.type = WID_BIN;
wid.size = pstrSetBeaconParam->head_len + pstrSetBeaconParam->tail_len + 16;
memcpy(pu8CurrByte, pstrSetBeaconParam->tail, pstrSetBeaconParam->tail_len);
pu8CurrByte += pstrSetBeaconParam->tail_len;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result)
PRINT_ER("Failed to send add beacon config packet\n");
pu8CurrByte = wid.val;
- PRINT_D(HOSTINF_DBG, "Deleting BEACON\n");
-
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result)
PRINT_ER("Failed to send delete beacon config packet\n");
}
pu8CurrByte = pu8Buffer;
- PRINT_D(HOSTINF_DBG, "Packing STA params\n");
memcpy(pu8CurrByte, pstrStationParam->bssid, ETH_ALEN);
pu8CurrByte += ETH_ALEN;
struct wid wid;
u8 *pu8CurrByte;
- PRINT_D(HOSTINF_DBG, "Handling add station\n");
wid.id = (u16)WID_ADD_STA;
wid.type = WID_BIN;
wid.size = WILC_ADD_STA_LENGTH + pstrStationParam->rates_len;
pu8CurrByte = wid.val;
pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam);
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result != 0)
PRINT_ER("Failed to send add station config packet\n");
wid.type = WID_STR;
wid.size = (pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1;
- PRINT_D(HOSTINF_DBG, "Handling delete station\n");
-
wid.val = kmalloc((pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1, GFP_KERNEL);
if (!wid.val)
goto ERRORHANDLER;
pu8CurrByte += ETH_ALEN;
}
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result)
PRINT_ER("Failed to send add station config packet\n");
wid.type = WID_BIN;
wid.size = ETH_ALEN;
- PRINT_D(HOSTINF_DBG, "Handling delete station\n");
-
wid.val = kmalloc(wid.size, GFP_KERNEL);
if (!wid.val)
goto ERRORHANDLER;
memcpy(pu8CurrByte, pstrDelStaParam->mac_addr, ETH_ALEN);
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result)
PRINT_ER("Failed to send add station config packet\n");
wid.type = WID_BIN;
wid.size = WILC_ADD_STA_LENGTH + pstrStationParam->rates_len;
- PRINT_D(HOSTINF_DBG, "Handling edit station\n");
wid.val = kmalloc(wid.size, GFP_KERNEL);
if (!wid.val)
goto ERRORHANDLER;
pu8CurrByte = wid.val;
pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam);
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result)
PRINT_ER("Failed to send edit station config packet\n");
}
if (hif_drv->usr_scan_req.scan_result) {
- PRINT_INFO(GENERIC_DBG, "Required to remain on chan while scanning return\n");
hif_drv->remain_on_ch_pending = 1;
result = -EBUSY;
goto ERRORHANDLER;
}
if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
- PRINT_INFO(GENERIC_DBG, "Required to remain on chan while connecting return\n");
result = -EBUSY;
goto ERRORHANDLER;
}
if (wilc_optaining_ip || wilc_connecting) {
- PRINT_D(GENERIC_DBG, "[handle_scan]: Don't do obss scan until IP adresss is obtained\n");
result = -EBUSY;
goto ERRORHANDLER;
}
- PRINT_D(HOSTINF_DBG, "Setting channel :%d\n",
- pstrHostIfRemainOnChan->ch);
-
u8remain_on_chan_flag = true;
wid.id = (u16)WID_REMAIN_ON_CHAN;
wid.type = WID_STR;
wid.val[0] = u8remain_on_chan_flag;
wid.val[1] = (s8)pstrHostIfRemainOnChan->ch;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result != 0)
PRINT_ER("Failed to set remain on channel\n");
hif_drv->remain_on_ch_timer.data = (unsigned long)vif;
mod_timer(&hif_drv->remain_on_ch_timer,
jiffies +
- msecs_to_jiffies(pstrHostIfRemainOnChan->u32duration));
+ msecs_to_jiffies(pstrHostIfRemainOnChan->duration));
if (hif_drv->remain_on_ch.ready)
hif_drv->remain_on_ch.ready(hif_drv->remain_on_ch.arg);
struct wid wid;
u8 *pu8CurrByte;
- PRINT_D(HOSTINF_DBG, "Handling frame register : %d FrameType: %d\n",
- pstrHostIfRegisterFrame->reg,
- pstrHostIfRegisterFrame->frame_type);
-
wid.id = (u16)WID_REGISTER_FRAME;
wid.type = WID_STR;
wid.val = kmalloc(sizeof(u16) + 2, GFP_KERNEL);
wid.size = sizeof(u16) + 2;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
PRINT_ER("Failed to frame register config packet\n");
result = -EINVAL;
s32 result = 0;
struct host_if_drv *hif_drv = vif->hif_drv;
- PRINT_D(HOSTINF_DBG, "CANCEL REMAIN ON CHAN\n");
-
if (P2P_LISTEN_STATE) {
u8remain_on_chan_flag = false;
wid.id = (u16)WID_REMAIN_ON_CHAN;
wid.val[0] = u8remain_on_chan_flag;
wid.val[1] = FALSE_FRMWR_CHANNEL;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result != 0) {
PRINT_ER("Failed to set remain on channel\n");
goto _done_;
}
P2P_LISTEN_STATE = 0;
} else {
- PRINT_D(GENERIC_DBG, "Not in listen state\n");
+ netdev_dbg(vif->ndev, "Not in listen state\n");
result = -EFAULT;
}
s8PowerMode = MIN_FAST_PS;
else
s8PowerMode = NO_POWERSAVE;
- PRINT_D(HOSTINF_DBG, "Handling power mgmt to %d\n", s8PowerMode);
+
wid.val = &s8PowerMode;
wid.size = sizeof(char);
- PRINT_D(HOSTINF_DBG, "Handling Power Management\n");
-
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result)
PRINT_ER("Failed to send power management config packet\n");
}
struct wid wid;
u8 *pu8CurrByte;
- PRINT_D(HOSTINF_DBG, "Setup Multicast Filter\n");
-
wid.id = (u16)WID_SETUP_MULTICAST_FILTER;
wid.type = WID_BIN;
wid.size = sizeof(struct set_multicast) + ((strHostIfSetMulti->cnt) * ETH_ALEN);
memcpy(pu8CurrByte, wilc_multicast_mac_addr_list,
((strHostIfSetMulti->cnt) * ETH_ALEN));
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result)
PRINT_ER("Failed to send setup multicast config packet\n");
struct wid wid;
char *ptr = NULL;
- PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x\nTID=%d\n",
- strHostIfBASessionInfo->bssid[0],
- strHostIfBASessionInfo->bssid[1],
- strHostIfBASessionInfo->bssid[2],
- strHostIfBASessionInfo->tid);
-
wid.id = (u16)WID_DEL_ALL_RX_BA;
wid.type = WID_STR;
wid.val = kmalloc(BLOCK_ACK_REQ_SIZE, GFP_KERNEL);
*ptr++ = 0;
*ptr++ = 32;
- result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
- if (result)
- PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n");
+ result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
kfree(wid.val);
return result;
}
+static void handle_set_tx_pwr(struct wilc_vif *vif, u8 tx_pwr)
+{
+ int ret;
+ struct wid wid;
+
+ wid.id = (u16)WID_TX_POWER;
+ wid.type = WID_CHAR;
+ wid.val = &tx_pwr;
+ wid.size = sizeof(char);
+
+ ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
+ if (ret)
+ netdev_err(vif->ndev, "Failed to set TX PWR\n");
+}
+
+static void handle_get_tx_pwr(struct wilc_vif *vif, u8 *tx_pwr)
+{
+ s32 ret = 0;
+ struct wid wid;
+
+ wid.id = (u16)WID_TX_POWER;
+ wid.type = WID_CHAR;
+ wid.val = (s8 *)tx_pwr;
+ wid.size = sizeof(char);
+
+ ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
+ if (ret)
+ netdev_err(vif->ndev, "Failed to get TX PWR\n");
+
+ up(&hif_sema_wait_response);
+}
+
static int hostIFthread(void *pvArg)
{
u32 u32Ret;
while (1) {
wilc_mq_recv(&hif_msg_q, &msg, sizeof(struct host_if_msg), &u32Ret);
vif = msg.vif;
- if (msg.id == HOST_IF_MSG_EXIT) {
- PRINT_D(GENERIC_DBG, "THREAD: Exiting HostIfThread\n");
+ if (msg.id == HOST_IF_MSG_EXIT)
break;
- }
if ((!wilc_initialized)) {
- PRINT_D(GENERIC_DBG, "--WAIT--");
usleep_range(200 * 1000, 200 * 1000);
wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
continue;
if (msg.id == HOST_IF_MSG_CONNECT &&
vif->hif_drv->usr_scan_req.scan_result) {
- PRINT_D(HOSTINF_DBG, "Requeue connect request till scan done received\n");
wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
usleep_range(2 * 1000, 2 * 1000);
continue;
case HOST_IF_MSG_RCVD_SCAN_COMPLETE:
del_timer(&vif->hif_drv->scan_timer);
- PRINT_D(HOSTINF_DBG, "scan completed successfully\n");
if (!wilc_wlan_get_num_conn_ifcs(wilc))
wilc_chip_sleep_manually(wilc);
break;
case HOST_IF_MSG_SCAN_TIMER_FIRED:
- PRINT_D(HOSTINF_DBG, "Scan Timeout\n");
Handle_ScanDone(msg.vif, SCAN_EVENT_ABORTED);
break;
case HOST_IF_MSG_CONNECT_TIMER_FIRED:
- PRINT_D(HOSTINF_DBG, "Connect Timeout\n");
Handle_ConnectTimeout(msg.vif);
break;
break;
case HOST_IF_MSG_SET_IPADDRESS:
- PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_IPADDRESS\n");
handle_set_ip_address(vif,
msg.body.ip_info.ip_addr,
msg.body.ip_info.idx);
break;
case HOST_IF_MSG_GET_IPADDRESS:
- PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_IPADDRESS\n");
handle_get_ip_address(vif, msg.body.ip_info.idx);
break;
break;
case HOST_IF_MSG_REMAIN_ON_CHAN:
- PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_REMAIN_ON_CHAN\n");
Handle_RemainOnChan(msg.vif, &msg.body.remain_on_ch);
break;
case HOST_IF_MSG_REGISTER_FRAME:
- PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_REGISTER_FRAME\n");
Handle_RegisterFrame(msg.vif, &msg.body.reg_frame);
break;
break;
case HOST_IF_MSG_SET_MULTICAST_FILTER:
- PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_MULTICAST_FILTER\n");
Handle_SetMulticastFilter(msg.vif, &msg.body.multicast_info);
break;
Handle_DelAllSta(msg.vif, &msg.body.del_all_sta_info);
break;
+ case HOST_IF_MSG_SET_TX_POWER:
+ handle_set_tx_pwr(msg.vif, msg.body.tx_power.tx_pwr);
+ break;
+
+ case HOST_IF_MSG_GET_TX_POWER:
+ handle_get_tx_pwr(msg.vif, &msg.body.tx_power.tx_pwr);
+ break;
default:
PRINT_ER("[Host Interface] undefined Received Msg ID\n");
break;
}
}
- PRINT_D(HOSTINF_DBG, "Releasing thread exit semaphore\n");
up(&hif_sema_thread);
return 0;
}
return result;
}
-s32 wilc_set_pmkid_info(struct wilc_vif *vif,
- struct host_if_pmkid_attr *pu8PmkidInfoArray)
+int wilc_set_pmkid_info(struct wilc_vif *vif,
+ struct host_if_pmkid_attr *pmkid)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = vif->hif_drv;
- u32 i;
+ int i;
if (!hif_drv) {
PRINT_ER("driver is null\n");
msg.body.key_info.action = ADDKEY;
msg.vif = vif;
- for (i = 0; i < pu8PmkidInfoArray->numpmkid; i++) {
+ for (i = 0; i < pmkid->numpmkid; i++) {
memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].bssid,
- &pu8PmkidInfoArray->pmkidlist[i].bssid, ETH_ALEN);
+ &pmkid->pmkidlist[i].bssid, ETH_ALEN);
memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].pmkid,
- &pu8PmkidInfoArray->pmkidlist[i].pmkid, PMKID_LEN);
+ &pmkid->pmkidlist[i].pmkid, PMKID_LEN);
}
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
return result;
}
-s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress)
+int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_GET_MAC_ADDRESS;
- msg.body.get_mac_info.mac_addr = pu8MacAddress;
+ msg.body.get_mac_info.mac_addr = mac_addr;
msg.vif = vif;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
return result;
}
-s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress)
-{
- s32 result = 0;
- struct host_if_msg msg;
-
- PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", pu8MacAddress[0], pu8MacAddress[1], pu8MacAddress[2]);
-
- memset(&msg, 0, sizeof(struct host_if_msg));
- msg.id = HOST_IF_MSG_SET_MAC_ADDRESS;
- memcpy(msg.body.set_mac_info.mac_addr, pu8MacAddress, ETH_ALEN);
- msg.vif = vif;
-
- result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (result)
- PRINT_ER("Failed to send message queue: Set mac address\n");
-
- return result;
-}
-
-s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid,
- size_t ssidLen, const u8 *pu8IEs, size_t IEsLen,
- wilc_connect_result pfConnectResult, void *pvUserArg,
- u8 u8security, enum AUTHTYPE tenuAuth_type,
- u8 u8channel, void *pJoinParams)
+int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid,
+ size_t ssid_len, const u8 *ies, size_t ies_len,
+ wilc_connect_result connect_result, void *user_arg,
+ u8 security, enum AUTHTYPE auth_type,
+ u8 channel, void *join_params)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = vif->hif_drv;
- if (!hif_drv || !pfConnectResult) {
+ if (!hif_drv || !connect_result) {
PRINT_ER("Driver is null\n");
return -EFAULT;
}
- if (!pJoinParams) {
+ if (!join_params) {
PRINT_ER("Unable to Join - JoinParams is NULL\n");
return -EFAULT;
}
msg.id = HOST_IF_MSG_CONNECT;
- msg.body.con_info.security = u8security;
- msg.body.con_info.auth_type = tenuAuth_type;
- msg.body.con_info.ch = u8channel;
- msg.body.con_info.result = pfConnectResult;
- msg.body.con_info.arg = pvUserArg;
- msg.body.con_info.params = pJoinParams;
+ msg.body.con_info.security = security;
+ msg.body.con_info.auth_type = auth_type;
+ msg.body.con_info.ch = channel;
+ msg.body.con_info.result = connect_result;
+ msg.body.con_info.arg = user_arg;
+ msg.body.con_info.params = join_params;
msg.vif = vif;
- if (pu8bssid) {
- msg.body.con_info.bssid = kmalloc(6, GFP_KERNEL);
- memcpy(msg.body.con_info.bssid, pu8bssid, 6);
+ if (bssid) {
+ msg.body.con_info.bssid = kmemdup(bssid, 6, GFP_KERNEL);
+ if (!msg.body.con_info.bssid)
+ return -ENOMEM;
}
- if (pu8ssid) {
- msg.body.con_info.ssid_len = ssidLen;
- msg.body.con_info.ssid = kmalloc(ssidLen, GFP_KERNEL);
- memcpy(msg.body.con_info.ssid, pu8ssid, ssidLen);
+ if (ssid) {
+ msg.body.con_info.ssid_len = ssid_len;
+ msg.body.con_info.ssid = kmemdup(ssid, ssid_len, GFP_KERNEL);
+ if (!msg.body.con_info.ssid)
+ return -ENOMEM;
}
- if (pu8IEs) {
- msg.body.con_info.ies_len = IEsLen;
- msg.body.con_info.ies = kmalloc(IEsLen, GFP_KERNEL);
- memcpy(msg.body.con_info.ies, pu8IEs, IEsLen);
+ if (ies) {
+ msg.body.con_info.ies_len = ies_len;
+ msg.body.con_info.ies = kmemdup(ies, ies_len, GFP_KERNEL);
+ if (!msg.body.con_info.ies)
+ return -ENOMEM;
}
if (hif_drv->hif_state < HOST_IF_CONNECTING)
hif_drv->hif_state = HOST_IF_CONNECTING;
- else
- PRINT_D(GENERIC_DBG, "Don't set state to 'connecting' : %d\n",
- hif_drv->hif_state);
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
if (result) {
return result;
}
-s32 wilc_flush_join_req(struct wilc_vif *vif)
-{
- s32 result = 0;
- struct host_if_msg msg;
- struct host_if_drv *hif_drv = vif->hif_drv;
-
- if (!join_req)
- return -EFAULT;
-
- if (!hif_drv) {
- PRINT_ER("Driver is null\n");
- return -EFAULT;
- }
-
- msg.id = HOST_IF_MSG_FLUSH_CONNECT;
- msg.vif = vif;
-
- result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (result) {
- PRINT_ER("Failed to send message queue: Flush join request\n");
- return -EFAULT;
- }
-
- return result;
-}
-
-s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode)
+int wilc_disconnect(struct wilc_vif *vif, u16 reason_code)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = vif->hif_drv;
wid.val = pu8AssocRespInfo;
wid.size = u32MaxAssocRespInfoLen;
- result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
+ result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
+ wilc_get_vif_idx(vif));
if (result) {
*pu32RcvdAssocRespInfoLen = 0;
PRINT_ER("Failed to send association response config packet\n");
return 0;
}
-int wilc_wait_msg_queue_idle(void)
-{
- int result = 0;
- struct host_if_msg msg;
-
- memset(&msg, 0, sizeof(struct host_if_msg));
- msg.id = HOST_IF_MSG_Q_IDLE;
- result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (result) {
- PRINT_ER("wilc mq send fail\n");
- result = -EINVAL;
- }
-
- down(&hif_sema_wait_response);
-
- return result;
-}
-
-int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index)
+int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx)
{
int result = 0;
struct host_if_msg msg;
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_SET_WFIDRV_HANDLER;
msg.body.drv.handler = index;
+ msg.body.drv.mac_idx = mac_idx;
msg.vif = vif;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
return result;
}
-s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi)
+int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = vif->hif_drv;
down(&hif_drv->sem_get_rssi);
- if (!ps8Rssi) {
+ if (!rssi_level) {
PRINT_ER("RSS pointer value is null");
return -EFAULT;
}
- *ps8Rssi = rssi;
+ *rssi_level = rssi;
return result;
}
-s32 wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics)
+int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_GET_STATISTICS;
- msg.body.data = (char *)pstrStatistics;
+ msg.body.data = (char *)stats;
msg.vif = vif;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
return -EFAULT;
}
- down(&hif_sema_wait_response);
+ if (stats != &vif->wilc->dummy_statistics)
+ down(&hif_sema_wait_response);
return result;
}
-s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType,
- u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs,
- size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg,
- struct hidden_network *pstrHiddenNetwork)
+int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
+ u8 *ch_freq_list, u8 ch_list_len, const u8 *ies,
+ size_t ies_len, wilc_scan_result scan_result, void *user_arg,
+ struct hidden_network *hidden_network)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = vif->hif_drv;
- if (!hif_drv || !ScanResult) {
- PRINT_ER("hif_drv or ScanResult = NULL\n");
+ if (!hif_drv || !scan_result) {
+ PRINT_ER("hif_drv or scan_result = NULL\n");
return -EFAULT;
}
msg.id = HOST_IF_MSG_SCAN;
- if (pstrHiddenNetwork) {
- msg.body.scan_info.hidden_network.pstrHiddenNetworkInfo = pstrHiddenNetwork->pstrHiddenNetworkInfo;
- msg.body.scan_info.hidden_network.u8ssidnum = pstrHiddenNetwork->u8ssidnum;
-
- } else
- PRINT_D(HOSTINF_DBG, "pstrHiddenNetwork IS EQUAL TO NULL\n");
+ if (hidden_network) {
+ msg.body.scan_info.hidden_network.net_info = hidden_network->net_info;
+ msg.body.scan_info.hidden_network.n_ssids = hidden_network->n_ssids;
+ }
msg.vif = vif;
- msg.body.scan_info.src = u8ScanSource;
- msg.body.scan_info.type = u8ScanType;
- msg.body.scan_info.result = ScanResult;
- msg.body.scan_info.arg = pvUserArg;
-
- msg.body.scan_info.ch_list_len = u8ChnlListLen;
- msg.body.scan_info.ch_freq_list = kmalloc(u8ChnlListLen, GFP_KERNEL);
- memcpy(msg.body.scan_info.ch_freq_list, pu8ChnlFreqList, u8ChnlListLen);
+ msg.body.scan_info.src = scan_source;
+ msg.body.scan_info.type = scan_type;
+ msg.body.scan_info.result = scan_result;
+ msg.body.scan_info.arg = user_arg;
+
+ msg.body.scan_info.ch_list_len = ch_list_len;
+ msg.body.scan_info.ch_freq_list = kmemdup(ch_freq_list,
+ ch_list_len,
+ GFP_KERNEL);
+ if (!msg.body.scan_info.ch_freq_list)
+ return -ENOMEM;
- msg.body.scan_info.ies_len = IEsLen;
- msg.body.scan_info.ies = kmalloc(IEsLen, GFP_KERNEL);
- memcpy(msg.body.scan_info.ies, pu8IEs, IEsLen);
+ msg.body.scan_info.ies_len = ies_len;
+ msg.body.scan_info.ies = kmemdup(ies, ies_len, GFP_KERNEL);
+ if (!msg.body.scan_info.ies)
+ return -ENOMEM;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
if (result) {
return -EINVAL;
}
- PRINT_D(HOSTINF_DBG, ">> Starting the SCAN timer\n");
hif_drv->scan_timer.data = (unsigned long)vif;
mod_timer(&hif_drv->scan_timer,
jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT));
return result;
}
-s32 wilc_hif_set_cfg(struct wilc_vif *vif,
- struct cfg_param_val *pstrCfgParamVal)
+int wilc_hif_set_cfg(struct wilc_vif *vif,
+ struct cfg_param_val *cfg_param)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = vif->hif_drv;
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_CFG_PARAMS;
- msg.body.cfg_info.cfg_attr_info = *pstrCfgParamVal;
+ msg.body.cfg_info.cfg_attr_info = *cfg_param;
msg.vif = vif;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
return;
}
- if (vif->hif_drv->hif_state == HOST_IF_CONNECTED) {
- s32 result = 0;
- struct host_if_msg msg;
-
- memset(&msg, 0, sizeof(struct host_if_msg));
-
- msg.id = HOST_IF_MSG_GET_RSSI;
- msg.vif = vif;
+ if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
+ wilc_get_statistics(vif, &vif->wilc->dummy_statistics);
- result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (result) {
- PRINT_ER("Failed to send get host channel param's message queue ");
- return;
- }
- }
periodic_rssi.data = (unsigned long)vif;
mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
}
-s32 wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
+int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
{
- s32 result = 0;
+ int result = 0;
struct host_if_drv *hif_drv;
struct wilc_vif *vif;
struct wilc *wilc;
vif = netdev_priv(dev);
wilc = vif->wilc;
- PRINT_D(HOSTINF_DBG, "Initializing host interface for client %d\n", clients_count + 1);
-
scan_while_connected = false;
sema_init(&hif_sema_wait_response, 0);
wilc_optaining_ip = false;
- PRINT_D(HOSTINF_DBG, "Global handle pointer value=%p\n", hif_drv);
if (clients_count == 0) {
sema_init(&hif_sema_thread, 0);
sema_init(&hif_sema_driver, 0);
sema_init(&hif_drv->sem_get_chnl, 0);
sema_init(&hif_drv->sem_inactive_time, 0);
- PRINT_D(HOSTINF_DBG, "INIT: CLIENT COUNT %d\n", clients_count);
-
if (clients_count == 0) {
result = wilc_mq_create(&hif_msg_q);
hif_drv->p2p_timeout = 0;
- PRINT_INFO(HOSTINF_DBG, "Initialization values, Site survey value: %d\n Scan source: %d\n Active scan time: %d\n Passive scan time: %d\nCurrent tx Rate = %d\n",
- hif_drv->cfg_values.site_survey_enabled,
- hif_drv->cfg_values.scan_source,
- hif_drv->cfg_values.active_scan_time,
- hif_drv->cfg_values.passive_scan_time,
- hif_drv->cfg_values.curr_tx_rate);
-
up(&hif_drv->sem_cfg_values);
clients_count++;
return result;
}
-s32 wilc_deinit(struct wilc_vif *vif)
+int wilc_deinit(struct wilc_vif *vif)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = vif->hif_drv;
if (!hif_drv) {
PRINT_ER("hif_drv = NULL\n");
- return 0;
+ return -EFAULT;
}
down(&hif_sema_deinit);
terminated_handle = hif_drv;
- PRINT_D(HOSTINF_DBG, "De-initializing host interface for client %d\n", clients_count);
-
- if (del_timer_sync(&hif_drv->scan_timer))
- PRINT_D(HOSTINF_DBG, ">> Scan timer is active\n");
-
- if (del_timer_sync(&hif_drv->connect_timer))
- PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n");
-
- if (del_timer_sync(&periodic_rssi))
- PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n");
+ del_timer_sync(&hif_drv->scan_timer);
+ del_timer_sync(&hif_drv->connect_timer);
+ del_timer_sync(&periodic_rssi);
del_timer_sync(&hif_drv->remain_on_ch_timer);
- wilc_set_wfi_drv_handler(vif, 0);
+ wilc_set_wfi_drv_handler(vif, 0, 0);
down(&hif_sema_driver);
if (hif_drv->usr_scan_req.scan_result) {
memset(&msg, 0, sizeof(struct host_if_msg));
if (clients_count == 1) {
- if (del_timer_sync(&periodic_rssi))
- PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n");
-
+ del_timer_sync(&periodic_rssi);
msg.id = HOST_IF_MSG_EXIT;
msg.vif = vif;
}
hif_drv = vif->hif_drv;
- PRINT_D(HOSTINF_DBG, "General asynchronous info packet received\n");
if (!hif_drv || hif_drv == terminated_handle) {
- PRINT_D(HOSTINF_DBG, "Wifi driver handler is equal to NULL\n");
up(&hif_sema_deinit);
return;
}
return;
hif_drv = vif->hif_drv;
- PRINT_D(GENERIC_DBG, "Scan notification received %p\n", hif_drv);
-
if (!hif_drv || hif_drv == terminated_handle)
return;
return;
}
-s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID,
- u32 u32duration, u16 chan,
- wilc_remain_on_chan_expired RemainOnChanExpired,
- wilc_remain_on_chan_ready RemainOnChanReady,
- void *pvUserArg)
+int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
+ u32 duration, u16 chan,
+ wilc_remain_on_chan_expired expired,
+ wilc_remain_on_chan_ready ready,
+ void *user_arg)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = vif->hif_drv;
msg.id = HOST_IF_MSG_REMAIN_ON_CHAN;
msg.body.remain_on_ch.ch = chan;
- msg.body.remain_on_ch.expired = RemainOnChanExpired;
- msg.body.remain_on_ch.ready = RemainOnChanReady;
- msg.body.remain_on_ch.arg = pvUserArg;
- msg.body.remain_on_ch.u32duration = u32duration;
- msg.body.remain_on_ch.id = u32SessionID;
+ msg.body.remain_on_ch.expired = expired;
+ msg.body.remain_on_ch.ready = ready;
+ msg.body.remain_on_ch.arg = user_arg;
+ msg.body.remain_on_ch.duration = duration;
+ msg.body.remain_on_ch.id = session_id;
msg.vif = vif;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
return result;
}
-s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID)
+int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = vif->hif_drv;
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_LISTEN_TIMER_FIRED;
msg.vif = vif;
- msg.body.remain_on_ch.id = u32SessionID;
+ msg.body.remain_on_ch.id = session_id;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
if (result)
return result;
}
-s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg)
+int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = vif->hif_drv;
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_REGISTER_FRAME;
- switch (u16FrameType) {
+ switch (frame_type) {
case ACTION:
- PRINT_D(HOSTINF_DBG, "ACTION\n");
msg.body.reg_frame.reg_id = ACTION_FRM_IDX;
break;
case PROBE_REQ:
- PRINT_D(HOSTINF_DBG, "PROBE REQ\n");
msg.body.reg_frame.reg_id = PROBE_REQ_IDX;
break;
default:
- PRINT_D(HOSTINF_DBG, "Not valid frame type\n");
break;
}
- msg.body.reg_frame.frame_type = u16FrameType;
- msg.body.reg_frame.reg = bReg;
+ msg.body.reg_frame.frame_type = frame_type;
+ msg.body.reg_frame.reg = reg;
msg.vif = vif;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
return result;
}
-s32 wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod,
- u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail)
+int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
+ u32 head_len, u8 *head, u32 tail_len, u8 *tail)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
- struct beacon_attr *pstrSetBeaconParam = &msg.body.beacon_info;
+ struct beacon_attr *beacon_info = &msg.body.beacon_info;
struct host_if_drv *hif_drv = vif->hif_drv;
if (!hif_drv) {
memset(&msg, 0, sizeof(struct host_if_msg));
- PRINT_D(HOSTINF_DBG, "Setting adding beacon message queue params\n");
-
msg.id = HOST_IF_MSG_ADD_BEACON;
msg.vif = vif;
- pstrSetBeaconParam->interval = u32Interval;
- pstrSetBeaconParam->dtim_period = u32DTIMPeriod;
- pstrSetBeaconParam->head_len = u32HeadLen;
- pstrSetBeaconParam->head = kmemdup(pu8Head, u32HeadLen, GFP_KERNEL);
- if (!pstrSetBeaconParam->head) {
+ beacon_info->interval = interval;
+ beacon_info->dtim_period = dtim_period;
+ beacon_info->head_len = head_len;
+ beacon_info->head = kmemdup(head, head_len, GFP_KERNEL);
+ if (!beacon_info->head) {
result = -ENOMEM;
goto ERRORHANDLER;
}
- pstrSetBeaconParam->tail_len = u32TailLen;
+ beacon_info->tail_len = tail_len;
- if (u32TailLen > 0) {
- pstrSetBeaconParam->tail = kmemdup(pu8Tail, u32TailLen,
- GFP_KERNEL);
- if (!pstrSetBeaconParam->tail) {
+ if (tail_len > 0) {
+ beacon_info->tail = kmemdup(tail, tail_len, GFP_KERNEL);
+ if (!beacon_info->tail) {
result = -ENOMEM;
goto ERRORHANDLER;
}
} else {
- pstrSetBeaconParam->tail = NULL;
+ beacon_info->tail = NULL;
}
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
ERRORHANDLER:
if (result) {
- kfree(pstrSetBeaconParam->head);
+ kfree(beacon_info->head);
- kfree(pstrSetBeaconParam->tail);
+ kfree(beacon_info->tail);
}
return result;
msg.id = HOST_IF_MSG_DEL_BEACON;
msg.vif = vif;
- PRINT_D(HOSTINF_DBG, "Setting deleting beacon message queue params\n");
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
if (result)
memset(&msg, 0, sizeof(struct host_if_msg));
- PRINT_D(HOSTINF_DBG, "Setting adding station message queue params\n");
-
msg.id = HOST_IF_MSG_ADD_STATION;
msg.vif = vif;
memset(&msg, 0, sizeof(struct host_if_msg));
- PRINT_D(HOSTINF_DBG, "Setting deleting station message queue params\n");
-
msg.id = HOST_IF_MSG_DEL_STATION;
msg.vif = vif;
return result;
}
-s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN])
+int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
- struct del_all_sta *pstrDelAllStationMsg = &msg.body.del_all_sta_info;
+ struct del_all_sta *del_all_sta_info = &msg.body.del_all_sta_info;
struct host_if_drv *hif_drv = vif->hif_drv;
- u8 au8Zero_Buff[ETH_ALEN] = {0};
- u32 i;
- u8 u8AssocNumb = 0;
+ u8 zero_addr[ETH_ALEN] = {0};
+ int i;
+ u8 assoc_sta = 0;
if (!hif_drv) {
PRINT_ER("driver is null\n");
memset(&msg, 0, sizeof(struct host_if_msg));
- PRINT_D(HOSTINF_DBG, "Setting deauthenticating station message queue params\n");
-
msg.id = HOST_IF_MSG_DEL_ALL_STA;
msg.vif = vif;
for (i = 0; i < MAX_NUM_STA; i++) {
- if (memcmp(pu8MacAddr[i], au8Zero_Buff, ETH_ALEN)) {
- memcpy(pstrDelAllStationMsg->del_all_sta[i], pu8MacAddr[i], ETH_ALEN);
+ if (memcmp(mac_addr[i], zero_addr, ETH_ALEN)) {
+ memcpy(del_all_sta_info->del_all_sta[i], mac_addr[i], ETH_ALEN);
PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n",
- pstrDelAllStationMsg->del_all_sta[i][0],
- pstrDelAllStationMsg->del_all_sta[i][1],
- pstrDelAllStationMsg->del_all_sta[i][2],
- pstrDelAllStationMsg->del_all_sta[i][3],
- pstrDelAllStationMsg->del_all_sta[i][4],
- pstrDelAllStationMsg->del_all_sta[i][5]);
- u8AssocNumb++;
+ del_all_sta_info->del_all_sta[i][0],
+ del_all_sta_info->del_all_sta[i][1],
+ del_all_sta_info->del_all_sta[i][2],
+ del_all_sta_info->del_all_sta[i][3],
+ del_all_sta_info->del_all_sta[i][4],
+ del_all_sta_info->del_all_sta[i][5]);
+ assoc_sta++;
}
}
- if (!u8AssocNumb) {
+ if (!assoc_sta) {
PRINT_D(CFG80211_DBG, "NO ASSOCIATED STAS\n");
return result;
}
- pstrDelAllStationMsg->assoc_sta = u8AssocNumb;
+ del_all_sta_info->assoc_sta = assoc_sta;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
if (result)
return result;
}
-s32 wilc_edit_station(struct wilc_vif *vif,
- struct add_sta_param *pstrStaParams)
+int wilc_edit_station(struct wilc_vif *vif,
+ struct add_sta_param *sta_param)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
- struct add_sta_param *pstrAddStationMsg = &msg.body.add_sta_info;
+ struct add_sta_param *add_sta_info = &msg.body.add_sta_info;
struct host_if_drv *hif_drv = vif->hif_drv;
if (!hif_drv) {
return -EFAULT;
}
- PRINT_D(HOSTINF_DBG, "Setting editing station message queue params\n");
-
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_EDIT_STATION;
msg.vif = vif;
- memcpy(pstrAddStationMsg, pstrStaParams, sizeof(struct add_sta_param));
- if (pstrAddStationMsg->rates_len > 0) {
- u8 *rates = kmalloc(pstrAddStationMsg->rates_len, GFP_KERNEL);
-
- if (!rates)
+ memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param));
+ if (add_sta_info->rates_len > 0) {
+ add_sta_info->rates = kmemdup(sta_param->rates,
+ add_sta_info->rates_len,
+ GFP_KERNEL);
+ if (!add_sta_info->rates)
return -ENOMEM;
-
- memcpy(rates, pstrStaParams->rates,
- pstrAddStationMsg->rates_len);
- pstrAddStationMsg->rates = rates;
}
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
return result;
}
-s32 wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout)
+int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
- struct power_mgmt_param *pstrPowerMgmtParam = &msg.body.pwr_mgmt_info;
+ struct power_mgmt_param *pwr_mgmt_info = &msg.body.pwr_mgmt_info;
struct host_if_drv *hif_drv = vif->hif_drv;
- PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n", bIsEnabled);
-
if (!hif_drv) {
PRINT_ER("driver is null\n");
return -EFAULT;
}
- PRINT_D(HOSTINF_DBG, "Setting Power management message queue params\n");
+ if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled)
+ return 0;
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_POWER_MGMT;
msg.vif = vif;
- pstrPowerMgmtParam->enabled = bIsEnabled;
- pstrPowerMgmtParam->timeout = u32Timeout;
+ pwr_mgmt_info->enabled = enabled;
+ pwr_mgmt_info->timeout = timeout;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
if (result)
return result;
}
-s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled,
- u32 u32count)
+int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled,
+ u32 count)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
- struct set_multicast *pstrMulticastFilterParam = &msg.body.multicast_info;
+ struct set_multicast *multicast_filter_param = &msg.body.multicast_info;
struct host_if_drv *hif_drv = vif->hif_drv;
if (!hif_drv) {
return -EFAULT;
}
- PRINT_D(HOSTINF_DBG, "Setting Multicast Filter params\n");
-
memset(&msg, 0, sizeof(struct host_if_msg));
msg.id = HOST_IF_MSG_SET_MULTICAST_FILTER;
msg.vif = vif;
- pstrMulticastFilterParam->enabled = bIsEnabled;
- pstrMulticastFilterParam->cnt = u32count;
+ multicast_filter_param->enabled = enabled;
+ multicast_filter_param->cnt = count;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
if (result)
return result;
}
-static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo)
+static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo)
{
struct join_bss_param *pNewJoinBssParam = NULL;
u8 *pu8IEs;
u8 authTotalCount = 0;
u8 i, j;
- pu8IEs = ptstrNetworkInfo->pu8IEs;
- u16IEsLen = ptstrNetworkInfo->u16IEsLen;
+ pu8IEs = ptstrNetworkInfo->ies;
+ u16IEsLen = ptstrNetworkInfo->ies_len;
pNewJoinBssParam = kzalloc(sizeof(struct join_bss_param), GFP_KERNEL);
if (pNewJoinBssParam) {
- pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod;
- pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod;
- pNewJoinBssParam->cap_info = ptstrNetworkInfo->u16CapInfo;
- memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6);
- memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->au8ssid, ptstrNetworkInfo->u8SsidLen + 1);
- pNewJoinBssParam->ssid_len = ptstrNetworkInfo->u8SsidLen;
+ pNewJoinBssParam->dtim_period = ptstrNetworkInfo->dtim_period;
+ pNewJoinBssParam->beacon_period = ptstrNetworkInfo->beacon_period;
+ pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info;
+ memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->bssid, 6);
+ memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->ssid,
+ ptstrNetworkInfo->ssid_len + 1);
+ pNewJoinBssParam->ssid_len = ptstrNetworkInfo->ssid_len;
memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3);
memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3);
(pu8IEs[index + 5] == 0x09) && (pu8IEs[index + 6] == 0x0c)) {
u16 u16P2P_count;
- pNewJoinBssParam->tsf = ptstrNetworkInfo->u32Tsf;
+ pNewJoinBssParam->tsf = ptstrNetworkInfo->tsf_lo;
pNewJoinBssParam->noa_enabled = 1;
pNewJoinBssParam->idx = pu8IEs[index + 9];
pNewJoinBssParam->opp_enabled = 0;
}
- PRINT_D(GENERIC_DBG, "P2P Dump\n");
- for (i = 0; i < pu8IEs[index + 7]; i++)
- PRINT_D(GENERIC_DBG, " %x\n", pu8IEs[index + 9 + i]);
-
pNewJoinBssParam->cnt = pu8IEs[index + 11];
u16P2P_count = index + 12;
return (void *)pNewJoinBssParam;
}
-void wilc_free_join_params(void *pJoinParams)
+int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
{
- if ((struct bss_param *)pJoinParams)
- kfree((struct bss_param *)pJoinParams);
- else
- PRINT_ER("Unable to FREE null pointer\n");
-}
-
-s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID)
-{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
- struct ba_session_info *pBASessionInfo = &msg.body.session_info;
struct host_if_drv *hif_drv = vif->hif_drv;
if (!hif_drv) {
memset(&msg, 0, sizeof(struct host_if_msg));
- msg.id = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS;
+ msg.id = HOST_IF_MSG_SET_IPADDRESS;
- memcpy(pBASessionInfo->bssid, pBSSID, ETH_ALEN);
- pBASessionInfo->tid = TID;
+ msg.body.ip_info.ip_addr = ip_addr;
msg.vif = vif;
+ msg.body.ip_info.idx = idx;
result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
if (result)
PRINT_ER("wilc_mq_send fail\n");
- down(&hif_sema_wait_response);
-
return result;
}
-s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx)
+static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
{
- s32 result = 0;
+ int result = 0;
struct host_if_msg msg;
struct host_if_drv *hif_drv = vif->hif_drv;
- return 0;
-
if (!hif_drv) {
PRINT_ER("driver is null\n");
return -EFAULT;
memset(&msg, 0, sizeof(struct host_if_msg));
- msg.id = HOST_IF_MSG_SET_IPADDRESS;
+ msg.id = HOST_IF_MSG_GET_IPADDRESS;
- msg.body.ip_info.ip_addr = u16ipadd;
+ msg.body.ip_info.ip_addr = ip_addr;
msg.vif = vif;
msg.body.ip_info.idx = idx;
return result;
}
-static s32 host_int_get_ipaddress(struct wilc_vif *vif,
- struct host_if_drv *hif_drv,
- u8 *u16ipadd, u8 idx)
+int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
{
- s32 result = 0;
+ int ret = 0;
struct host_if_msg msg;
- if (!hif_drv) {
- PRINT_ER("driver is null\n");
- return -EFAULT;
- }
-
memset(&msg, 0, sizeof(struct host_if_msg));
- msg.id = HOST_IF_MSG_GET_IPADDRESS;
+ msg.id = HOST_IF_MSG_SET_TX_POWER;
+ msg.body.tx_power.tx_pwr = tx_power;
+ msg.vif = vif;
+
+ ret = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (ret)
+ netdev_err(vif->ndev, "wilc_mq_send fail\n");
+
+ return ret;
+}
+
+int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
+{
+ int ret = 0;
+ struct host_if_msg msg;
- msg.body.ip_info.ip_addr = u16ipadd;
+ memset(&msg, 0, sizeof(struct host_if_msg));
+
+ msg.id = HOST_IF_MSG_GET_TX_POWER;
msg.vif = vif;
- msg.body.ip_info.idx = idx;
- result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
- if (result)
- PRINT_ER("wilc_mq_send fail\n");
+ ret = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg));
+ if (ret)
+ netdev_err(vif->ndev, "Failed to get TX PWR\n");
- return result;
+ down(&hif_sema_wait_response);
+ *tx_power = msg.body.tx_power.tx_pwr;
+
+ return ret;
}
PMKSA,
};
-typedef void (*wilc_scan_result)(enum scan_event, tstrNetworkInfo *,
- void *, void *);
+typedef void (*wilc_scan_result)(enum scan_event, struct network_info *,
+ void *, void *);
typedef void (*wilc_connect_result)(enum conn_event,
tstrConnectInfo *,
};
struct hidden_net_info {
- u8 *pu8ssid;
- u8 u8ssidlen;
+ u8 *ssid;
+ u8 ssid_len;
};
struct hidden_network {
- struct hidden_net_info *pstrHiddenNetworkInfo;
- u8 u8ssidnum;
+ struct hidden_net_info *net_info;
+ u8 n_ssids;
};
struct user_scan_req {
struct drv_handler {
u32 handler;
+ u8 mac_idx;
};
struct op_mode {
struct remain_ch {
u16 ch;
- u32 u32duration;
+ u32 duration;
wilc_remain_on_chan_expired expired;
wilc_remain_on_chan_ready ready;
void *arg;
u8 index);
int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
u8 index, u8 mode, enum AUTHTYPE auth_type);
-s32 wilc_add_ptk(struct wilc_vif *vif, const u8 *pu8Ptk, u8 u8PtkKeylen,
- const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic,
- u8 mode, u8 u8Ciphermode, u8 u8Idx);
+int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
+ const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
+ u8 mode, u8 cipher_mode, u8 index);
s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac,
u32 *pu32InactiveTime);
-s32 wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *pu8RxGtk, u8 u8GtkKeylen,
- u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC,
- const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode,
- u8 u8Ciphermode);
-s32 wilc_add_tx_gtk(struct host_if_drv *hWFIDrv, u8 u8KeyLen,
- u8 *pu8TxGtk, u8 u8KeyIdx);
-s32 wilc_set_pmkid_info(struct wilc_vif *vif,
- struct host_if_pmkid_attr *pu8PmkidInfoArray);
-s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress);
-s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress);
-int wilc_wait_msg_queue_idle(void);
-s32 wilc_set_start_scan_req(struct host_if_drv *hWFIDrv, u8 scanSource);
-s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid,
- size_t ssidLen, const u8 *pu8IEs, size_t IEsLen,
- wilc_connect_result pfConnectResult, void *pvUserArg,
- u8 u8security, enum AUTHTYPE tenuAuth_type,
- u8 u8channel, void *pJoinParams);
-s32 wilc_flush_join_req(struct wilc_vif *vif);
-s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode);
+int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
+ u8 index, u32 key_rsc_len, const u8 *key_rsc,
+ const u8 *rx_mic, const u8 *tx_mic, u8 mode,
+ u8 cipher_mode);
+int wilc_set_pmkid_info(struct wilc_vif *vif,
+ struct host_if_pmkid_attr *pmkid);
+int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr);
+int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid,
+ size_t ssid_len, const u8 *ies, size_t ies_len,
+ wilc_connect_result connect_result, void *user_arg,
+ u8 security, enum AUTHTYPE auth_type,
+ u8 channel, void *join_params);
+int wilc_disconnect(struct wilc_vif *vif, u16 reason_code);
int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel);
-s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi);
-s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType,
- u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs,
- size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg,
- struct hidden_network *pstrHiddenNetwork);
-s32 wilc_hif_set_cfg(struct wilc_vif *vif,
- struct cfg_param_val *pstrCfgParamVal);
-s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv);
-s32 wilc_deinit(struct wilc_vif *vif);
-s32 wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod,
- u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail);
+int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level);
+int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
+ u8 *ch_freq_list, u8 ch_list_len, const u8 *ies,
+ size_t ies_len, wilc_scan_result scan_result, void *user_arg,
+ struct hidden_network *hidden_network);
+int wilc_hif_set_cfg(struct wilc_vif *vif,
+ struct cfg_param_val *cfg_param);
+int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler);
+int wilc_deinit(struct wilc_vif *vif);
+int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
+ u32 head_len, u8 *head, u32 tail_len, u8 *tail);
int wilc_del_beacon(struct wilc_vif *vif);
int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param);
-s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]);
+int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]);
int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr);
-s32 wilc_edit_station(struct wilc_vif *vif,
- struct add_sta_param *pstrStaParams);
-s32 wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout);
-s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled,
- u32 u32count);
-s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx);
-s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID);
-s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID,
- u32 u32duration, u16 chan,
- wilc_remain_on_chan_expired RemainOnChanExpired,
- wilc_remain_on_chan_ready RemainOnChanReady,
- void *pvUserArg);
-s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID);
-s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg);
-int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index);
+int wilc_edit_station(struct wilc_vif *vif,
+ struct add_sta_param *sta_param);
+int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout);
+int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled,
+ u32 count);
+int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx);
+int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id,
+ u32 duration, u16 chan,
+ wilc_remain_on_chan_expired expired,
+ wilc_remain_on_chan_ready ready,
+ void *user_arg);
+int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id);
+int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg);
+int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx);
int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode);
-
-void wilc_free_join_params(void *pJoinParams);
-
-s32 wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics);
+int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats);
void wilc_resolve_disconnect_aberration(struct wilc_vif *vif);
int wilc_get_vif_idx(struct wilc_vif *vif);
+int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power);
+int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power);
extern bool wilc_optaining_ip;
extern u8 wilc_connected_ssid[6];
#include "wilc_wlan_if.h"
#include "wilc_wlan.h"
-
struct wilc_wfi_radiotap_hdr {
struct ieee80211_radiotap_header hdr;
u8 rate;
-} __attribute__((packed));
+} __packed;
struct wilc_wfi_radiotap_cb_hdr {
struct ieee80211_radiotap_header hdr;
u8 rate;
u8 dump;
u16 tx_flags;
-} __attribute__((packed));
+} __packed;
static struct net_device *wilc_wfi_mon; /* global monitor netdev */
PRINT_INFO(HOSTAPD_DBG, "In monitor interface receive function\n");
- if (wilc_wfi_mon == NULL)
+ if (!wilc_wfi_mon)
return;
if (!netif_running(wilc_wfi_mon)) {
pkt_offset = GET_PKT_OFFSET(header);
if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
-
/* hostapd callback mgmt frame */
skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_cb_hdr));
- if (skb == NULL) {
+ if (!skb) {
PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb");
return;
}
memcpy(skb_put(skb, size), buff, size);
- cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr));
+ cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *)skb_push(skb, sizeof(*cb_hdr));
memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
}
} else {
-
skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_hdr));
- if (skb == NULL) {
+ if (!skb) {
PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb");
return;
}
memcpy(skb_put(skb, size), buff, size);
- hdr = (struct wilc_wfi_radiotap_hdr *) skb_push(skb, sizeof(*hdr));
+ hdr = (struct wilc_wfi_radiotap_hdr *)skb_push(skb, sizeof(*hdr));
memset(hdr, 0, sizeof(struct wilc_wfi_radiotap_hdr));
hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_hdr));
(1 << IEEE80211_RADIOTAP_RATE); /* | */
PRINT_INFO(HOSTAPD_DBG, "Presentflags %d\n", hdr->hdr.it_present);
hdr->rate = 5; /* txrate->bitrate / 5; */
-
}
-
-
skb->dev = wilc_wfi_mon;
skb_set_mac_header(skb, 0);
skb->ip_summed = CHECKSUM_UNNECESSARY;
memset(skb->cb, 0, sizeof(skb->cb));
netif_rx(skb);
-
-
}
struct tx_complete_mon_data {
static void mgmt_tx_complete(void *priv, int status)
{
-
struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv;
u8 *buf = pv_data->buff;
-
-
if (status == 1) {
if (INFO || buf[0] == 0x10 || buf[0] == 0xb0)
PRINT_INFO(HOSTAPD_DBG, "Packet sent successfully - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff);
PRINT_INFO(HOSTAPD_DBG, "Couldn't send packet - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff);
}
-
-
/* incase of fully hosting mode, the freeing will be done in response to the cfg packet */
kfree(pv_data->buff);
kfree(pv_data);
}
+
static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len)
{
struct tx_complete_mon_data *mgmt_tx = NULL;
- if (dev == NULL) {
+ if (!dev) {
PRINT_D(HOSTAPD_DBG, "ERROR: dev == NULL\n");
return -EFAULT;
}
netif_stop_queue(dev);
- mgmt_tx = kmalloc(sizeof(struct tx_complete_mon_data), GFP_ATOMIC);
- if (mgmt_tx == NULL) {
- PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
- return -EFAULT;
- }
+ mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_ATOMIC);
+ if (!mgmt_tx)
+ return -ENOMEM;
mgmt_tx->buff = kmalloc(len, GFP_ATOMIC);
- if (mgmt_tx->buff == NULL) {
- PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
+ if (!mgmt_tx->buff) {
kfree(mgmt_tx);
- return -EFAULT;
-
+ return -ENOMEM;
}
mgmt_tx->size = len;
struct sk_buff *skb2;
struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
- if (wilc_wfi_mon == NULL)
+ if (!wilc_wfi_mon)
return -EFAULT;
mon_priv = netdev_priv(wilc_wfi_mon);
- if (mon_priv == NULL) {
+ if (!mon_priv) {
PRINT_ER("Monitor interface private structure is NULL\n");
return -EFAULT;
}
-
rtap_len = ieee80211_get_radiotap_len(skb->data);
if (skb->len < rtap_len) {
PRINT_ER("Error in radiotap header\n");
memcpy(skb_put(skb2, skb->len), skb->data, skb->len);
- cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr));
+ cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *)skb_push(skb2, sizeof(*cb_hdr));
memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
PRINT_INFO(HOSTAPD_DBG, "Skipping the radiotap header\n");
-
-
/* actual deliver of data is device-specific, and not shown here */
PRINT_INFO(HOSTAPD_DBG, "SKB netdevice name = %s\n", skb->dev->name);
PRINT_INFO(HOSTAPD_DBG, "MONITOR real dev name = %s\n", mon_priv->real_ndev->name);
if (!(memcmp(srcAdd, bssid, 6))) {
mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len);
dev_kfree_skb(skb);
- } else
+ } else {
ret = wilc_mac_xmit(skb, mon_priv->real_ndev);
+ }
return ret;
}
*/
struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_device *real_dev)
{
-
-
u32 ret = 0;
struct WILC_WFI_mon_priv *priv;
if (!wilc_wfi_mon) {
PRINT_ER("failed to allocate memory\n");
return NULL;
-
}
wilc_wfi_mon->type = ARPHRD_IEEE80211_RADIOTAP;
return NULL;
}
priv = netdev_priv(wilc_wfi_mon);
- if (priv == NULL) {
+ if (!priv) {
PRINT_ER("private structure is NULL\n");
return NULL;
}
{
bool rollback_lock = false;
- if (wilc_wfi_mon != NULL) {
+ if (wilc_wfi_mon) {
PRINT_D(HOSTAPD_DBG, "In Deinit monitor interface\n");
PRINT_D(HOSTAPD_DBG, "RTNL is being locked\n");
if (rtnl_is_locked()) {
wilc_wfi_mon = NULL;
}
return 0;
-
}
#include <linux/semaphore.h>
-static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr);
+static int dev_state_ev_handler(struct notifier_block *this,
+ unsigned long event, void *ptr);
static struct notifier_block g_dev_notifier = {
.notifier_call = dev_state_ev_handler
};
-static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr)
+static int dev_state_ev_handler(struct notifier_block *this,
+ unsigned long event, void *ptr)
{
struct in_ifaddr *dev_iface = (struct in_ifaddr *)ptr;
struct wilc_priv *priv;
u8 null_ip[4] = {0};
char wlan_dev_name[5] = "wlan0";
- if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) {
- PRINT_D(GENERIC_DBG, "dev_iface = NULL\n");
+ if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev)
return NOTIFY_DONE;
- }
if (memcmp(dev_iface->ifa_label, "wlan0", 5) &&
- memcmp(dev_iface->ifa_label, "p2p0", 4)) {
- PRINT_D(GENERIC_DBG, "Interface is neither WLAN0 nor P2P0\n");
+ memcmp(dev_iface->ifa_label, "p2p0", 4))
return NOTIFY_DONE;
- }
dev = (struct net_device *)dev_iface->ifa_dev->dev;
- if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) {
- PRINT_D(GENERIC_DBG, "No Wireless registerd\n");
+ if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
return NOTIFY_DONE;
- }
+
priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
- if (!priv) {
- PRINT_D(GENERIC_DBG, "No Wireless Priv\n");
+ if (!priv)
return NOTIFY_DONE;
- }
- hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
+
+ hif_drv = (struct host_if_drv *)priv->hif_drv;
vif = netdev_priv(dev);
- if (!vif || !hif_drv) {
- PRINT_D(GENERIC_DBG, "No Wireless Priv\n");
+ if (!vif || !hif_drv)
return NOTIFY_DONE;
- }
-
- PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler +++\n");
switch (event) {
case NETDEV_UP:
- PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_UP %p\n", dev);
-
- PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Obtained ===============\n\n");
-
if (vif->iftype == STATION_MODE || vif->iftype == CLIENT_MODE) {
hif_drv->IFC_UP = 1;
wilc_optaining_ip = false;
del_timer(&wilc_during_ip_timer);
- PRINT_D(GENERIC_DBG, "IP obtained , enable scan\n");
}
if (wilc_enable_ps)
wilc_set_power_mgmt(vif, 1, 0);
- PRINT_D(GENERIC_DBG, "[%s] Up IP\n", dev_iface->ifa_label);
+ netdev_dbg(dev, "[%s] Up IP\n", dev_iface->ifa_label);
ip_addr_buf = (char *)&dev_iface->ifa_address;
- PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n",
- ip_addr_buf[0], ip_addr_buf[1],
- ip_addr_buf[2], ip_addr_buf[3]);
- wilc_setup_ipaddress(vif, ip_addr_buf, vif->u8IfIdx);
+ netdev_dbg(dev, "IP add=%d:%d:%d:%d\n",
+ ip_addr_buf[0], ip_addr_buf[1],
+ ip_addr_buf[2], ip_addr_buf[3]);
+ wilc_setup_ipaddress(vif, ip_addr_buf, vif->idx);
break;
case NETDEV_DOWN:
- PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_DOWN %p\n", dev);
-
- PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Released ===============\n\n");
if (vif->iftype == STATION_MODE || vif->iftype == CLIENT_MODE) {
hif_drv->IFC_UP = 0;
wilc_optaining_ip = false;
wilc_resolve_disconnect_aberration(vif);
- PRINT_D(GENERIC_DBG, "[%s] Down IP\n", dev_iface->ifa_label);
+ netdev_dbg(dev, "[%s] Down IP\n", dev_iface->ifa_label);
ip_addr_buf = null_ip;
- PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n",
- ip_addr_buf[0], ip_addr_buf[1],
- ip_addr_buf[2], ip_addr_buf[3]);
+ netdev_dbg(dev, "IP add=%d:%d:%d:%d\n",
+ ip_addr_buf[0], ip_addr_buf[1],
+ ip_addr_buf[2], ip_addr_buf[3]);
- wilc_setup_ipaddress(vif, ip_addr_buf, vif->u8IfIdx);
+ wilc_setup_ipaddress(vif, ip_addr_buf, vif->idx);
break;
default:
- PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler event=default\n");
- PRINT_INFO(GENERIC_DBG, "[%s] unknown dev event: %lu\n", dev_iface->ifa_label, event);
-
break;
}
vif = netdev_priv(dev);
wilc = vif->wilc;
- PRINT_D(INT_DBG, "Interrupt received UH\n");
if (wilc->close) {
- PRINT_ER("Driver is CLOSING: Can't handle UH interrupt\n");
+ netdev_err(dev, "Can't handle UH interrupt\n");
return IRQ_HANDLED;
}
return IRQ_WAKE_THREAD;
{
struct wilc_vif *vif;
struct wilc *wilc;
+ struct net_device *dev = (struct net_device *)userdata;
vif = netdev_priv(userdata);
wilc = vif->wilc;
if (wilc->close) {
- PRINT_ER("Driver is CLOSING: Can't handle BH interrupt\n");
+ netdev_err(dev, "Can't handle BH interrupt\n");
return IRQ_HANDLED;
}
- PRINT_D(INT_DBG, "Interrupt received BH\n");
wilc_handle_isr(wilc);
return IRQ_HANDLED;
wl->dev_irq_num = gpio_to_irq(wl->gpio);
} else {
ret = -1;
- PRINT_ER("could not obtain gpio for WILC_INTR\n");
+ netdev_err(dev, "could not obtain gpio for WILC_INTR\n");
}
if (ret != -1 && request_threaded_irq(wl->dev_irq_num,
isr_bh_routine,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"WILC_IRQ", dev) < 0) {
- PRINT_ER("Failed to request IRQ for GPIO: %d\n", wl->gpio);
+ netdev_err(dev, "Failed to request IRQ GPIO: %d\n", wl->gpio);
gpio_free(wl->gpio);
ret = -1;
} else {
- PRINT_D(INIT_DBG, "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n",
- wl->dev_irq_num, wl->gpio);
+ netdev_dbg(dev,
+ "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n",
+ wl->dev_irq_num, wl->gpio);
}
return ret;
/* FIXME: replace with mutex_lock or wait_for_completion */
int error = -1;
- PRINT_D(LOCK_DBG, "Locking %p\n", vp);
if (vp)
error = down_timeout((struct semaphore *)vp,
msecs_to_jiffies(timeout));
- else
- PRINT_ER("Failed, mutex is NULL\n");
return error;
}
} else {
wilc->mac_status = status;
}
- } else if (flag == WILC_MAC_INDICATE_SCAN) {
- PRINT_D(GENERIC_DBG, "Scanning ...\n");
}
}
bssid = mac_header + 10;
bssid1 = mac_header + 4;
- for (i = 0; i < wilc->vif_num; i++)
- if (!memcmp(bssid1, wilc->vif[i]->bssid, ETH_ALEN) ||
- !memcmp(bssid, wilc->vif[i]->bssid, ETH_ALEN))
- return wilc->vif[i]->ndev;
-
- PRINT_INFO(INIT_DBG, "Invalide handle\n");
- for (i = 0; i < 25; i++)
- PRINT_D(INIT_DBG, "%02x ", mac_header[i]);
- bssid = mac_header + 18;
- bssid1 = mac_header + 12;
- for (i = 0; i < wilc->vif_num; i++)
- if (!memcmp(bssid1, wilc->vif[i]->bssid, ETH_ALEN) ||
- !memcmp(bssid, wilc->vif[i]->bssid, ETH_ALEN))
- return wilc->vif[i]->ndev;
+ for (i = 0; i < wilc->vif_num; i++) {
+ if (wilc->vif[i]->mode == STATION_MODE)
+ if (!memcmp(bssid, wilc->vif[i]->bssid, ETH_ALEN))
+ return wilc->vif[i]->ndev;
+ if (wilc->vif[i]->mode == AP_MODE)
+ if (!memcmp(bssid1, wilc->vif[i]->bssid, ETH_ALEN))
+ return wilc->vif[i]->ndev;
+ }
- PRINT_INFO(INIT_DBG, "\n");
return NULL;
}
-int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid)
+int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode)
{
int i = 0;
int ret = -1;
for (i = 0; i < wilc->vif_num; i++)
if (wilc->vif[i]->ndev == wilc_netdev) {
memcpy(wilc->vif[i]->bssid, bssid, 6);
+ wilc->vif[i]->mode = mode;
ret = 0;
break;
}
up(&wl->txq_thread_started);
while (1) {
- PRINT_D(TX_DBG, "txq_task Taking a nap :)\n");
down(&wl->txq_event);
- PRINT_D(TX_DBG, "txq_task Who waked me up :$\n");
if (wl->close) {
up(&wl->txq_thread_started);
while (!kthread_should_stop())
schedule();
-
- PRINT_D(TX_DBG, "TX thread stopped\n");
break;
}
- PRINT_D(TX_DBG, "txq_task handle the sending packet and let me go to sleep.\n");
#if !defined USE_TX_BACKOFF_DELAY_IF_NO_BUFFERS
ret = wilc_wlan_handle_txq(dev, &txq_count);
#else
do {
ret = wilc_wlan_handle_txq(dev, &txq_count);
if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
- PRINT_D(TX_DBG, "Waking up queue\n");
-
if (netif_queue_stopped(wl->vif[0]->ndev))
netif_wake_queue(wl->vif[0]->ndev);
if (netif_queue_stopped(wl->vif[1]->ndev))
}
if (ret == WILC_TX_ERR_NO_BUF) {
- do {
- msleep(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight);
- } while (0);
backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP;
if (backoff_weight > TX_BACKOFF_WEIGHT_MAX)
backoff_weight = TX_BACKOFF_WEIGHT_MAX;
return 0;
}
-void wilc_rx_complete(struct wilc *nic)
-{
- PRINT_D(RX_DBG, "RX completed\n");
-}
-
int wilc_wlan_get_firmware(struct net_device *dev)
{
struct wilc_vif *vif;
struct wilc *wilc;
- int ret = 0;
+ int chip_id, ret = 0;
const struct firmware *wilc_firmware;
char *firmware;
vif = netdev_priv(dev);
wilc = vif->wilc;
- if (vif->iftype == AP_MODE) {
- firmware = AP_FIRMWARE;
- } else if (vif->iftype == STATION_MODE) {
- firmware = STA_FIRMWARE;
- } else {
- PRINT_D(INIT_DBG, "Get P2P_CONCURRENCY_FIRMWARE\n");
- firmware = P2P_CONCURRENCY_FIRMWARE;
- }
+ chip_id = wilc_get_chipid(wilc, false);
- if (!vif) {
- PRINT_ER("vif is NULL\n");
- goto _fail_;
- }
+ if (chip_id < 0x1003a0)
+ firmware = FIRMWARE_1002;
+ else
+ firmware = FIRMWARE_1003;
- if (!(&vif->ndev->dev)) {
- PRINT_ER("&vif->ndev->dev is NULL\n");
+ netdev_info(dev, "loading firmware %s\n", firmware);
+
+ if (!(&vif->ndev->dev))
goto _fail_;
- }
if (request_firmware(&wilc_firmware, firmware, wilc->dev) != 0) {
- PRINT_ER("%s - firmare not available\n", firmware);
+ netdev_err(dev, "%s - firmare not available\n", firmware);
ret = -1;
goto _fail_;
}
vif = netdev_priv(dev);
wilc = vif->wilc;
- PRINT_D(INIT_DBG, "Starting Firmware ...\n");
ret = wilc_wlan_start(wilc);
- if (ret < 0) {
- PRINT_ER("Failed to start Firmware\n");
+ if (ret < 0)
return ret;
- }
- PRINT_D(INIT_DBG, "Waiting for Firmware to get ready ...\n");
ret = wilc_lock_timeout(wilc, &wilc->sync_event, 5000);
- if (ret) {
- PRINT_D(INIT_DBG, "Firmware start timed out");
+ if (ret)
return ret;
- }
- PRINT_D(INIT_DBG, "Firmware successfully started\n");
return 0;
}
wilc = vif->wilc;
if (!wilc->firmware) {
- PRINT_ER("Firmware buffer is NULL\n");
+ netdev_err(dev, "Firmware buffer is NULL\n");
return -ENOBUFS;
}
- PRINT_D(INIT_DBG, "Downloading Firmware ...\n");
+
ret = wilc_wlan_firmware_download(wilc, wilc->firmware->data,
wilc->firmware->size);
if (ret < 0)
return ret;
- PRINT_D(INIT_DBG, "Freeing FW buffer ...\n");
- PRINT_D(INIT_DBG, "Releasing firmware\n");
release_firmware(wilc->firmware);
wilc->firmware = NULL;
- PRINT_D(INIT_DBG, "Download Succeeded\n");
+ netdev_dbg(dev, "Download Succeeded\n");
return 0;
}
static int linux_wlan_init_test_config(struct net_device *dev,
- struct wilc *wilc)
+ struct wilc_vif *vif)
{
unsigned char c_val[64];
unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xff};
-
+ struct wilc *wilc = vif->wilc;
struct wilc_priv *priv;
struct host_if_drv *hif_drv;
- PRINT_D(TX_DBG, "Start configuring Firmware\n");
- get_random_bytes(&mac_add[5], 1);
- get_random_bytes(&mac_add[4], 1);
+ netdev_dbg(dev, "Start configuring Firmware\n");
priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
- hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
- PRINT_D(INIT_DBG, "Host = %p\n", hif_drv);
+ hif_drv = (struct host_if_drv *)priv->hif_drv;
+ netdev_dbg(dev, "Host = %p\n", hif_drv);
+ wilc_get_mac_address(vif, mac_add);
- PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n",
- mac_add[0], mac_add[1], mac_add[2],
- mac_add[3], mac_add[4], mac_add[5]);
- wilc_get_chipid(wilc, 0);
+ netdev_dbg(dev, "MAC address is : %pM\n", mac_add);
+ wilc_get_chipid(wilc, false);
*(int *)c_val = 1;
- if (!wilc_wlan_cfg_set(wilc, 1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0))
goto _fail_;
c_val[0] = 0;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_PC_TEST_MODE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_PC_TEST_MODE, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = INFRASTRUCTURE;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_BSS_TYPE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = RATE_AUTO;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = G_MIXED_11B_2_MODE;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11G_OPERATING_MODE, c_val, 1, 0,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, c_val, 1, 0,
0))
goto _fail_;
c_val[0] = 1;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = G_SHORT_PREAMBLE;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_PREAMBLE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = AUTO_PROT;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_PROT_MECH, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = ACTIVE_SCAN;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_SCAN_TYPE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = SITE_SURVEY_OFF;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_SITE_SURVEY, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, c_val, 1, 0, 0))
goto _fail_;
*((int *)c_val) = 0xffff;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_RTS_THRESHOLD, c_val, 2, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, c_val, 2, 0, 0))
goto _fail_;
*((int *)c_val) = 2346;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0))
goto _fail_;
c_val[0] = 0;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_BCAST_SSID, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = 1;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_QOS_ENABLE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = NO_POWERSAVE;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = NO_SECURITY; /* NO_ENCRYPT, 0x79 */
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11I_MODE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = OPEN_SYSTEM;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_AUTH_TYPE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, c_val, 1, 0, 0))
goto _fail_;
strcpy(c_val, "123456790abcdef1234567890");
- if (!wilc_wlan_cfg_set(wilc, 0, WID_WEP_KEY_VALUE, c_val,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_WEP_KEY_VALUE, c_val,
(strlen(c_val) + 1), 0, 0))
goto _fail_;
strcpy(c_val, "12345678");
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11I_PSK, c_val, (strlen(c_val)), 0,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11I_PSK, c_val, (strlen(c_val)), 0,
0))
goto _fail_;
strcpy(c_val, "password");
- if (!wilc_wlan_cfg_set(wilc, 0, WID_1X_KEY, c_val, (strlen(c_val) + 1),
+ if (!wilc_wlan_cfg_set(vif, 0, WID_1X_KEY, c_val, (strlen(c_val) + 1),
0, 0))
goto _fail_;
c_val[1] = 168;
c_val[2] = 1;
c_val[3] = 112;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_1X_SERV_ADDR, c_val, 4, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_1X_SERV_ADDR, c_val, 4, 0, 0))
goto _fail_;
c_val[0] = 3;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = 3;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_DTIM_PERIOD, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = NORMAL_ACK;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_ACK_POLICY, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = 0;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1,
0, 0))
goto _fail_;
c_val[0] = 48;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0,
0))
goto _fail_;
c_val[0] = 28;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0,
0))
goto _fail_;
*((int *)c_val) = 100;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_BEACON_INTERVAL, c_val, 2, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, c_val, 2, 0, 0))
goto _fail_;
c_val[0] = REKEY_DISABLE;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_REKEY_POLICY, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, c_val, 1, 0, 0))
goto _fail_;
*((int *)c_val) = 84600;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_REKEY_PERIOD, c_val, 4, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, c_val, 4, 0, 0))
goto _fail_;
*((int *)c_val) = 500;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_REKEY_PACKET_COUNT, c_val, 4, 0,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, c_val, 4, 0,
0))
goto _fail_;
c_val[0] = 1;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0,
0))
goto _fail_;
c_val[0] = G_SELF_CTS_PROT;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = 1;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_ENABLE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = HT_MIXED_MODE;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_OPERATING_MODE, c_val, 1, 0,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, c_val, 1, 0,
0))
goto _fail_;
c_val[0] = 1;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0,
0))
goto _fail_;
memcpy(c_val, mac_add, 6);
- if (!wilc_wlan_cfg_set(wilc, 0, WID_MAC_ADDR, c_val, 6, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_MAC_ADDR, c_val, 6, 0, 0))
goto _fail_;
c_val[0] = DETECT_PROTECT_REPORT;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1,
0, 0))
goto _fail_;
c_val[0] = RTS_CTS_NONHT_PROT;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = 0;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0,
0))
goto _fail_;
c_val[0] = MIMO_MODE;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_SMPS_MODE, c_val, 1, 0, 0))
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_SMPS_MODE, c_val, 1, 0, 0))
goto _fail_;
c_val[0] = 7;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0,
0))
goto _fail_;
c_val[0] = 1;
- if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1,
+ if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1,
1, 1))
goto _fail_;
if (wl->initialized) {
netdev_info(dev, "Deinitializing wilc1000...\n");
- PRINT_D(INIT_DBG, "Disabling IRQ\n");
if (!wl->dev_irq_num &&
wl->hif_func->disable_interrupt) {
mutex_lock(&wl->hif_cs);
if (&wl->txq_event)
up(&wl->txq_event);
- PRINT_D(INIT_DBG, "Deinitializing Threads\n");
wlan_deinitialize_threads(dev);
-
- PRINT_D(INIT_DBG, "Deinitializing IRQ\n");
deinit_irq(dev);
wilc_wlan_stop(wl);
-
- PRINT_D(INIT_DBG, "Deinitializing WILC Wlan\n");
wilc_wlan_cleanup(dev);
#if defined(PLAT_ALLWINNER_A20) || defined(PLAT_ALLWINNER_A23) || defined(PLAT_ALLWINNER_A31)
if (!wl->dev_irq_num &&
wl->hif_func->disable_interrupt) {
-
- PRINT_D(INIT_DBG, "Disabling IRQ 2\n");
-
mutex_lock(&wl->hif_cs);
wl->hif_func->disable_interrupt(wl);
mutex_unlock(&wl->hif_cs);
}
#endif
-
- PRINT_D(INIT_DBG, "Deinitializing Locks\n");
wlan_deinit_locks(dev);
wl->initialized = false;
- PRINT_D(INIT_DBG, "wilc1000 deinitialization Done\n");
-
+ netdev_dbg(dev, "wilc1000 deinitialization Done\n");
} else {
- PRINT_D(INIT_DBG, "wilc1000 is not initialized\n");
+ netdev_dbg(dev, "wilc1000 is not initialized\n");
}
}
vif = netdev_priv(dev);
wl = vif->wilc;
- PRINT_D(INIT_DBG, "Initializing Locks ...\n");
-
mutex_init(&wl->hif_cs);
mutex_init(&wl->rxq_cs);
vif = netdev_priv(dev);
wilc = vif->wilc;
- PRINT_D(INIT_DBG, "De-Initializing Locks\n");
-
if (&wilc->hif_cs)
mutex_destroy(&wilc->hif_cs);
vif = netdev_priv(dev);
wilc = vif->wilc;
- PRINT_D(INIT_DBG, "Initializing Threads ...\n");
- PRINT_D(INIT_DBG, "Creating kthread for transmission\n");
wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev,
"K_TXQ_TASK");
if (!wilc->txq_thread) {
- PRINT_ER("couldn't create TXQ thread\n");
+ netdev_err(dev, "couldn't create TXQ thread\n");
wilc->close = 0;
return -ENOBUFS;
}
{
struct wilc_vif *vif;
struct wilc *wl;
+
vif = netdev_priv(dev);
wl = vif->wilc;
wl->close = 1;
- PRINT_D(INIT_DBG, "Deinitializing Threads\n");
if (&wl->txq_event)
up(&wl->txq_event);
ret = wilc_wlan_init(dev);
if (ret < 0) {
- PRINT_ER("Initializing WILC_Wlan FAILED\n");
ret = -EIO;
goto _fail_locks_;
}
if (wl->gpio >= 0 && init_irq(dev)) {
- PRINT_ER("couldn't initialize IRQ\n");
ret = -EIO;
goto _fail_locks_;
}
ret = wlan_initialize_threads(dev);
if (ret < 0) {
- PRINT_ER("Initializing Threads FAILED\n");
ret = -EIO;
goto _fail_wilc_wlan_;
}
if (!wl->dev_irq_num &&
wl->hif_func->enable_interrupt &&
wl->hif_func->enable_interrupt(wl)) {
- PRINT_ER("couldn't initialize IRQ\n");
ret = -EIO;
goto _fail_irq_init_;
}
if (wilc_wlan_get_firmware(dev)) {
- PRINT_ER("Can't get firmware\n");
ret = -EIO;
goto _fail_irq_enable_;
}
ret = wilc1000_firmware_download(dev);
if (ret < 0) {
- PRINT_ER("Failed to download firmware\n");
ret = -EIO;
goto _fail_irq_enable_;
}
ret = linux_wlan_start_firmware(dev);
if (ret < 0) {
- PRINT_ER("Failed to start firmware\n");
ret = -EIO;
goto _fail_irq_enable_;
}
- if (wilc_wlan_cfg_get(wl, 1, WID_FIRMWARE_VERSION, 1, 0)) {
+ if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) {
int size;
- char Firmware_ver[20];
+ char firmware_ver[20];
- size = wilc_wlan_cfg_get_val(
- WID_FIRMWARE_VERSION,
- Firmware_ver, sizeof(Firmware_ver));
- Firmware_ver[size] = '\0';
- PRINT_D(INIT_DBG, "***** Firmware Ver = %s *******\n", Firmware_ver);
+ size = wilc_wlan_cfg_get_val(WID_FIRMWARE_VERSION,
+ firmware_ver,
+ sizeof(firmware_ver));
+ firmware_ver[size] = '\0';
+ netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver);
}
- ret = linux_wlan_init_test_config(dev, wl);
+ ret = linux_wlan_init_test_config(dev, vif);
if (ret < 0) {
- PRINT_ER("Failed to configure firmware\n");
+ netdev_err(dev, "Failed to configure firmware\n");
ret = -EIO;
goto _fail_fw_start_;
}
wilc_wlan_cleanup(dev);
_fail_locks_:
wlan_deinit_locks(dev);
- PRINT_ER("WLAN Iinitialization FAILED\n");
+ netdev_err(dev, "WLAN Iinitialization FAILED\n");
} else {
- PRINT_D(INIT_DBG, "wilc1000 already initialized\n");
+ netdev_dbg(dev, "wilc1000 already initialized\n");
}
return ret;
}
vif = netdev_priv(ndev);
wl = vif->wilc;
- if (!wl|| !wl->dev) {
+ if (!wl || !wl->dev) {
netdev_err(ndev, "wilc1000: SPI device not ready\n");
return -ENODEV;
}
vif = netdev_priv(ndev);
wilc = vif->wilc;
priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy);
- PRINT_D(INIT_DBG, "MAC OPEN[%p]\n", ndev);
+ netdev_dbg(ndev, "MAC OPEN[%p]\n", ndev);
ret = wilc_init_host_int(ndev);
- if (ret < 0) {
- PRINT_ER("Failed to initialize host interface\n");
-
+ if (ret < 0)
return ret;
- }
- PRINT_D(INIT_DBG, "*** re-init ***\n");
ret = wilc1000_wlan_init(ndev, vif);
if (ret < 0) {
- PRINT_ER("Failed to initialize wilc1000\n");
wilc_deinit_host_int(ndev);
return ret;
}
- wilc_set_machw_change_vir_if(ndev, false);
-
- wilc_get_mac_address(vif, mac_add);
- PRINT_D(INIT_DBG, "Mac address: %pM\n", mac_add);
-
for (i = 0; i < wl->vif_num; i++) {
if (ndev == wl->vif[i]->ndev) {
+ if (vif->iftype == AP_MODE) {
+ wilc_set_wfi_drv_handler(vif,
+ wilc_get_vif_idx(vif),
+ 0);
+ } else if (!wilc_wlan_get_num_conn_ifcs(wilc)) {
+ wilc_set_wfi_drv_handler(vif,
+ wilc_get_vif_idx(vif),
+ wilc->open_ifcs);
+ } else {
+ if (memcmp(wilc->vif[i ^ 1]->bssid,
+ wilc->vif[i ^ 1]->src_addr, 6))
+ wilc_set_wfi_drv_handler(vif,
+ wilc_get_vif_idx(vif),
+ 0);
+ else
+ wilc_set_wfi_drv_handler(vif,
+ wilc_get_vif_idx(vif),
+ 1);
+ }
+ wilc_set_operation_mode(vif, vif->iftype);
+
+ wilc_get_mac_address(vif, mac_add);
+ netdev_dbg(ndev, "Mac address: %pM\n", mac_add);
memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN);
+
break;
}
}
memcpy(ndev->dev_addr, wl->vif[i]->src_addr, ETH_ALEN);
if (!is_valid_ether_addr(ndev->dev_addr)) {
- PRINT_ER("Error: Wrong MAC address\n");
+ netdev_err(ndev, "Wrong MAC address\n");
wilc_deinit_host_int(ndev);
wilc1000_wlan_deinit(ndev);
return -EINVAL;
static struct net_device_stats *mac_stats(struct net_device *dev)
{
- struct wilc_vif *vif= netdev_priv(dev);
+ struct wilc_vif *vif = netdev_priv(dev);
return &vif->netstats;
}
priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
vif = netdev_priv(dev);
- hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
-
- if (!dev)
- return;
-
- PRINT_D(INIT_DBG, "Setting Multicast List with count = %d.\n",
- dev->mc.count);
+ hif_drv = (struct host_if_drv *)priv->hif_drv;
- if (dev->flags & IFF_PROMISC) {
- PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets\n");
+ if (dev->flags & IFF_PROMISC)
return;
- }
if ((dev->flags & IFF_ALLMULTI) ||
(dev->mc.count) > WILC_MULTICAST_TABLE_SIZE) {
- PRINT_D(INIT_DBG, "Disable multicast filter, retrive all multicast packets\n");
wilc_setup_multicast_filter(vif, false, 0);
return;
}
if ((dev->mc.count) == 0) {
- PRINT_D(INIT_DBG, "Enable multicast filter, retrive directed packets only.\n");
wilc_setup_multicast_filter(vif, true, 0);
return;
}
netdev_for_each_mc_addr(ha, dev) {
memcpy(wilc_multicast_mac_addr_list[i], ha->addr, ETH_ALEN);
- PRINT_D(INIT_DBG, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i,
- wilc_multicast_mac_addr_list[i][0],
- wilc_multicast_mac_addr_list[i][1],
- wilc_multicast_mac_addr_list[i][2],
- wilc_multicast_mac_addr_list[i][3],
- wilc_multicast_mac_addr_list[i][4],
- wilc_multicast_mac_addr_list[i][5]);
+ netdev_dbg(dev, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i,
+ wilc_multicast_mac_addr_list[i][0],
+ wilc_multicast_mac_addr_list[i][1],
+ wilc_multicast_mac_addr_list[i][2],
+ wilc_multicast_mac_addr_list[i][3],
+ wilc_multicast_mac_addr_list[i][4],
+ wilc_multicast_mac_addr_list[i][5]);
i++;
}
wilc_setup_multicast_filter(vif, true, (dev->mc.count));
-
- return;
}
static void linux_wlan_tx_complete(void *priv, int status)
{
struct tx_complete_data *pv_data = (struct tx_complete_data *)priv;
- if (status == 1)
- PRINT_D(TX_DBG, "Packet sent successfully - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb);
- else
- PRINT_D(TX_DBG, "Couldn't send packet - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb);
dev_kfree_skb(pv_data->skb);
kfree(pv_data);
}
vif = netdev_priv(ndev);
wilc = vif->wilc;
- PRINT_D(TX_DBG, "Sending packet just received from TCP/IP\n");
-
if (skb->dev != ndev) {
- PRINT_ER("Packet not destined to this device\n");
+ netdev_err(ndev, "Packet not destined to this device\n");
return 0;
}
tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
if (!tx_data) {
- PRINT_ER("Failed to allocate memory for tx_data structure\n");
dev_kfree_skb(skb);
netif_wake_queue(ndev);
return 0;
eth_h = (struct ethhdr *)(skb->data);
if (eth_h->h_proto == 0x8e88)
- PRINT_D(INIT_DBG, "EAPOL transmitted\n");
+ netdev_dbg(ndev, "EAPOL transmitted\n");
ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
udp_buf = (char *)ih + sizeof(struct iphdr);
if ((udp_buf[1] == 68 && udp_buf[3] == 67) ||
(udp_buf[1] == 67 && udp_buf[3] == 68))
- PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n",
- udp_buf[248], udp_buf[249], udp_buf[250]);
+ netdev_dbg(ndev, "DHCP Message transmitted, type:%x %x %x\n",
+ udp_buf[248], udp_buf[249], udp_buf[250]);
- PRINT_D(TX_DBG, "Sending packet - Size = %d - Address = %p - SKB = %p\n", tx_data->size, tx_data->buff, tx_data->skb);
- PRINT_D(TX_DBG, "Adding tx packet to TX Queue\n");
vif->netstats.tx_packets++;
vif->netstats.tx_bytes += tx_data->size;
- tx_data->pBssid = wilc->vif[vif->u8IfIdx]->bssid;
+ tx_data->bssid = wilc->vif[vif->idx]->bssid;
queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data,
tx_data->buff, tx_data->size,
linux_wlan_tx_complete);
vif = netdev_priv(ndev);
if (!vif || !vif->ndev || !vif->ndev->ieee80211_ptr ||
- !vif->ndev->ieee80211_ptr->wiphy) {
- PRINT_ER("vif = NULL\n");
+ !vif->ndev->ieee80211_ptr->wiphy)
return 0;
- }
priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy);
wl = vif->wilc;
- if (!priv) {
- PRINT_ER("priv = NULL\n");
+ if (!priv)
return 0;
- }
- hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv;
+ hif_drv = (struct host_if_drv *)priv->hif_drv;
- PRINT_D(GENERIC_DBG, "Mac close\n");
+ netdev_dbg(ndev, "Mac close\n");
- if (!wl) {
- PRINT_ER("wl = NULL\n");
+ if (!wl)
return 0;
- }
- if (!hif_drv) {
- PRINT_ER("hif_drv = NULL\n");
+ if (!hif_drv)
return 0;
- }
- if ((wl->open_ifcs) > 0) {
+ if ((wl->open_ifcs) > 0)
wl->open_ifcs--;
- } else {
- PRINT_ER("ERROR: MAC close called while number of opened interfaces is zero\n");
+ else
return 0;
- }
if (vif->ndev) {
netif_stop_queue(vif->ndev);
}
if (wl->open_ifcs == 0) {
- PRINT_D(GENERIC_DBG, "Deinitializing wilc1000\n");
+ netdev_dbg(ndev, "Deinitializing wilc1000\n");
wl->close = 1;
wilc1000_wlan_deinit(ndev);
WILC_WFI_deinit_mon_interface();
switch (cmd) {
case SIOCSIWPRIV:
{
- struct iwreq *wrq = (struct iwreq *) req;
+ struct iwreq *wrq = (struct iwreq *)req;
size = wrq->u.data.length;
if (strncasecmp(buff, "RSSI", length) == 0) {
priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy);
ret = wilc_get_rssi(vif, &rssi);
- if (ret)
- PRINT_ER("Failed to send get rssi param's message queue ");
- PRINT_INFO(GENERIC_DBG, "RSSI :%d\n", rssi);
+ netdev_info(ndev, "RSSI :%d\n", rssi);
rssi += 5;
snprintf(buff, size, "rssi %d", rssi);
if (copy_to_user(wrq->u.data.pointer, buff, size)) {
- PRINT_ER("%s: failed to copy data to user buffer\n", __func__);
+ netdev_err(ndev, "failed to copy\n");
ret = -EFAULT;
goto done;
}
default:
{
- PRINT_INFO(GENERIC_DBG, "Command - %d - has been received\n", cmd);
+ netdev_info(ndev, "Command - %d - has been received\n", cmd);
ret = -EOPNOTSUPP;
goto done;
}
struct net_device *wilc_netdev;
struct wilc_vif *vif;
+ if (!wilc)
+ return;
+
wilc_netdev = get_if_handler(wilc, buff);
if (!wilc_netdev)
return;
buff_to_send = buff;
skb = dev_alloc_skb(frame_len);
- if (!skb) {
- PRINT_ER("Low memory - packet droped\n");
+ if (!skb)
return;
- }
- if (!wilc || !wilc_netdev)
- PRINT_ER("wilc_netdev in wilc is NULL");
skb->dev = wilc_netdev;
- if (!skb->dev)
- PRINT_ER("skb->dev is NULL\n");
-
memcpy(skb_put(skb, frame_len), buff_to_send, frame_len);
skb->protocol = eth_type_trans(skb, wilc_netdev);
vif->netstats.rx_bytes += frame_len;
skb->ip_summed = CHECKSUM_UNNECESSARY;
stats = netif_rx(skb);
- PRINT_D(RX_DBG, "netif_rx ret value is: %d\n", stats);
+ netdev_dbg(wilc_netdev, "netif_rx ret value is: %d\n", stats);
}
}
release_firmware(wilc->firmware);
if (wilc && (wilc->vif[0]->ndev || wilc->vif[1]->ndev)) {
- wilc_lock_timeout(wilc, &close_exit_sync, 12 * 1000);
+ wilc_lock_timeout(wilc, &close_exit_sync, 5 * 1000);
for (i = 0; i < NUM_CONCURRENT_IFC; i++)
if (wilc->vif[i]->ndev)
for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
ndev = alloc_etherdev(sizeof(struct wilc_vif));
- if (!ndev) {
- PRINT_ER("Failed to allocate ethernet dev\n");
+ if (!ndev)
return -1;
- }
vif = netdev_priv(ndev);
memset(vif, 0, sizeof(struct wilc_vif));
else
strcpy(ndev->name, "p2p%d");
- vif->u8IfIdx = wl->vif_num;
+ vif->idx = wl->vif_num;
vif->wilc = *wilc;
wl->vif[i] = vif;
wl->vif[wl->vif_num]->ndev = ndev;
{
struct wireless_dev *wdev;
+
wdev = wilc_create_wiphy(ndev, dev);
if (dev)
SET_NETDEV_DEV(ndev, dev);
if (!wdev) {
- PRINT_ER("Can't register WILC Wiphy\n");
+ netdev_err(ndev, "Can't register WILC Wiphy\n");
return -1;
}
vif->netstats.tx_bytes = 0;
}
- if (register_netdev(ndev)) {
- PRINT_ER("Device couldn't be registered - %s\n",
- ndev->name);
+ if (register_netdev(ndev))
return -1;
- }
vif->iftype = STATION_MODE;
vif->mac_opened = 0;
#define LINUX_WLAN_COMMON_H
enum debug_region {
- Generic_debug = 0,
- Hostapd_debug,
- Hostinf_debug,
+ Hostapd_debug = 0,
CFG80211_debug,
- Coreconfig_debug,
- Interrupt_debug,
- TX_debug,
- RX_debug,
- Lock_debug,
- Tcp_enhance,
- Spin_debug,
-
Init_debug,
- Bus_debug,
- Mem_debug,
- Firmware_debug,
COMP = 0xFFFFFFFF,
};
-#define GENERIC_DBG (1 << Generic_debug)
#define HOSTAPD_DBG (1 << Hostapd_debug)
-#define HOSTINF_DBG (1 << Hostinf_debug)
-#define CORECONFIG_DBG (1 << Coreconfig_debug)
#define CFG80211_DBG (1 << CFG80211_debug)
-#define INT_DBG (1 << Interrupt_debug)
-#define TX_DBG (1 << TX_debug)
-#define RX_DBG (1 << RX_debug)
-#define LOCK_DBG (1 << Lock_debug)
-#define TCP_ENH (1 << Tcp_enhance)
-#define SPIN_DEBUG (1 << Spin_debug)
#define INIT_DBG (1 << Init_debug)
-#define BUS_DBG (1 << Bus_debug)
-#define MEM_DBG (1 << Mem_debug)
-#define FIRM_DBG (1 << Firmware_debug)
#if defined (WILC_DEBUGFS)
extern atomic_t WILC_REGION;
* --------------------------------------------------------------------------------
*/
-#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | HOSTINF_DBG | CORECONFIG_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG)
+#define DBG_REGION_ALL (HOSTAPD_DBG | CFG80211_DBG | INIT_DBG)
#define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR)
-atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG);
+atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | CFG80211_DBG |
+ HOSTAPD_DBG);
EXPORT_SYMBOL_GPL(WILC_REGION);
atomic_t WILC_DEBUG_LEVEL = ATOMIC_INIT(ERR);
EXPORT_SYMBOL_GPL(WILC_DEBUG_LEVEL);
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
-static ssize_t wilc_debug_region_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
+static ssize_t wilc_debug_region_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
char buffer[128] = {};
int flag;
static struct wilc_debugfs_info_t debugfs_info[] = {
{ "wilc_debug_level", 0666, (DEBUG | ERR), FOPS(NULL, wilc_debug_level_read, wilc_debug_level_write, NULL), },
- { "wilc_debug_region", 0666, (INIT_DBG | GENERIC_DBG | CFG80211_DBG), FOPS(NULL, wilc_debug_region_read, wilc_debug_region_write, NULL), },
+ { "wilc_debug_region", 0666, (INIT_DBG | CFG80211_DBG), FOPS(NULL, wilc_debug_region_read, wilc_debug_region_write, NULL), },
};
static int __init wilc_debugfs_init(void)
* @note copied from FLO glue implementatuion
* @version 1.0
*/
-int wilc_mq_create(WILC_MsgQueueHandle *pHandle)
+int wilc_mq_create(struct message_queue *mq)
{
- spin_lock_init(&pHandle->strCriticalSection);
- sema_init(&pHandle->hSem, 0);
- pHandle->pstrMessageList = NULL;
- pHandle->u32ReceiversCount = 0;
- pHandle->bExiting = false;
+ spin_lock_init(&mq->lock);
+ sema_init(&mq->sem, 0);
+ INIT_LIST_HEAD(&mq->msg_list);
+ mq->recv_count = 0;
+ mq->exiting = false;
return 0;
}
* @note copied from FLO glue implementatuion
* @version 1.0
*/
-int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle)
+int wilc_mq_destroy(struct message_queue *mq)
{
- pHandle->bExiting = true;
+ struct message *msg;
+
+ mq->exiting = true;
/* Release any waiting receiver thread. */
- while (pHandle->u32ReceiversCount > 0) {
- up(&pHandle->hSem);
- pHandle->u32ReceiversCount--;
+ while (mq->recv_count > 0) {
+ up(&mq->sem);
+ mq->recv_count--;
}
- while (pHandle->pstrMessageList) {
- Message *pstrMessge = pHandle->pstrMessageList->pstrNext;
-
- kfree(pHandle->pstrMessageList);
- pHandle->pstrMessageList = pstrMessge;
+ while (!list_empty(&mq->msg_list)) {
+ msg = list_first_entry(&mq->msg_list, struct message, list);
+ list_del(&msg->list);
+ kfree(msg->buf);
}
return 0;
* @note copied from FLO glue implementatuion
* @version 1.0
*/
-int wilc_mq_send(WILC_MsgQueueHandle *pHandle,
- const void *pvSendBuffer, u32 u32SendBufferSize)
+int wilc_mq_send(struct message_queue *mq,
+ const void *send_buf, u32 send_buf_size)
{
unsigned long flags;
- Message *pstrMessage = NULL;
+ struct message *new_msg = NULL;
- if ((!pHandle) || (u32SendBufferSize == 0) || (!pvSendBuffer)) {
- PRINT_ER("pHandle or pvSendBuffer is null\n");
- return -EFAULT;
- }
+ if (!mq || (send_buf_size == 0) || !send_buf)
+ return -EINVAL;
- if (pHandle->bExiting) {
- PRINT_ER("pHandle fail\n");
+ if (mq->exiting)
return -EFAULT;
- }
/* construct a new message */
- pstrMessage = kmalloc(sizeof(Message), GFP_ATOMIC);
- if (!pstrMessage)
+ new_msg = kmalloc(sizeof(*new_msg), GFP_ATOMIC);
+ if (!new_msg)
return -ENOMEM;
- pstrMessage->u32Length = u32SendBufferSize;
- pstrMessage->pstrNext = NULL;
- pstrMessage->pvBuffer = kmemdup(pvSendBuffer, u32SendBufferSize,
- GFP_ATOMIC);
- if (!pstrMessage->pvBuffer) {
- kfree(pstrMessage);
+ new_msg->len = send_buf_size;
+ INIT_LIST_HEAD(&new_msg->list);
+ new_msg->buf = kmemdup(send_buf, send_buf_size, GFP_ATOMIC);
+ if (!new_msg->buf) {
+ kfree(new_msg);
return -ENOMEM;
}
- spin_lock_irqsave(&pHandle->strCriticalSection, flags);
+ spin_lock_irqsave(&mq->lock, flags);
/* add it to the message queue */
- if (!pHandle->pstrMessageList) {
- pHandle->pstrMessageList = pstrMessage;
- } else {
- Message *pstrTailMsg = pHandle->pstrMessageList;
+ list_add_tail(&new_msg->list, &mq->msg_list);
- while (pstrTailMsg->pstrNext)
- pstrTailMsg = pstrTailMsg->pstrNext;
-
- pstrTailMsg->pstrNext = pstrMessage;
- }
+ spin_unlock_irqrestore(&mq->lock, flags);
- spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
-
- up(&pHandle->hSem);
+ up(&mq->sem);
return 0;
}
* @note copied from FLO glue implementatuion
* @version 1.0
*/
-int wilc_mq_recv(WILC_MsgQueueHandle *pHandle,
- void *pvRecvBuffer, u32 u32RecvBufferSize,
- u32 *pu32ReceivedLength)
+int wilc_mq_recv(struct message_queue *mq,
+ void *recv_buf, u32 recv_buf_size, u32 *recv_len)
{
- Message *pstrMessage;
+ struct message *msg;
unsigned long flags;
- if ((!pHandle) || (u32RecvBufferSize == 0)
- || (!pvRecvBuffer) || (!pu32ReceivedLength)) {
- PRINT_ER("pHandle or pvRecvBuffer is null\n");
+ if (!mq || (recv_buf_size == 0) || !recv_buf || !recv_len)
return -EINVAL;
- }
- if (pHandle->bExiting) {
- PRINT_ER("pHandle fail\n");
+ if (mq->exiting)
return -EFAULT;
- }
-
- spin_lock_irqsave(&pHandle->strCriticalSection, flags);
- pHandle->u32ReceiversCount++;
- spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
- down(&pHandle->hSem);
-
- if (pHandle->bExiting) {
- PRINT_ER("pHandle fail\n");
- return -EFAULT;
- }
+ spin_lock_irqsave(&mq->lock, flags);
+ mq->recv_count++;
+ spin_unlock_irqrestore(&mq->lock, flags);
- spin_lock_irqsave(&pHandle->strCriticalSection, flags);
+ down(&mq->sem);
+ spin_lock_irqsave(&mq->lock, flags);
- pstrMessage = pHandle->pstrMessageList;
- if (!pstrMessage) {
- spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
- PRINT_ER("pstrMessage is null\n");
+ if (list_empty(&mq->msg_list)) {
+ spin_unlock_irqrestore(&mq->lock, flags);
+ up(&mq->sem);
return -EFAULT;
}
/* check buffer size */
- if (u32RecvBufferSize < pstrMessage->u32Length) {
- spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
- up(&pHandle->hSem);
- PRINT_ER("u32RecvBufferSize overflow\n");
+ msg = list_first_entry(&mq->msg_list, struct message, list);
+ if (recv_buf_size < msg->len) {
+ spin_unlock_irqrestore(&mq->lock, flags);
+ up(&mq->sem);
return -EOVERFLOW;
}
/* consume the message */
- pHandle->u32ReceiversCount--;
- memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length);
- *pu32ReceivedLength = pstrMessage->u32Length;
+ mq->recv_count--;
+ memcpy(recv_buf, msg->buf, msg->len);
+ *recv_len = msg->len;
- pHandle->pstrMessageList = pstrMessage->pstrNext;
+ list_del(&msg->list);
- kfree(pstrMessage->pvBuffer);
- kfree(pstrMessage);
+ kfree(msg->buf);
+ kfree(msg);
- spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
+ spin_unlock_irqrestore(&mq->lock, flags);
return 0;
}
#ifndef __WILC_MSG_QUEUE_H__
#define __WILC_MSG_QUEUE_H__
-/*!
- * @file wilc_msgqueue.h
- * @brief Message Queue OS wrapper functionality
- * @author syounan
- * @sa wilc_oswrapper.h top level OS wrapper file
- * @date 30 Aug 2010
- * @version 1.0
- */
-
#include <linux/semaphore.h>
-
-/* Message Queue type is a structure */
-typedef struct __Message_struct {
- void *pvBuffer;
- u32 u32Length;
- struct __Message_struct *pstrNext;
-} Message;
-
-typedef struct __MessageQueue_struct {
- struct semaphore hSem;
- spinlock_t strCriticalSection;
- bool bExiting;
- u32 u32ReceiversCount;
- Message *pstrMessageList;
-} WILC_MsgQueueHandle;
-
-/*!
- * @brief Creates a new Message queue
- * @details Creates a new Message queue, if the feature
- * CONFIG_WILC_MSG_QUEUE_IPC_NAME is enabled and pstrAttrs->pcName
- * is not Null, then this message queue can be used for IPC with
- * any other message queue having the same name in the system
- * @param[in,out] pHandle handle to the message queue object
- * @param[in] pstrAttrs Optional attributes, NULL for default
- * @return Error code indicating success/failure
- * @author syounan
- * @date 30 Aug 2010
- * @version 1.0
- */
-int wilc_mq_create(WILC_MsgQueueHandle *pHandle);
-
-/*!
- * @brief Sends a message
- * @details Sends a message, this API will block until the message is
- * actually sent or until it is timedout (as long as the feature
- * CONFIG_WILC_MSG_QUEUE_TIMEOUT is enabled and pstrAttrs->u32Timeout
- * is not set to WILC_OS_INFINITY), zero timeout is a valid value
- * @param[in] pHandle handle to the message queue object
- * @param[in] pvSendBuffer pointer to the data to send
- * @param[in] u32SendBufferSize the size of the data to send
- * @param[in] pstrAttrs Optional attributes, NULL for default
- * @return Error code indicating success/failure
- * @author syounan
- * @date 30 Aug 2010
- * @version 1.0
- */
-int wilc_mq_send(WILC_MsgQueueHandle *pHandle,
- const void *pvSendBuffer, u32 u32SendBufferSize);
-
-/*!
- * @brief Receives a message
- * @details Receives a message, this API will block until a message is
- * received or until it is timedout (as long as the feature
- * CONFIG_WILC_MSG_QUEUE_TIMEOUT is enabled and pstrAttrs->u32Timeout
- * is not set to WILC_OS_INFINITY), zero timeout is a valid value
- * @param[in] pHandle handle to the message queue object
- * @param[out] pvRecvBuffer pointer to a buffer to fill with the received message
- * @param[in] u32RecvBufferSize the size of the receive buffer
- * @param[out] pu32ReceivedLength the length of received data
- * @param[in] pstrAttrs Optional attributes, NULL for default
- * @return Error code indicating success/failure
- * @author syounan
- * @date 30 Aug 2010
- * @version 1.0
- */
-int wilc_mq_recv(WILC_MsgQueueHandle *pHandle,
- void *pvRecvBuffer, u32 u32RecvBufferSize,
- u32 *pu32ReceivedLength);
-
-/*!
- * @brief Destroys an existing Message queue
- * @param[in] pHandle handle to the message queue object
- * @param[in] pstrAttrs Optional attributes, NULL for default
- * @return Error code indicating success/failure
- * @author syounan
- * @date 30 Aug 2010
- * @version 1.0
- */
-int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle);
+#include <linux/list.h>
+
+struct message {
+ void *buf;
+ u32 len;
+ struct list_head list;
+};
+
+struct message_queue {
+ struct semaphore sem;
+ spinlock_t lock;
+ bool exiting;
+ u32 recv_count;
+ struct list_head msg_list;
+};
+
+int wilc_mq_create(struct message_queue *mq);
+int wilc_mq_send(struct message_queue *mq,
+ const void *send_buf, u32 send_buf_size);
+int wilc_mq_recv(struct message_queue *mq,
+ void *recv_buf, u32 recv_buf_size, u32 *recv_len);
+int wilc_mq_destroy(struct message_queue *mq);
#endif
static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data);
static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data);
+static int sdio_init(struct wilc *wilc, bool resume);
static void wilc_sdio_interrupt(struct sdio_func *func)
{
wilc_netdev_cleanup(sdio_get_drvdata(func));
}
+static int sdio_reset(struct wilc *wilc)
+{
+ sdio_cmd52_t cmd;
+ int ret;
+ struct sdio_func *func = dev_to_sdio_func(wilc->dev);
+
+ cmd.read_write = 1;
+ cmd.function = 0;
+ cmd.raw = 0;
+ cmd.address = 0x6;
+ cmd.data = 0x8;
+ ret = wilc_sdio_cmd52(wilc, &cmd);
+ if (ret) {
+ dev_err(&func->dev, "Fail cmd 52, reset cmd ...\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int wilc_sdio_suspend(struct device *dev)
+{
+ struct sdio_func *func = dev_to_sdio_func(dev);
+ struct wilc *wilc = sdio_get_drvdata(func);
+ int ret;
+
+ dev_info(dev, "sdio suspend\n");
+ chip_wakeup(wilc);
+
+ if (!wilc->suspend_event) {
+ wilc_chip_sleep_manually(wilc);
+ } else {
+ host_sleep_notify(wilc);
+ chip_allow_sleep(wilc);
+ }
+
+ ret = sdio_reset(wilc);
+ if (ret) {
+ dev_err(&func->dev, "Fail reset sdio\n");
+ return ret;
+ }
+ sdio_claim_host(func);
+
+ return 0;
+}
+
+static int wilc_sdio_resume(struct device *dev)
+{
+ struct sdio_func *func = dev_to_sdio_func(dev);
+ struct wilc *wilc = sdio_get_drvdata(func);
+
+ dev_info(dev, "sdio resume\n");
+ sdio_release_host(func);
+ chip_wakeup(wilc);
+ sdio_init(wilc, true);
+
+ if (wilc->suspend_event)
+ host_wakeup_notify(wilc);
+
+ chip_allow_sleep(wilc);
+
+ return 0;
+}
+
+static const struct dev_pm_ops wilc_sdio_pm_ops = {
+ .suspend = wilc_sdio_suspend,
+ .resume = wilc_sdio_resume,
+};
+
static struct sdio_driver wilc1000_sdio_driver = {
.name = SDIO_MODALIAS,
.id_table = wilc_sdio_ids,
.probe = linux_sdio_probe,
.remove = linux_sdio_remove,
+ .drv = {
+ .pm = &wilc_sdio_pm_ops,
+ }
};
module_driver(wilc1000_sdio_driver,
sdio_register_driver,
dev_info(&func->dev, "wilc_sdio_disable_interrupt OUT\n");
}
-static int wilc_sdio_init(void)
-{
- return 1;
-}
-
/********************************************
*
* Function 0
return 1;
}
-static int sdio_init(struct wilc *wilc)
+static int sdio_init(struct wilc *wilc, bool resume)
{
struct sdio_func *func = dev_to_sdio_func(wilc->dev);
sdio_cmd52_t cmd;
int loop, ret;
u32 chipid;
- memset(&g_sdio, 0, sizeof(wilc_sdio_t));
-
- g_sdio.irq_gpio = (wilc->dev_irq_num);
-
- if (!wilc_sdio_init()) {
- dev_err(&func->dev, "Failed io init bus...\n");
- return 0;
- } else {
- return 0;
+ if (!resume) {
+ memset(&g_sdio, 0, sizeof(wilc_sdio_t));
+ g_sdio.irq_gpio = (wilc->dev_irq_num);
}
/**
/**
* make sure can read back chip id correctly
**/
- if (!sdio_read_reg(wilc, 0x1000, &chipid)) {
- dev_err(&func->dev, "Fail cmd read chip id...\n");
- goto _fail_;
+ if (!resume) {
+ if (!sdio_read_reg(wilc, 0x1000, &chipid)) {
+ dev_err(&func->dev, "Fail cmd read chip id...\n");
+ goto _fail_;
+ }
+ dev_err(&func->dev, "chipid (%08x)\n", chipid);
+ if ((chipid & 0xfff) > 0x2a0)
+ g_sdio.has_thrpt_enh3 = 1;
+ else
+ g_sdio.has_thrpt_enh3 = 0;
+ dev_info(&func->dev, "has_thrpt_enh3 = %d...\n",
+ g_sdio.has_thrpt_enh3);
}
- dev_err(&func->dev, "chipid (%08x)\n", chipid);
- if ((chipid & 0xfff) > 0x2a0)
- g_sdio.has_thrpt_enh3 = 1;
- else
- g_sdio.has_thrpt_enh3 = 0;
- dev_info(&func->dev, "has_thrpt_enh3 = %d...\n", g_sdio.has_thrpt_enh3);
return 1;
#define USE_SPI_DMA 0
-static const struct wilc1000_ops wilc1000_spi_ops;
-
static int wilc_bus_probe(struct spi_device *spi)
{
int ret, gpio;
};
MODULE_DEVICE_TABLE(of, wilc1000_of_match);
-struct spi_driver wilc1000_spi_driver = {
+static struct spi_driver wilc1000_spi_driver = {
.driver = {
.name = MODALIAS,
.of_match_table = wilc1000_of_match,
return 1;
}
-static int wilc_spi_init(struct wilc *wilc)
+static int wilc_spi_init(struct wilc *wilc, bool resume)
{
struct spi_device *spi = to_spi_device(wilc->dev);
u32 reg;
}
};
+static const struct wiphy_wowlan_support wowlan_support = {
+ .flags = WIPHY_WOWLAN_ANY
+};
+
#define WILC_WFI_DWELL_PASSIVE 100
#define WILC_WFI_DWELL_ACTIVE 40
extern int wilc_mac_open(struct net_device *ndev);
extern int wilc_mac_close(struct net_device *ndev);
-static tstrNetworkInfo last_scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW];
+static struct network_info last_scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW];
static u32 last_scanned_cnt;
struct timer_list wilc_during_ip_timer;
static struct timer_list hAgingTimer;
if (op_ifcs == 0) {
del_timer_sync(&hAgingTimer);
- PRINT_INFO(CORECONFIG_DBG, "destroy aging timer\n");
for (i = 0; i < last_scanned_cnt; i++) {
- if (last_scanned_shadow[last_scanned_cnt].pu8IEs) {
- kfree(last_scanned_shadow[i].pu8IEs);
- last_scanned_shadow[last_scanned_cnt].pu8IEs = NULL;
+ if (last_scanned_shadow[last_scanned_cnt].ies) {
+ kfree(last_scanned_shadow[i].ies);
+ last_scanned_shadow[last_scanned_cnt].ies = NULL;
}
- wilc_free_join_params(last_scanned_shadow[i].pJoinParams);
- last_scanned_shadow[i].pJoinParams = NULL;
+ kfree(last_scanned_shadow[i].join_params);
+ last_scanned_shadow[i].join_params = NULL;
}
last_scanned_cnt = 0;
}
}
-static u32 get_rssi_avg(tstrNetworkInfo *network_info)
+static u32 get_rssi_avg(struct network_info *network_info)
{
u8 i;
int rssi_v = 0;
- u8 num_rssi = (network_info->strRssi.u8Full) ? NUM_RSSI : (network_info->strRssi.u8Index);
+ u8 num_rssi = (network_info->str_rssi.u8Full) ?
+ NUM_RSSI : (network_info->str_rssi.u8Index);
for (i = 0; i < num_rssi; i++)
- rssi_v += network_info->strRssi.as8RSSI[i];
+ rssi_v += network_info->str_rssi.as8RSSI[i];
rssi_v /= num_rssi;
return rssi_v;
wiphy = priv->dev->ieee80211_ptr->wiphy;
for (i = 0; i < last_scanned_cnt; i++) {
- tstrNetworkInfo *network_info;
+ struct network_info *network_info;
network_info = &last_scanned_shadow[i];
- if (!network_info->u8Found || all) {
+ if (!network_info->found || all) {
s32 freq;
struct ieee80211_channel *channel;
if (network_info) {
- freq = ieee80211_channel_to_frequency((s32)network_info->u8channel, IEEE80211_BAND_2GHZ);
+ freq = ieee80211_channel_to_frequency((s32)network_info->ch, IEEE80211_BAND_2GHZ);
channel = ieee80211_get_channel(wiphy, freq);
rssi = get_rssi_avg(network_info);
- if (memcmp("DIRECT-", network_info->au8ssid, 7) ||
+ if (memcmp("DIRECT-", network_info->ssid, 7) ||
direct_scan) {
- bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->au8bssid, network_info->u64Tsf, network_info->u16CapInfo,
- network_info->u16BeaconPeriod, (const u8 *)network_info->pu8IEs,
- (size_t)network_info->u16IEsLen, (((s32)rssi) * 100), GFP_KERNEL);
+ bss = cfg80211_inform_bss(wiphy,
+ channel,
+ CFG80211_BSS_FTYPE_UNKNOWN,
+ network_info->bssid,
+ network_info->tsf_hi,
+ network_info->cap_info,
+ network_info->beacon_period,
+ (const u8 *)network_info->ies,
+ (size_t)network_info->ies_len,
+ (s32)rssi * 100,
+ GFP_KERNEL);
cfg80211_put_bss(wiphy, bss);
}
}
int i;
for (i = 0; i < last_scanned_cnt; i++)
- last_scanned_shadow[i].u8Found = 0;
+ last_scanned_shadow[i].found = 0;
}
static void update_scan_time(void)
int i;
for (i = 0; i < last_scanned_cnt; i++)
- last_scanned_shadow[i].u32TimeRcvdInScan = jiffies;
+ last_scanned_shadow[i].time_scan = jiffies;
}
static void remove_network_from_shadow(unsigned long arg)
for (i = 0; i < last_scanned_cnt; i++) {
- if (time_after(now, last_scanned_shadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) {
- PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s\n", last_scanned_shadow[i].au8ssid);
+ if (time_after(now, last_scanned_shadow[i].time_scan +
+ (unsigned long)(SCAN_RESULT_EXPIRE))) {
+ PRINT_D(CFG80211_DBG, "Network expired ScanShadow:%s\n",
+ last_scanned_shadow[i].ssid);
- kfree(last_scanned_shadow[i].pu8IEs);
- last_scanned_shadow[i].pu8IEs = NULL;
+ kfree(last_scanned_shadow[i].ies);
+ last_scanned_shadow[i].ies = NULL;
- wilc_free_join_params(last_scanned_shadow[i].pJoinParams);
+ kfree(last_scanned_shadow[i].join_params);
for (j = i; (j < last_scanned_cnt - 1); j++)
last_scanned_shadow[j] = last_scanned_shadow[j + 1];
static void clear_duringIP(unsigned long arg)
{
- PRINT_D(GENERIC_DBG, "GO:IP Obtained , enable scan\n");
wilc_optaining_ip = false;
}
-static int is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo,
+static int is_network_in_shadow(struct network_info *pstrNetworkInfo,
void *user_void)
{
int state = -1;
state = -1;
} else {
for (i = 0; i < last_scanned_cnt; i++) {
- if (memcmp(last_scanned_shadow[i].au8bssid,
- pstrNetworkInfo->au8bssid, 6) == 0) {
+ if (memcmp(last_scanned_shadow[i].bssid,
+ pstrNetworkInfo->bssid, 6) == 0) {
state = i;
break;
}
return state;
}
-static void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo,
+static void add_network_to_shadow(struct network_info *pstrNetworkInfo,
void *user_void, void *pJoinParams)
{
int ap_found = is_network_in_shadow(pstrNetworkInfo, user_void);
} else {
ap_index = ap_found;
}
- rssi_index = last_scanned_shadow[ap_index].strRssi.u8Index;
- last_scanned_shadow[ap_index].strRssi.as8RSSI[rssi_index++] = pstrNetworkInfo->s8rssi;
+ rssi_index = last_scanned_shadow[ap_index].str_rssi.u8Index;
+ last_scanned_shadow[ap_index].str_rssi.as8RSSI[rssi_index++] = pstrNetworkInfo->rssi;
if (rssi_index == NUM_RSSI) {
rssi_index = 0;
- last_scanned_shadow[ap_index].strRssi.u8Full = 1;
- }
- last_scanned_shadow[ap_index].strRssi.u8Index = rssi_index;
- last_scanned_shadow[ap_index].s8rssi = pstrNetworkInfo->s8rssi;
- last_scanned_shadow[ap_index].u16CapInfo = pstrNetworkInfo->u16CapInfo;
- last_scanned_shadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen;
- memcpy(last_scanned_shadow[ap_index].au8ssid,
- pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen);
- memcpy(last_scanned_shadow[ap_index].au8bssid,
- pstrNetworkInfo->au8bssid, ETH_ALEN);
- last_scanned_shadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod;
- last_scanned_shadow[ap_index].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod;
- last_scanned_shadow[ap_index].u8channel = pstrNetworkInfo->u8channel;
- last_scanned_shadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen;
- last_scanned_shadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf;
+ last_scanned_shadow[ap_index].str_rssi.u8Full = 1;
+ }
+ last_scanned_shadow[ap_index].str_rssi.u8Index = rssi_index;
+ last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi;
+ last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info;
+ last_scanned_shadow[ap_index].ssid_len = pstrNetworkInfo->ssid_len;
+ memcpy(last_scanned_shadow[ap_index].ssid,
+ pstrNetworkInfo->ssid, pstrNetworkInfo->ssid_len);
+ memcpy(last_scanned_shadow[ap_index].bssid,
+ pstrNetworkInfo->bssid, ETH_ALEN);
+ last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period;
+ last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period;
+ last_scanned_shadow[ap_index].ch = pstrNetworkInfo->ch;
+ last_scanned_shadow[ap_index].ies_len = pstrNetworkInfo->ies_len;
+ last_scanned_shadow[ap_index].tsf_hi = pstrNetworkInfo->tsf_hi;
if (ap_found != -1)
- kfree(last_scanned_shadow[ap_index].pu8IEs);
- last_scanned_shadow[ap_index].pu8IEs =
- kmalloc(pstrNetworkInfo->u16IEsLen, GFP_KERNEL);
- memcpy(last_scanned_shadow[ap_index].pu8IEs,
- pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen);
- last_scanned_shadow[ap_index].u32TimeRcvdInScan = jiffies;
- last_scanned_shadow[ap_index].u32TimeRcvdInScanCached = jiffies;
- last_scanned_shadow[ap_index].u8Found = 1;
+ kfree(last_scanned_shadow[ap_index].ies);
+ last_scanned_shadow[ap_index].ies = kmalloc(pstrNetworkInfo->ies_len,
+ GFP_KERNEL);
+ memcpy(last_scanned_shadow[ap_index].ies,
+ pstrNetworkInfo->ies, pstrNetworkInfo->ies_len);
+ last_scanned_shadow[ap_index].time_scan = jiffies;
+ last_scanned_shadow[ap_index].time_scan_cached = jiffies;
+ last_scanned_shadow[ap_index].found = 1;
if (ap_found != -1)
- wilc_free_join_params(last_scanned_shadow[ap_index].pJoinParams);
- last_scanned_shadow[ap_index].pJoinParams = pJoinParams;
+ kfree(last_scanned_shadow[ap_index].join_params);
+ last_scanned_shadow[ap_index].join_params = pJoinParams;
}
static void CfgScanResult(enum scan_event scan_event,
- tstrNetworkInfo *network_info,
+ struct network_info *network_info,
void *user_void,
void *join_params)
{
return;
if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
- (((s32)network_info->s8rssi * 100) < 0 ||
- ((s32)network_info->s8rssi * 100) > 100)) {
- PRINT_ER("wiphy signal type fial\n");
+ (((s32)network_info->rssi * 100) < 0 ||
+ ((s32)network_info->rssi * 100) > 100))
return;
- }
if (network_info) {
- s32Freq = ieee80211_channel_to_frequency((s32)network_info->u8channel, IEEE80211_BAND_2GHZ);
+ s32Freq = ieee80211_channel_to_frequency((s32)network_info->ch, IEEE80211_BAND_2GHZ);
channel = ieee80211_get_channel(wiphy, s32Freq);
if (!channel)
return;
- PRINT_INFO(CFG80211_DBG, "Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d,"
- "BeaconPeriod: %d\n", channel->center_freq, (((s32)network_info->s8rssi) * 100),
- network_info->u16CapInfo, network_info->u16BeaconPeriod);
-
- if (network_info->bNewNetwork) {
+ PRINT_INFO(CFG80211_DBG, "Network Info::"
+ "CHANNEL Frequency: %d,"
+ "RSSI: %d,"
+ "Capability Info: %d,"
+ "Beacon Period: %d\n",
+ channel->center_freq,
+ (s32)network_info->rssi * 100,
+ network_info->cap_info,
+ network_info->beacon_period);
+
+ if (network_info->new_network) {
if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) {
- PRINT_D(CFG80211_DBG, "Network %s found\n", network_info->au8ssid);
+ PRINT_D(CFG80211_DBG,
+ "Network %s found\n",
+ network_info->ssid);
priv->u32RcvdChCount++;
- if (!join_params)
- PRINT_INFO(CORECONFIG_DBG, ">> Something really bad happened\n");
add_network_to_shadow(network_info, priv, join_params);
- if (!(memcmp("DIRECT-", network_info->au8ssid, 7))) {
- bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->au8bssid, network_info->u64Tsf, network_info->u16CapInfo,
- network_info->u16BeaconPeriod, (const u8 *)network_info->pu8IEs,
- (size_t)network_info->u16IEsLen, (((s32)network_info->s8rssi) * 100), GFP_KERNEL);
+ if (!(memcmp("DIRECT-", network_info->ssid, 7))) {
+ bss = cfg80211_inform_bss(wiphy,
+ channel,
+ CFG80211_BSS_FTYPE_UNKNOWN,
+ network_info->bssid,
+ network_info->tsf_hi,
+ network_info->cap_info,
+ network_info->beacon_period,
+ (const u8 *)network_info->ies,
+ (size_t)network_info->ies_len,
+ (s32)network_info->rssi * 100,
+ GFP_KERNEL);
cfg80211_put_bss(wiphy, bss);
}
-
-
- } else {
- PRINT_ER("Discovered networks exceeded the max limit\n");
}
} else {
u32 i;
for (i = 0; i < priv->u32RcvdChCount; i++) {
- if (memcmp(last_scanned_shadow[i].au8bssid, network_info->au8bssid, 6) == 0) {
- PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].au8ssid);
+ if (memcmp(last_scanned_shadow[i].bssid, network_info->bssid, 6) == 0) {
+ PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].ssid);
- last_scanned_shadow[i].s8rssi = network_info->s8rssi;
- last_scanned_shadow[i].u32TimeRcvdInScan = jiffies;
+ last_scanned_shadow[i].rssi = network_info->rssi;
+ last_scanned_shadow[i].time_scan = jiffies;
break;
}
}
dev = priv->dev;
vif = netdev_priv(dev);
wl = vif->wilc;
- pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
+ pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) {
u16 u16ConnectStatus;
if ((u8MacStatus == MAC_DISCONNECTED) &&
(pstrConnectInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE;
- wilc_wlan_set_bssid(priv->dev, NullBssid);
+ wilc_wlan_set_bssid(priv->dev, NullBssid,
+ STATION_MODE);
eth_zero_addr(wilc_connected_ssid);
if (!pstrWFIDrv->p2p_connect)
wlan_channel = INVALID_CHANNEL;
- PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d\n", u16ConnectStatus, u8MacStatus);
+ netdev_err(dev, "Unspecified failure\n");
}
if (u16ConnectStatus == WLAN_STATUS_SUCCESS) {
for (i = 0; i < last_scanned_cnt; i++) {
- if (memcmp(last_scanned_shadow[i].au8bssid,
- pstrConnectInfo->au8bssid, ETH_ALEN) == 0) {
+ if (memcmp(last_scanned_shadow[i].bssid,
+ pstrConnectInfo->au8bssid,
+ ETH_ALEN) == 0) {
unsigned long now = jiffies;
if (time_after(now,
- last_scanned_shadow[i].u32TimeRcvdInScanCached + (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) {
+ last_scanned_shadow[i].time_scan_cached +
+ (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ))))
bNeedScanRefresh = true;
- }
break;
}
u16ConnectStatus, GFP_KERNEL);
} else if (enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF) {
wilc_optaining_ip = false;
- PRINT_ER("Received MAC_DISCONNECTED from firmware with reason %d on dev [%p]\n",
- pstrDisconnectNotifInfo->u16reason, priv->dev);
p2p_local_random = 0x01;
p2p_recv_random = 0x00;
wilc_ie = false;
eth_zero_addr(priv->au8AssociatedBss);
- wilc_wlan_set_bssid(priv->dev, NullBssid);
+ wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
eth_zero_addr(wilc_connected_ssid);
if (!pstrWFIDrv->p2p_connect)
result = wilc_set_mac_chnl_num(vif, channelnum);
if (result != 0)
- PRINT_ER("Error in setting channel %d\n", channelnum);
+ netdev_err(priv->dev, "Error in setting channel\n");
return result;
}
priv->u32RcvdChCount = 0;
- wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif));
reset_shadow_found();
priv->bCfgScanning = true;
PRINT_D(CFG80211_DBG, "Number of SSIDs %d\n", request->n_ssids);
if (request->n_ssids >= 1) {
- strHiddenNetwork.pstrHiddenNetworkInfo = kmalloc(request->n_ssids * sizeof(struct hidden_network), GFP_KERNEL);
- strHiddenNetwork.u8ssidnum = request->n_ssids;
+ strHiddenNetwork.net_info = kmalloc(request->n_ssids * sizeof(struct hidden_network), GFP_KERNEL);
+ strHiddenNetwork.n_ssids = request->n_ssids;
for (i = 0; i < request->n_ssids; i++) {
if (request->ssids[i].ssid &&
request->ssids[i].ssid_len != 0) {
- strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL);
- memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, request->ssids[i].ssid, request->ssids[i].ssid_len);
- strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len;
+ strHiddenNetwork.net_info[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL);
+ memcpy(strHiddenNetwork.net_info[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len);
+ strHiddenNetwork.net_info[i].ssid_len = request->ssids[i].ssid_len;
} else {
PRINT_D(CFG80211_DBG, "Received one NULL SSID\n");
- strHiddenNetwork.u8ssidnum -= 1;
+ strHiddenNetwork.n_ssids -= 1;
}
}
PRINT_D(CFG80211_DBG, "Trigger Scan Request\n");
(void *)priv, NULL);
}
} else {
- PRINT_ER("Requested num of scanned channels is greater than the max, supported"
- " channels\n");
+ netdev_err(priv->dev, "Requested scanned channels over\n");
}
if (s32Error != 0) {
struct wilc_priv *priv;
struct host_if_drv *pstrWFIDrv;
- tstrNetworkInfo *pstrNetworkInfo = NULL;
+ struct network_info *pstrNetworkInfo = NULL;
struct wilc_vif *vif;
wilc_connecting = 1;
priv = wiphy_priv(wiphy);
vif = netdev_priv(priv->dev);
- pstrWFIDrv = (struct host_if_drv *)(priv->hWILCWFIDrv);
+ pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
- wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif));
-
- PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", sme->ssid, dev, priv->hWILCWFIDrv);
+ PRINT_D(CFG80211_DBG,
+ "Connecting to SSID [%s] on netdev [%p] host if [%p]\n",
+ sme->ssid, dev, priv->hif_drv);
if (!(strncmp(sme->ssid, "DIRECT-", 7))) {
PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n");
pstrWFIDrv->p2p_connect = 1;
PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d\n", sme->ssid, sme->auth_type);
for (i = 0; i < last_scanned_cnt; i++) {
- if ((sme->ssid_len == last_scanned_shadow[i].u8SsidLen) &&
- memcmp(last_scanned_shadow[i].au8ssid,
+ if ((sme->ssid_len == last_scanned_shadow[i].ssid_len) &&
+ memcmp(last_scanned_shadow[i].ssid,
sme->ssid,
sme->ssid_len) == 0) {
PRINT_INFO(CFG80211_DBG, "Network with required SSID is found %s\n", sme->ssid);
PRINT_INFO(CFG80211_DBG, "BSSID is not passed from the user\n");
break;
} else {
- if (memcmp(last_scanned_shadow[i].au8bssid,
+ if (memcmp(last_scanned_shadow[i].bssid,
sme->bssid,
ETH_ALEN) == 0) {
PRINT_INFO(CFG80211_DBG, "BSSID is passed from the user and matched\n");
pstrNetworkInfo = &last_scanned_shadow[i];
- PRINT_INFO(CFG80211_DBG, "network BSSID to be associated: %x%x%x%x%x%x\n",
- pstrNetworkInfo->au8bssid[0], pstrNetworkInfo->au8bssid[1],
- pstrNetworkInfo->au8bssid[2], pstrNetworkInfo->au8bssid[3],
- pstrNetworkInfo->au8bssid[4], pstrNetworkInfo->au8bssid[5]);
+ PRINT_INFO(CFG80211_DBG, "network BSSID to be associated:"
+ "%x%x%x%x%x%x\n",
+ pstrNetworkInfo->bssid[0], pstrNetworkInfo->bssid[1],
+ pstrNetworkInfo->bssid[2], pstrNetworkInfo->bssid[3],
+ pstrNetworkInfo->bssid[4], pstrNetworkInfo->bssid[5]);
} else {
s32Error = -ENOENT;
if (last_scanned_cnt == 0)
PRINT_D(CFG80211_DBG, "No Scan results yet\n");
else
PRINT_D(CFG80211_DBG, "Required bss not in scan results: Error(%d)\n", s32Error);
-
- goto done;
+ wilc_connecting = 0;
+ return s32Error;
}
- priv->WILC_WFI_wep_default = 0;
memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key));
memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len));
PRINT_INFO(CFG80211_DBG, "sme->crypto.n_ciphers_pairwise=%d\n", sme->crypto.n_ciphers_pairwise);
- if (INFO) {
- for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++)
- PRINT_D(CORECONFIG_DBG, "sme->crypto.ciphers_pairwise[%d]=%x\n", i, sme->crypto.ciphers_pairwise[i]);
- }
-
if (sme->crypto.cipher_group != NO_ENCRYPT) {
pcwpa_version = "Default";
- PRINT_D(CORECONFIG_DBG, ">> sme->crypto.wpa_versions: %x\n", sme->crypto.wpa_versions);
if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) {
u8security = ENCRYPT_ENABLED | WEP;
pcgroup_encrypt_val = "WEP40";
pccipher_group = "WLAN_CIPHER_SUITE_WEP40";
PRINT_INFO(CFG80211_DBG, "WEP Default Key Idx = %d\n", sme->key_idx);
- if (INFO) {
- for (i = 0; i < sme->key_len; i++)
- PRINT_D(CORECONFIG_DBG, "WEP Key Value[%d] = %d\n", i, sme->key[i]);
- }
- priv->WILC_WFI_wep_default = sme->key_idx;
priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
pcgroup_encrypt_val = "WEP104";
pccipher_group = "WLAN_CIPHER_SUITE_WEP104";
- priv->WILC_WFI_wep_default = sme->key_idx;
priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
} else {
s32Error = -ENOTSUPP;
- PRINT_ER("Not supported cipher: Error(%d)\n", s32Error);
-
- goto done;
+ netdev_err(dev, "Not supported cipher\n");
+ wilc_connecting = 0;
+ return s32Error;
}
}
}
- PRINT_INFO(CFG80211_DBG, "Required Channel = %d\n", pstrNetworkInfo->u8channel);
+ PRINT_INFO(CFG80211_DBG, "Required Ch = %d\n", pstrNetworkInfo->ch);
PRINT_INFO(CFG80211_DBG, "Group encryption value = %s\n Cipher Group = %s\n WPA version = %s\n",
pcgroup_encrypt_val, pccipher_group, pcwpa_version);
- curr_channel = pstrNetworkInfo->u8channel;
+ curr_channel = pstrNetworkInfo->ch;
if (!pstrWFIDrv->p2p_connect)
- wlan_channel = pstrNetworkInfo->u8channel;
+ wlan_channel = pstrNetworkInfo->ch;
- wilc_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid);
+ wilc_wlan_set_bssid(dev, pstrNetworkInfo->bssid, STATION_MODE);
- s32Error = wilc_set_join_req(vif, pstrNetworkInfo->au8bssid, sme->ssid,
+ s32Error = wilc_set_join_req(vif, pstrNetworkInfo->bssid, sme->ssid,
sme->ssid_len, sme->ie, sme->ie_len,
CfgConnectResult, (void *)priv,
u8security, tenuAuth_type,
- pstrNetworkInfo->u8channel,
- pstrNetworkInfo->pJoinParams);
+ pstrNetworkInfo->ch,
+ pstrNetworkInfo->join_params);
if (s32Error != 0) {
- PRINT_ER("wilc_set_join_req(): Error(%d)\n", s32Error);
+ netdev_err(dev, "wilc_set_join_req(): Error\n");
s32Error = -ENOENT;
- goto done;
+ wilc_connecting = 0;
+ return s32Error;
}
-done:
-
return s32Error;
}
priv = wiphy_priv(wiphy);
vif = netdev_priv(priv->dev);
- pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
+ pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
if (!pstrWFIDrv->p2p_connect)
wlan_channel = INVALID_CHANNEL;
- wilc_wlan_set_bssid(priv->dev, NullBssid);
+ wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE);
PRINT_D(CFG80211_DBG, "Disconnecting with reason code(%d)\n", reason_code);
s32Error = wilc_disconnect(vif, reason_code);
if (s32Error != 0) {
- PRINT_ER("Error in disconnecting: Error(%d)\n", s32Error);
+ netdev_err(priv->dev, "Error in disconnecting\n");
s32Error = -EINVAL;
}
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
if (priv->wdev->iftype == NL80211_IFTYPE_AP) {
- priv->WILC_WFI_wep_default = key_index;
priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
break;
}
if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) {
- priv->WILC_WFI_wep_default = key_index;
priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
break;
default:
- PRINT_ER("Not supported cipher: Error(%d)\n", s32Error);
+ netdev_err(netdev, "Not supported cipher\n");
s32Error = -ENOTSUPP;
}
kfree(g_key_gtk_params.seq);
g_key_gtk_params.seq = NULL;
- wilc_set_machw_change_vir_if(netdev, false);
}
if (key_index >= 0 && key_index <= 3) {
wilc_remove_wep_key(vif, key_index);
} else {
PRINT_D(CFG80211_DBG, "Removing all installed keys\n");
- wilc_remove_key(priv->hWILCWFIDrv, mac_addr);
+ wilc_remove_key(priv->hif_drv, mac_addr);
}
return 0;
PRINT_D(CFG80211_DBG, "Setting default key with idx = %d\n", key_index);
- if (key_index != priv->WILC_WFI_wep_default) {
- wilc_set_wep_default_keyid(vif, key_index);
- }
+ wilc_set_wep_default_keyid(vif, key_index);
return 0;
}
}
if (associatedsta == -1) {
- PRINT_ER("Station required is not associated\n");
+ netdev_err(dev, "sta required is not associated\n");
return -ENOENT;
}
wilc_enable_tcp_ack_filter(true);
else if (strStatistics.link_speed != DEFAULT_LINK_SPEED)
wilc_enable_tcp_ack_filter(false);
-
- PRINT_D(CORECONFIG_DBG, "*** stats[%d][%d][%d][%d][%d]\n", sinfo->signal, sinfo->rx_packets, sinfo->tx_packets,
- sinfo->tx_failed, sinfo->txrate.legacy);
}
return 0;
}
PRINT_D(CFG80211_DBG, "Setting CFG params in the host interface\n");
s32Error = wilc_hif_set_cfg(vif, &pstrCfgParamVal);
if (s32Error)
- PRINT_ER("Error in setting WIPHY PARAMS\n");
-
+ netdev_err(priv->dev, "Error in setting WIPHY PARAMS\n");
return s32Error;
}
if (!(flag == PMKID_FOUND))
priv->pmkid_list.numpmkid++;
} else {
- PRINT_ER("Invalid PMKID index\n");
+ netdev_err(netdev, "Invalid PMKID index\n");
s32Error = -EINVAL;
}
}
if (wlan_channel != INVALID_CHANNEL) {
if (channel_list_attr_index) {
- PRINT_D(GENERIC_DBG, "Modify channel list attribute\n");
for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
if (buf[i] == 0x51) {
for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) {
}
if (op_channel_attr_index) {
- PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n");
buf[op_channel_attr_index + 6] = 0x51;
buf[op_channel_attr_index + 7] = wlan_channel;
}
}
if (wlan_channel != INVALID_CHANNEL && bOperChan) {
if (channel_list_attr_index) {
- PRINT_D(GENERIC_DBG, "Modify channel list attribute\n");
for (i = channel_list_attr_index + 3; i < ((channel_list_attr_index + 3) + buf[channel_list_attr_index + 1]); i++) {
if (buf[i] == 0x51) {
for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) {
}
if (op_channel_attr_index) {
- PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n");
buf[op_channel_attr_index + 6] = 0x51;
buf[op_channel_attr_index + 7] = wlan_channel;
}
s32 s32Freq;
priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
- pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
+ pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
if (buff[FRAME_TYPE_ID] == IEEE80211_STYPE_PROBE_RESP) {
- PRINT_D(GENERIC_DBG, "Probe response ACK\n");
cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
return;
} else {
- if (pkt_offset & IS_MGMT_STATUS_SUCCES) {
- PRINT_D(GENERIC_DBG, "Success Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID],
- buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]);
+ if (pkt_offset & IS_MGMT_STATUS_SUCCES)
cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL);
- } else {
- PRINT_D(GENERIC_DBG, "Fail Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID],
- buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]);
+ else
cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL);
- }
return;
}
} else {
- PRINT_D(GENERIC_DBG, "Rx Frame Type:%x\n", buff[FRAME_TYPE_ID]);
-
s32Freq = ieee80211_channel_to_frequency(curr_channel, IEEE80211_BAND_2GHZ);
if (ieee80211_is_action(buff[FRAME_TYPE_ID])) {
- PRINT_D(GENERIC_DBG, "Rx Action Frame Type: %x %x\n", buff[ACTION_SUBTYPE_ID], buff[P2P_PUB_ACTION_SUBTYPE]);
-
if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) {
- PRINT_D(GENERIC_DBG, "Receiving action frames from wrong channels\n");
+ netdev_dbg(dev, "Receiving action wrong ch\n");
return;
}
if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
switch (buff[ACTION_SUBTYPE_ID]) {
case GAS_INTIAL_REQ:
- PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buff[ACTION_SUBTYPE_ID]);
break;
case GAS_INTIAL_RSP:
- PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buff[ACTION_SUBTYPE_ID]);
break;
case PUBLIC_ACT_VENDORSPEC:
if (!memcmp(p2p_vendor_spec, &buff[i], 6)) {
p2p_recv_random = buff[i + 6];
wilc_ie = true;
- PRINT_D(GENERIC_DBG, "WILC Vendor specific IE:%02x\n", p2p_recv_random);
break;
}
}
}
}
} else {
- PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random);
+ netdev_dbg(dev, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random);
}
}
if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP) && (wilc_ie)) {
- PRINT_D(GENERIC_DBG, "Sending P2P to host without extra elemnt\n");
cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
return;
}
break;
default:
- PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]);
+ netdev_dbg(dev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]);
break;
}
}
}
- cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0);
+ cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size, 0);
}
}
priv = (struct wilc_priv *)pUserVoid;
- PRINT_D(HOSTINF_DBG, "Remain on channel ready\n");
-
priv->bInP2PlistenState = true;
cfg80211_ready_on_channel(priv->wdev,
priv = (struct wilc_priv *)pUserVoid;
if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) {
- PRINT_D(GENERIC_DBG, "Remain on channel expired\n");
-
priv->bInP2PlistenState = false;
cfg80211_remain_on_channel_expired(priv->wdev,
priv->strRemainOnChanParams.u64ListenCookie,
priv->strRemainOnChanParams.pstrListenChan,
GFP_KERNEL);
- } else {
- PRINT_D(GENERIC_DBG, "Received ID 0x%x Expected ID 0x%x (No match)\n", u32SessionID
- , priv->strRemainOnChanParams.u32ListenSessionID);
}
}
priv = wiphy_priv(wiphy);
vif = netdev_priv(priv->dev);
- PRINT_D(GENERIC_DBG, "Remaining on channel %d\n", chan->hw_value);
-
-
if (wdev->iftype == NL80211_IFTYPE_AP) {
- PRINT_D(GENERIC_DBG, "Required remain-on-channel while in AP mode");
+ netdev_dbg(vif->ndev, "Required while in AP mode\n");
return s32Error;
}
vif = netdev_priv(wdev->netdev);
priv = wiphy_priv(wiphy);
- pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
+ pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
*cookie = (unsigned long)buf;
priv->u64tx_cookie = *cookie;
if (ieee80211_is_mgmt(mgmt->frame_control)) {
mgmt_tx = kmalloc(sizeof(struct p2p_mgmt_data), GFP_KERNEL);
- if (!mgmt_tx) {
- PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
+ if (!mgmt_tx)
return -EFAULT;
- }
+
mgmt_tx->buff = kmalloc(buf_len, GFP_KERNEL);
- if (!mgmt_tx->buff) {
- PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
+ if (!mgmt_tx->buff)
kfree(mgmt_tx);
return -EFAULT;
- }
+
memcpy(mgmt_tx->buff, buf, len);
mgmt_tx->size = len;
if (ieee80211_is_probe_resp(mgmt->frame_control)) {
- PRINT_D(GENERIC_DBG, "TX: Probe Response\n");
- PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value);
wilc_set_mac_chnl_num(vif, chan->hw_value);
curr_channel = chan->hw_value;
} else if (ieee80211_is_action(mgmt->frame_control)) {
- PRINT_D(GENERIC_DBG, "ACTION FRAME:%x\n", (u16)mgmt->frame_control);
-
-
if (buf[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) {
if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC ||
buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) {
- PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value);
wilc_set_mac_chnl_num(vif,
chan->hw_value);
curr_channel = chan->hw_value;
}
switch (buf[ACTION_SUBTYPE_ID]) {
case GAS_INTIAL_REQ:
- {
- PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buf[ACTION_SUBTYPE_ID]);
break;
- }
case GAS_INTIAL_RSP:
- {
- PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buf[ACTION_SUBTYPE_ID]);
break;
- }
case PUBLIC_ACT_VENDORSPEC:
{
if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
|| buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
if (p2p_local_random > p2p_recv_random) {
- PRINT_D(GENERIC_DBG, "LOCAL WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random);
-
for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) {
if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buf[i + 2], 4))) {
if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)
mgmt_tx->buff[len + sizeof(p2p_vendor_spec)] = p2p_local_random;
mgmt_tx->size = buf_len;
}
- } else {
- PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random);
}
}
} else {
- PRINT_D(GENERIC_DBG, "Not a P2P public action frame\n");
+ netdev_dbg(vif->ndev, "Not a P2P public action frame\n");
}
break;
default:
{
- PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]);
+ netdev_dbg(vif->ndev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]);
break;
}
}
}
- PRINT_D(GENERIC_DBG, "TX: ACTION FRAME Type:%x : Chan:%d\n", buf[ACTION_SUBTYPE_ID], chan->hw_value);
pstrWFIDrv->p2p_timeout = (jiffies + msecs_to_jiffies(wait));
-
- PRINT_D(GENERIC_DBG, "Current Jiffies: %lu Timeout:%llu\n",
- jiffies, pstrWFIDrv->p2p_timeout);
}
wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,
mgmt_tx->buff, mgmt_tx->size,
WILC_WFI_mgmt_tx_complete);
- } else {
- PRINT_D(GENERIC_DBG, "This function transmits only management frames\n");
}
return 0;
}
struct host_if_drv *pstrWFIDrv;
priv = wiphy_priv(wiphy);
- pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv;
-
-
- PRINT_D(GENERIC_DBG, "Tx Cancel wait :%lu\n", jiffies);
+ pstrWFIDrv = (struct host_if_drv *)priv->hif_drv;
pstrWFIDrv->p2p_timeout = jiffies;
if (!priv->bInP2PlistenState) {
if (!frame_type)
return;
- PRINT_D(GENERIC_DBG, "Frame registering Frame Type: %x: Boolean: %d\n", frame_type, reg);
switch (frame_type) {
case PROBE_REQ:
{
}
}
- if (!wl->initialized) {
- PRINT_D(GENERIC_DBG, "Return since mac is closed\n");
+ if (!wl->initialized)
return;
- }
wilc_frame_register(vif, frame_type, reg);
}
priv = wiphy_priv(wiphy);
vif = netdev_priv(priv->dev);
- if (!priv->hWILCWFIDrv) {
- PRINT_ER("Driver is NULL\n");
+ if (!priv->hif_drv)
return -EIO;
- }
if (wilc_enable_ps)
wilc_set_power_mgmt(vif, enabled, timeout);
{
struct wilc_priv *priv;
struct wilc_vif *vif;
- u8 interface_type;
- u16 TID = 0;
- u8 i;
struct wilc *wl;
vif = netdev_priv(dev);
wilc_ie = false;
wilc_optaining_ip = false;
del_timer(&wilc_during_ip_timer);
- PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n");
-
- if (g_ptk_keys_saved && g_gtk_keys_saved) {
- wilc_set_machw_change_vir_if(dev, true);
- }
switch (type) {
case NL80211_IFTYPE_STATION:
priv->wdev->iftype = type;
vif->monitor_flag = 0;
vif->iftype = STATION_MODE;
+ wilc_set_operation_mode(vif, STATION_MODE);
memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN);
- interface_type = vif->iftype;
- vif->iftype = STATION_MODE;
- if (wl->initialized) {
- wilc_del_all_rx_ba_session(vif, wl->vif[0]->bssid,
- TID);
- wilc_wait_msg_queue_idle();
-
- up(&wl->cfg_event);
-
- wilc1000_wlan_deinit(dev);
- wilc1000_wlan_init(dev, vif);
- wilc_initialized = 1;
- vif->iftype = interface_type;
-
- wilc_set_wfi_drv_handler(vif,
- wilc_get_vif_idx(wl->vif[0]));
- wilc_set_mac_address(wl->vif[0], wl->vif[0]->src_addr);
- wilc_set_operation_mode(vif, STATION_MODE);
-
- if (g_wep_keys_saved) {
- wilc_set_wep_default_keyid(wl->vif[0],
- g_key_wep_params.key_idx);
- wilc_add_wep_key_bss_sta(wl->vif[0],
- g_key_wep_params.key,
- g_key_wep_params.key_len,
- g_key_wep_params.key_idx);
- }
-
- wilc_flush_join_req(vif);
-
- if (g_ptk_keys_saved && g_gtk_keys_saved) {
- PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0],
- g_key_ptk_params.key[1],
- g_key_ptk_params.key[2]);
- PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0],
- g_key_gtk_params.key[1],
- g_key_gtk_params.key[2]);
- add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy,
- wl->vif[0]->ndev,
- g_add_ptk_key_params.key_idx,
- g_add_ptk_key_params.pairwise,
- g_add_ptk_key_params.mac_addr,
- (struct key_params *)(&g_key_ptk_params));
-
- add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy,
- wl->vif[0]->ndev,
- g_add_gtk_key_params.key_idx,
- g_add_gtk_key_params.pairwise,
- g_add_gtk_key_params.mac_addr,
- (struct key_params *)(&g_key_gtk_params));
- }
-
- if (wl->initialized) {
- for (i = 0; i < num_reg_frame; i++) {
- PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type,
- vif->g_struct_frame_reg[i].reg);
- wilc_frame_register(vif,
- vif->g_struct_frame_reg[i].frame_type,
- vif->g_struct_frame_reg[i].reg);
- }
- }
-
- wilc_enable_ps = true;
- wilc_set_power_mgmt(vif, 1, 0);
- }
+ wilc_enable_ps = true;
+ wilc_set_power_mgmt(vif, 1, 0);
break;
case NL80211_IFTYPE_P2P_CLIENT:
- wilc_enable_ps = false;
- wilc_set_power_mgmt(vif, 0, 0);
wilc_connecting = 0;
PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_P2P_CLIENT\n");
- wilc_del_all_rx_ba_session(vif, wl->vif[0]->bssid, TID);
-
dev->ieee80211_ptr->iftype = type;
priv->wdev->iftype = type;
vif->monitor_flag = 0;
-
- PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n");
vif->iftype = CLIENT_MODE;
+ wilc_set_operation_mode(vif, STATION_MODE);
-
- if (wl->initialized) {
- wilc_wait_msg_queue_idle();
-
- wilc1000_wlan_deinit(dev);
- wilc1000_wlan_init(dev, vif);
- wilc_initialized = 1;
-
- wilc_set_wfi_drv_handler(vif,
- wilc_get_vif_idx(wl->vif[0]));
- wilc_set_mac_address(wl->vif[0], wl->vif[0]->src_addr);
- wilc_set_operation_mode(vif, STATION_MODE);
-
- if (g_wep_keys_saved) {
- wilc_set_wep_default_keyid(wl->vif[0],
- g_key_wep_params.key_idx);
- wilc_add_wep_key_bss_sta(wl->vif[0],
- g_key_wep_params.key,
- g_key_wep_params.key_len,
- g_key_wep_params.key_idx);
- }
-
- wilc_flush_join_req(vif);
-
- if (g_ptk_keys_saved && g_gtk_keys_saved) {
- PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0],
- g_key_ptk_params.key[1],
- g_key_ptk_params.key[2]);
- PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0],
- g_key_gtk_params.key[1],
- g_key_gtk_params.key[2]);
- add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy,
- wl->vif[0]->ndev,
- g_add_ptk_key_params.key_idx,
- g_add_ptk_key_params.pairwise,
- g_add_ptk_key_params.mac_addr,
- (struct key_params *)(&g_key_ptk_params));
-
- add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy,
- wl->vif[0]->ndev,
- g_add_gtk_key_params.key_idx,
- g_add_gtk_key_params.pairwise,
- g_add_gtk_key_params.mac_addr,
- (struct key_params *)(&g_key_gtk_params));
- }
-
- refresh_scan(priv, 1, true);
- wilc_set_machw_change_vir_if(dev, false);
-
- if (wl->initialized) {
- for (i = 0; i < num_reg_frame; i++) {
- PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type,
- vif->g_struct_frame_reg[i].reg);
- wilc_frame_register(vif,
- vif->g_struct_frame_reg[i].frame_type,
- vif->g_struct_frame_reg[i].reg);
- }
- }
- }
+ wilc_enable_ps = false;
+ wilc_set_power_mgmt(vif, 0, 0);
break;
case NL80211_IFTYPE_AP:
dev->ieee80211_ptr->iftype = type;
priv->wdev->iftype = type;
vif->iftype = AP_MODE;
- PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
-
- PRINT_D(HOSTAPD_DBG, "Downloading AP firmware\n");
- wilc_wlan_get_firmware(dev);
-
- if (wl->initialized) {
- vif->iftype = AP_MODE;
- wilc_mac_close(dev);
- wilc_mac_open(dev);
-
- for (i = 0; i < num_reg_frame; i++) {
- PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type,
- vif->g_struct_frame_reg[i].reg);
- wilc_frame_register(vif,
- vif->g_struct_frame_reg[i].frame_type,
- vif->g_struct_frame_reg[i].reg);
- }
+
+ if (wl->initialized) {
+ wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif),
+ 0);
+ wilc_set_operation_mode(vif, AP_MODE);
+ wilc_set_power_mgmt(vif, 0, 0);
}
break;
case NL80211_IFTYPE_P2P_GO:
- PRINT_D(GENERIC_DBG, "start duringIP timer\n");
-
wilc_optaining_ip = true;
mod_timer(&wilc_during_ip_timer,
jiffies + msecs_to_jiffies(during_ip_time));
- wilc_set_power_mgmt(vif, 0, 0);
- wilc_del_all_rx_ba_session(vif, wl->vif[0]->bssid, TID);
- wilc_enable_ps = false;
PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_GO\n");
+
+ wilc_set_operation_mode(vif, AP_MODE);
dev->ieee80211_ptr->iftype = type;
priv->wdev->iftype = type;
-
- PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
-
- PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n");
-
-
vif->iftype = GO_MODE;
- wilc_wait_msg_queue_idle();
- wilc1000_wlan_deinit(dev);
- wilc1000_wlan_init(dev, vif);
- wilc_initialized = 1;
-
- wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(wl->vif[0]));
- wilc_set_mac_address(wl->vif[0], wl->vif[0]->src_addr);
- wilc_set_operation_mode(vif, AP_MODE);
-
- if (g_wep_keys_saved) {
- wilc_set_wep_default_keyid(wl->vif[0],
- g_key_wep_params.key_idx);
- wilc_add_wep_key_bss_sta(wl->vif[0],
- g_key_wep_params.key,
- g_key_wep_params.key_len,
- g_key_wep_params.key_idx);
- }
-
- wilc_flush_join_req(vif);
-
- if (g_ptk_keys_saved && g_gtk_keys_saved) {
- PRINT_D(CFG80211_DBG, "ptk %x %x %x cipher %x\n", g_key_ptk_params.key[0],
- g_key_ptk_params.key[1],
- g_key_ptk_params.key[2],
- g_key_ptk_params.cipher);
- PRINT_D(CFG80211_DBG, "gtk %x %x %x cipher %x\n", g_key_gtk_params.key[0],
- g_key_gtk_params.key[1],
- g_key_gtk_params.key[2],
- g_key_gtk_params.cipher);
- add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy,
- wl->vif[0]->ndev,
- g_add_ptk_key_params.key_idx,
- g_add_ptk_key_params.pairwise,
- g_add_ptk_key_params.mac_addr,
- (struct key_params *)(&g_key_ptk_params));
-
- add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy,
- wl->vif[0]->ndev,
- g_add_gtk_key_params.key_idx,
- g_add_gtk_key_params.pairwise,
- g_add_gtk_key_params.mac_addr,
- (struct key_params *)(&g_key_gtk_params));
- }
-
- if (wl->initialized) {
- for (i = 0; i < num_reg_frame; i++) {
- PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type,
- vif->g_struct_frame_reg[i].reg);
- wilc_frame_register(vif,
- vif->g_struct_frame_reg[i].frame_type,
- vif->g_struct_frame_reg[i].reg);
- }
- }
+ wilc_enable_ps = false;
+ wilc_set_power_mgmt(vif, 0, 0);
break;
default:
- PRINT_ER("Unknown interface type= %d\n", type);
+ netdev_err(dev, "Unknown interface type= %d\n", type);
return -EINVAL;
}
s32Error = set_channel(wiphy, &settings->chandef);
if (s32Error != 0)
- PRINT_ER("Error in setting channel\n");
+ netdev_err(dev, "Error in setting channel\n");
- wilc_wlan_set_bssid(dev, wl->vif[0]->src_addr);
+ wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, AP_MODE);
+ wilc_set_power_mgmt(vif, 0, 0);
s32Error = wilc_add_beacon(vif, settings->beacon_interval,
settings->dtim_period, beacon->head_len,
PRINT_D(HOSTAPD_DBG, "Deleting beacon\n");
- wilc_wlan_set_bssid(dev, NullBssid);
+ wilc_wlan_set_bssid(dev, NullBssid, AP_MODE);
s32Error = wilc_del_beacon(vif);
if (s32Error)
- PRINT_ER("Host delete beacon fail\n");
+ netdev_err(dev, "Host delete beacon fail\n");
return s32Error;
}
s32Error = wilc_add_station(vif, &strStaParams);
if (s32Error)
- PRINT_ER("Host add station fail\n");
+ netdev_err(dev, "Host add station fail\n");
}
return s32Error;
s32Error = wilc_del_station(vif, mac);
if (s32Error)
- PRINT_ER("Host delete station fail\n");
+ netdev_err(dev, "Host delete station fail\n");
}
return s32Error;
}
s32Error = wilc_edit_station(vif, &strStaParams);
if (s32Error)
- PRINT_ER("Host edit station fail\n");
+ netdev_err(dev, "Host edit station fail\n");
}
return s32Error;
}
PRINT_D(HOSTAPD_DBG, "Setting monitor flag in private structure\n");
vif = netdev_priv(priv->wdev->netdev);
vif->monitor_flag = 1;
- } else
- PRINT_ER("Error in initializing monitor interface\n ");
+ }
}
return priv->wdev;
}
return 0;
}
+static int wilc_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
+{
+ struct wilc_priv *priv = wiphy_priv(wiphy);
+ struct wilc_vif *vif = netdev_priv(priv->dev);
+
+ if (!wow && wilc_wlan_get_num_conn_ifcs(vif->wilc))
+ vif->wilc->suspend_event = true;
+ else
+ vif->wilc->suspend_event = false;
+
+ return 0;
+}
+
+static int wilc_resume(struct wiphy *wiphy)
+{
+ struct wilc_priv *priv = wiphy_priv(wiphy);
+ struct wilc_vif *vif = netdev_priv(priv->dev);
+
+ netdev_info(vif->ndev, "cfg resume\n");
+ return 0;
+}
+
+static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled)
+{
+ struct wilc_priv *priv = wiphy_priv(wiphy);
+ struct wilc_vif *vif = netdev_priv(priv->dev);
+
+ netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled);
+}
+
+static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+ enum nl80211_tx_power_setting type, int mbm)
+{
+ int ret;
+ s32 tx_power = MBM_TO_DBM(mbm);
+ struct wilc_priv *priv = wiphy_priv(wiphy);
+ struct wilc_vif *vif = netdev_priv(priv->dev);
+
+ if (tx_power < 0)
+ tx_power = 0;
+ else if (tx_power > 18)
+ tx_power = 18;
+ ret = wilc_set_tx_power(vif, tx_power);
+ if (ret)
+ netdev_err(vif->ndev, "Failed to set tx power\n");
+
+ return ret;
+}
+
+static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+ int *dbm)
+{
+ int ret;
+ struct wilc_priv *priv = wiphy_priv(wiphy);
+ struct wilc_vif *vif = netdev_priv(priv->dev);
+
+ ret = wilc_get_tx_power(vif, (u8 *)dbm);
+ if (ret)
+ netdev_err(vif->ndev, "Failed to get tx power\n");
+
+ return ret;
+}
+
static struct cfg80211_ops wilc_cfg80211_ops = {
.set_monitor_channel = set_channel,
.scan = scan,
.set_power_mgmt = set_power_mgmt,
.set_cqm_rssi_config = set_cqm_rssi_config,
+ .suspend = wilc_suspend,
+ .resume = wilc_resume,
+ .set_wakeup = wilc_set_wakeup,
+ .set_tx_power = set_tx_power,
+ .get_tx_power = get_tx_power,
+
};
int WILC_WFI_update_stats(struct wiphy *wiphy, u32 pktlen, u8 changed)
PRINT_D(CFG80211_DBG, "Allocating wireless device\n");
wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
- if (!wdev) {
- PRINT_ER("Cannot allocate wireless device\n");
+ if (!wdev)
goto _fail_;
- }
wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv));
- if (!wdev->wiphy) {
- PRINT_ER("Cannot allocate wiphy\n");
+ if (!wdev->wiphy)
goto _fail_mem_;
- }
WILC_WFI_band_2ghz.ht_cap.ht_supported = 1;
WILC_WFI_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
wdev = WILC_WFI_CfgAlloc();
if (!wdev) {
- PRINT_ER("CfgAlloc Failed\n");
+ netdev_err(net, "wiphy new allocate failed\n");
return NULL;
}
sema_init(&(priv->SemHandleUpdateStats), 1);
priv->wdev = wdev;
wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID;
+#ifdef CONFIG_PM
+ wdev->wiphy->wowlan = &wowlan_support;
+#endif
wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;
PRINT_INFO(CFG80211_DBG, "Max number of PMKIDs = %d\n", wdev->wiphy->max_num_pmkids);
set_wiphy_dev(wdev->wiphy, dev);
s32Error = wiphy_register(wdev->wiphy);
- if (s32Error) {
- PRINT_ER("Cannot register wiphy device\n");
- } else {
+ if (s32Error)
+ netdev_err(net, "Cannot register wiphy device\n");
+ else
PRINT_D(CFG80211_DBG, "Successful Registering\n");
- }
priv->dev = net;
return wdev;
setup_timer(&wilc_during_ip_timer, clear_duringIP, 0);
}
op_ifcs++;
- if (s32Error < 0) {
- PRINT_ER("Failed to creat refresh Timer\n");
- return s32Error;
- }
priv->gbAutoRateAdjusted = false;
priv->bInP2PlistenState = false;
sema_init(&(priv->hSemScanReq), 1);
- s32Error = wilc_init(net, &priv->hWILCWFIDrv);
+ s32Error = wilc_init(net, &priv->hif_drv);
if (s32Error)
- PRINT_ER("Error while initializing hostinterface\n");
+ netdev_err(net, "Error while initializing hostinterface\n");
return s32Error;
}
s32Error = wilc_deinit(vif);
clear_shadow_scan();
- if (op_ifcs == 0) {
- PRINT_D(CORECONFIG_DBG, "destroy during ip\n");
+ if (op_ifcs == 0)
del_timer_sync(&wilc_during_ip_timer);
- }
if (s32Error)
- PRINT_ER("Error while deintializing host interface\n");
+ netdev_err(net, "Error while deintializing host interface\n");
return s32Error;
}
spinlock_t lock;
struct net_device *dev;
struct napi_struct napi;
- struct host_if_drv *hWILCWFIDrv;
+ struct host_if_drv *hif_drv;
struct host_if_pmkid_attr pmkid_list;
struct WILC_WFI_stats netstats;
- u8 WILC_WFI_wep_default;
u8 WILC_WFI_wep_key[4][WLAN_KEY_LEN_WEP104];
u8 WILC_WFI_wep_key_len[4];
/* The real interface that the monitor is on */
} struct_frame_reg;
struct wilc_vif {
- u8 u8IfIdx;
+ u8 idx;
u8 iftype;
int monitor_flag;
int mac_opened;
u8 bssid[ETH_ALEN];
struct host_if_drv *hif_drv;
struct net_device *ndev;
+ u8 mode;
};
struct wilc {
const struct firmware *firmware;
struct device *dev;
+ bool suspend_event;
+
+ struct rf_info dummy_statistics;
};
struct WILC_WFI_mon_priv {
void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset);
void wilc_mac_indicate(struct wilc *wilc, int flag);
-void wilc_rx_complete(struct wilc *wilc);
void wilc_dbg(u8 *buff);
int wilc_lock_timeout(struct wilc *wilc, void *, u32 timeout);
const struct wilc_hif_func *ops);
void wilc1000_wlan_deinit(struct net_device *dev);
void WILC_WFI_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size);
-u16 wilc_set_machw_change_vir_if(struct net_device *dev, bool value);
int wilc_wlan_get_firmware(struct net_device *dev);
-int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid);
+int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode);
#endif
#include "wilc_wfi_netdevice.h"
#include "wilc_wlan_cfg.h"
-#ifdef WILC_OPTIMIZE_SLEEP_INT
-static inline void chip_allow_sleep(struct wilc *wilc);
-#endif
-static inline void chip_wakeup(struct wilc *wilc);
static u32 dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ;
/* FIXME: replace with dev_debug() */
static inline void acquire_bus(struct wilc *wilc, BUS_ACQUIRE_T acquire)
{
mutex_lock(&wilc->hif_cs);
- #ifndef WILC_OPTIMIZE_SLEEP_INT
- if (chip_ps_state != CHIP_WAKEDUP)
- #endif
- {
- if (acquire == ACQUIRE_AND_WAKEUP)
- chip_wakeup(wilc);
- }
+ if (acquire == ACQUIRE_AND_WAKEUP)
+ chip_wakeup(wilc);
}
static inline void release_bus(struct wilc *wilc, BUS_RELEASE_T release)
{
- #ifdef WILC_OPTIMIZE_SLEEP_INT
if (release == RELEASE_ALLOW_SLEEP)
chip_allow_sleep(wilc);
- #endif
mutex_unlock(&wilc->hif_cs);
}
-#ifdef TCP_ACK_FILTER
-static void wilc_wlan_txq_remove(struct txq_entry_t *tqe)
+static void wilc_wlan_txq_remove(struct wilc *wilc, struct txq_entry_t *tqe)
{
if (tqe == wilc->txq_head) {
}
wilc->txq_entries -= 1;
}
-#endif
static struct txq_entry_t *
wilc_wlan_txq_remove_from_head(struct net_device *dev)
wilc->txq_tail = tqe;
}
wilc->txq_entries += 1;
- PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", wilc->txq_entries);
spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
- PRINT_D(TX_DBG, "Wake the txq_handling\n");
-
up(&wilc->txq_event);
}
-static int wilc_wlan_txq_add_to_head(struct wilc *wilc, struct txq_entry_t *tqe)
+static int wilc_wlan_txq_add_to_head(struct wilc_vif *vif,
+ struct txq_entry_t *tqe)
{
unsigned long flags;
+ struct wilc *wilc = vif->wilc;
+
if (wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs,
CFG_PKTS_TIMEOUT))
return -1;
wilc->txq_head = tqe;
}
wilc->txq_entries += 1;
- PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", wilc->txq_entries);
spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
up(&wilc->txq_add_to_head_cs);
up(&wilc->txq_event);
- PRINT_D(TX_DBG, "Wake up the txq_handler\n");
return 0;
}
-#ifdef TCP_ACK_FILTER
struct ack_session_info;
struct ack_session_info {
u32 seq_num;
static inline int add_tcp_session(u32 src_prt, u32 dst_prt, u32 seq)
{
- ack_session_info[tcp_session].seq_num = seq;
- ack_session_info[tcp_session].bigger_ack_num = 0;
- ack_session_info[tcp_session].src_port = src_prt;
- ack_session_info[tcp_session].dst_port = dst_prt;
- tcp_session++;
-
- PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", tcp_session, seq);
+ if (tcp_session < 2 * MAX_TCP_SESSION) {
+ ack_session_info[tcp_session].seq_num = seq;
+ ack_session_info[tcp_session].bigger_ack_num = 0;
+ ack_session_info[tcp_session].src_port = src_prt;
+ ack_session_info[tcp_session].dst_port = dst_prt;
+ tcp_session++;
+ }
return 0;
}
static inline int update_tcp_session(u32 index, u32 ack)
{
- if (ack > ack_session_info[index].bigger_ack_num)
+ if (index < 2 * MAX_TCP_SESSION &&
+ ack > ack_session_info[index].bigger_ack_num)
ack_session_info[index].bigger_ack_num = ack;
return 0;
}
static inline int add_tcp_pending_ack(u32 ack, u32 session_index,
struct txq_entry_t *txqe)
{
- if (pending_acks < MAX_PENDING_ACKS) {
+ if (pending_base + pending_acks < MAX_PENDING_ACKS) {
pending_acks_info[pending_base + pending_acks].ack_num = ack;
pending_acks_info[pending_base + pending_acks].txqe = txqe;
pending_acks_info[pending_base + pending_acks].session_index = session_index;
}
return 0;
}
-static inline int remove_TCP_related(struct wilc *wilc)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&wilc->txq_spinlock, flags);
-
- spin_unlock_irqrestore(&wilc->txq_spinlock, flags);
- return 0;
-}
static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe)
{
vif = netdev_priv(dev);
wilc = vif->wilc;
+ spin_lock_irqsave(&wilc->txq_spinlock, flags);
eth_hdr_ptr = &buffer[0];
h_proto = ntohs(*((unsigned short *)ð_hdr_ptr[12]));
- if (h_proto == 0x0800) {
+ if (h_proto == ETH_P_IP) {
u8 *ip_hdr_ptr;
u8 protocol;
(u32)tcp_hdr_ptr[11];
for (i = 0; i < tcp_session; i++) {
- if (ack_session_info[i].seq_num == seq_no) {
+ if (i < 2 * MAX_TCP_SESSION &&
+ ack_session_info[i].seq_num == seq_no) {
update_tcp_session(i, ack_no);
break;
}
spin_lock_irqsave(&wilc->txq_spinlock, wilc->txq_spinlock_flags);
for (i = pending_base; i < (pending_base + pending_acks); i++) {
+ if (i >= MAX_PENDING_ACKS ||
+ pending_acks_info[i].session_index >= 2 * MAX_TCP_SESSION)
+ break;
if (pending_acks_info[i].ack_num < ack_session_info[pending_acks_info[i].session_index].bigger_ack_num) {
struct txq_entry_t *tqe;
- PRINT_D(TCP_ENH, "DROP ACK: %u\n",
- pending_acks_info[i].ack_num);
tqe = pending_acks_info[i].txqe;
if (tqe) {
- wilc_wlan_txq_remove(tqe);
+ wilc_wlan_txq_remove(wilc, tqe);
tqe->status = 1;
if (tqe->tx_complete_func)
tqe->tx_complete_func(tqe->priv,
return 1;
}
-#endif
static bool enabled = false;
enabled = value;
}
-#ifdef TCP_ACK_FILTER
static bool is_tcp_ack_filter_enabled(void)
{
return enabled;
}
-#endif
-static int wilc_wlan_txq_add_cfg_pkt(struct wilc *wilc, u8 *buffer, u32 buffer_size)
+static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer,
+ u32 buffer_size)
{
struct txq_entry_t *tqe;
+ struct wilc *wilc = vif->wilc;
- PRINT_D(TX_DBG, "Adding config packet ...\n");
+ netdev_dbg(vif->ndev, "Adding config packet ...\n");
if (wilc->quit) {
- PRINT_D(TX_DBG, "Return due to clear function\n");
+ netdev_dbg(vif->ndev, "Return due to clear function\n");
up(&wilc->cfg_event);
return 0;
}
tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC);
if (!tqe) {
- PRINT_ER("Failed to allocate memory\n");
+ netdev_err(vif->ndev, "Failed to allocate memory\n");
return 0;
}
tqe->buffer_size = buffer_size;
tqe->tx_complete_func = NULL;
tqe->priv = NULL;
-#ifdef TCP_ACK_FILTER
tqe->tcp_pending_ack_idx = NOT_TCP_ACK;
-#endif
- PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n");
- if (wilc_wlan_txq_add_to_head(wilc, tqe))
+ if (wilc_wlan_txq_add_to_head(vif, tqe))
return 0;
return 1;
}
tqe->tx_complete_func = func;
tqe->priv = priv;
- PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n");
-#ifdef TCP_ACK_FILTER
tqe->tcp_pending_ack_idx = NOT_TCP_ACK;
if (is_tcp_ack_filter_enabled())
tcp_process(dev, tqe);
-#endif
wilc_wlan_txq_add_to_tail(dev, tqe);
return wilc->txq_entries;
}
tqe->buffer_size = buffer_size;
tqe->tx_complete_func = func;
tqe->priv = priv;
-#ifdef TCP_ACK_FILTER
tqe->tcp_pending_ack_idx = NOT_TCP_ACK;
-#endif
- PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n");
wilc_wlan_txq_add_to_tail(dev, tqe);
return 1;
}
mutex_lock(&wilc->rxq_cs);
if (!wilc->rxq_head) {
- PRINT_D(RX_DBG, "Add to Queue head\n");
rqe->next = NULL;
wilc->rxq_head = rqe;
wilc->rxq_tail = rqe;
} else {
- PRINT_D(RX_DBG, "Add to Queue tail\n");
wilc->rxq_tail->next = rqe;
rqe->next = NULL;
wilc->rxq_tail = rqe;
}
wilc->rxq_entries += 1;
- PRINT_D(RX_DBG, "Number of queue entries: %d\n", wilc->rxq_entries);
mutex_unlock(&wilc->rxq_cs);
return wilc->rxq_entries;
}
static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc)
{
- PRINT_D(RX_DBG, "Getting rxQ element\n");
if (wilc->rxq_head) {
struct rxq_entry_t *rqe;
rqe = wilc->rxq_head;
wilc->rxq_head = wilc->rxq_head->next;
wilc->rxq_entries -= 1;
- PRINT_D(RX_DBG, "RXQ entries decreased\n");
mutex_unlock(&wilc->rxq_cs);
return rqe;
}
- PRINT_D(RX_DBG, "Nothing to get from Q\n");
return NULL;
}
-#ifdef WILC_OPTIMIZE_SLEEP_INT
-
-static inline void chip_allow_sleep(struct wilc *wilc)
+void chip_allow_sleep(struct wilc *wilc)
{
u32 reg = 0;
wilc->hif_func->hif_read_reg(wilc, 0xf0, ®);
wilc->hif_func->hif_write_reg(wilc, 0xf0, reg & ~BIT(0));
+ wilc->hif_func->hif_write_reg(wilc, 0xfa, 0);
}
+EXPORT_SYMBOL_GPL(chip_allow_sleep);
-static inline void chip_wakeup(struct wilc *wilc)
+void chip_wakeup(struct wilc *wilc)
{
u32 reg, clk_status_reg, trials = 0;
- u32 sleep_time;
if ((wilc->io_type & 0x1) == HIF_SPI) {
do {
} while (wilc_get_chipid(wilc, true) == 0);
} else if ((wilc->io_type & 0x1) == HIF_SDIO) {
+ wilc->hif_func->hif_write_reg(wilc, 0xfa, 1);
+ udelay(200);
wilc->hif_func->hif_read_reg(wilc, 0xf0, ®);
do {
wilc->hif_func->hif_write_reg(wilc, 0xf0,
}
if (chip_ps_state == CHIP_SLEEPING_MANUAL) {
- wilc->hif_func->hif_read_reg(wilc, 0x1C0C, ®);
- reg &= ~BIT(0);
- wilc->hif_func->hif_write_reg(wilc, 0x1C0C, reg);
-
- if (wilc_get_chipid(wilc, false) >= 0x1002b0) {
+ if (wilc_get_chipid(wilc, false) < 0x1002b0) {
u32 val32;
wilc->hif_func->hif_read_reg(wilc, 0x1e1c, &val32);
}
chip_ps_state = CHIP_WAKEDUP;
}
-#else
-static inline void chip_wakeup(struct wilc *wilc)
-{
- u32 reg, trials = 0;
-
- do {
- if ((wilc->io_type & 0x1) == HIF_SPI) {
- wilc->hif_func->hif_read_reg(wilc, 1, ®);
- wilc->hif_func->hif_write_reg(wilc, 1, reg & ~BIT(1));
- wilc->hif_func->hif_write_reg(wilc, 1, reg | BIT(1));
- wilc->hif_func->hif_write_reg(wilc, 1, reg & ~BIT(1));
- } else if ((wilc->io_type & 0x1) == HIF_SDIO) {
- wilc->hif_func->hif_read_reg(wilc, 0xf0, ®);
- wilc->hif_func->hif_write_reg(wilc, 0xf0,
- reg & ~BIT(0));
- wilc->hif_func->hif_write_reg(wilc, 0xf0,
- reg | BIT(0));
- wilc->hif_func->hif_write_reg(wilc, 0xf0,
- reg & ~BIT(0));
- }
-
- do {
- mdelay(3);
-
- if ((wilc_get_chipid(wilc, true) == 0))
- wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n");
-
- } while ((wilc_get_chipid(wilc, true) == 0) && ((++trials % 3) == 0));
-
- } while (wilc_get_chipid(wilc, true) == 0);
-
- if (chip_ps_state == CHIP_SLEEPING_MANUAL) {
- wilc->hif_func->hif_read_reg(wilc, 0x1C0C, ®);
- reg &= ~BIT(0);
- wilc->hif_func->hif_write_reg(wilc, 0x1C0C, reg);
-
- if (wilc_get_chipid(wilc, false) >= 0x1002b0) {
- u32 val32;
+EXPORT_SYMBOL_GPL(chip_wakeup);
- wilc->hif_func->hif_read_reg(wilc, 0x1e1c, &val32);
- val32 |= BIT(6);
- wilc->hif_func->hif_write_reg(wilc, 0x1e1c, val32);
-
- wilc->hif_func->hif_read_reg(wilc, 0x1e9c, &val32);
- val32 |= BIT(6);
- wilc->hif_func->hif_write_reg(wilc, 0x1e9c, val32);
- }
- }
- chip_ps_state = CHIP_WAKEDUP;
-}
-#endif
void wilc_chip_sleep_manually(struct wilc *wilc)
{
if (chip_ps_state != CHIP_WAKEDUP)
return;
acquire_bus(wilc, ACQUIRE_ONLY);
-#ifdef WILC_OPTIMIZE_SLEEP_INT
chip_allow_sleep(wilc);
-#endif
wilc->hif_func->hif_write_reg(wilc, 0x10a8, 1);
chip_ps_state = CHIP_SLEEPING_MANUAL;
release_bus(wilc, RELEASE_ONLY);
}
+EXPORT_SYMBOL_GPL(wilc_chip_sleep_manually);
+
+void host_wakeup_notify(struct wilc *wilc)
+{
+ acquire_bus(wilc, ACQUIRE_ONLY);
+ wilc->hif_func->hif_write_reg(wilc, 0x10b0, 1);
+ release_bus(wilc, RELEASE_ONLY);
+}
+EXPORT_SYMBOL_GPL(host_wakeup_notify);
+
+void host_sleep_notify(struct wilc *wilc)
+{
+ acquire_bus(wilc, ACQUIRE_ONLY);
+ wilc->hif_func->hif_write_reg(wilc, 0x10ac, 1);
+ release_bus(wilc, RELEASE_ONLY);
+}
+EXPORT_SYMBOL_GPL(host_sleep_notify);
int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count)
{
wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs,
CFG_PKTS_TIMEOUT);
-#ifdef TCP_ACK_FILTER
wilc_wlan_txq_filter_dup_tcp_ack(dev);
-#endif
- PRINT_D(TX_DBG, "Getting the head of the TxQ\n");
tqe = wilc_wlan_txq_get_first(wilc);
i = 0;
sum = 0;
vmm_sz = HOST_HDR_OFFSET;
vmm_sz += tqe->buffer_size;
- PRINT_D(TX_DBG, "VMM Size before alignment = %d\n", vmm_sz);
+
if (vmm_sz & 0x3)
vmm_sz = (vmm_sz + 4) & ~0x3;
if ((sum + vmm_sz) > LINUX_TX_SIZE)
break;
- PRINT_D(TX_DBG, "VMM Size AFTER alignment = %d\n", vmm_sz);
vmm_table[i] = vmm_sz / 4;
- PRINT_D(TX_DBG, "VMMTable entry size = %d\n",
- vmm_table[i]);
-
- if (tqe->type == WILC_CFG_PKT) {
+ if (tqe->type == WILC_CFG_PKT)
vmm_table[i] |= BIT(10);
- PRINT_D(TX_DBG, "VMMTable entry changed for CFG packet = %d\n", vmm_table[i]);
- }
vmm_table[i] = cpu_to_le32(vmm_table[i]);
i++;
sum += vmm_sz;
- PRINT_D(TX_DBG, "sum = %d\n", sum);
tqe = wilc_wlan_txq_get_next(wilc, tqe);
} else {
break;
}
} while (1);
- if (i == 0) {
- PRINT_D(TX_DBG, "Nothing in TX-Q\n");
+ if (i == 0)
break;
- } else {
- PRINT_D(TX_DBG, "Mark the last entry in VMM table - number of previous entries = %d\n", i);
+ else
vmm_table[i] = 0x0;
- }
+
acquire_bus(wilc, ACQUIRE_AND_WAKEUP);
counter = 0;
do {
- ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL,
- ®);
- if (!ret) {
- wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n");
+ ret = wilc->hif_func->hif_read_reg(wilc,
+ WILC_HOST_TX_CTRL,
+ ®);
+ if (!ret)
break;
- }
if ((reg & 0x1) == 0) {
- PRINT_D(TX_DBG, "Writing VMM table ... with Size = %d\n", ((i + 1) * 4));
break;
} else {
counter++;
if (counter > 200) {
counter = 0;
- PRINT_D(TX_DBG, "Looping in tx ctrl , forcce quit\n");
ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0);
break;
}
- PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n");
- release_bus(wilc, RELEASE_ALLOW_SLEEP);
- usleep_range(3000, 3000);
- acquire_bus(wilc, ACQUIRE_AND_WAKEUP);
}
} while (!wilc->quit);
timeout = 200;
do {
ret = wilc->hif_func->hif_block_tx(wilc, WILC_VMM_TBL_RX_SHADOW_BASE, (u8 *)vmm_table, ((i + 1) * 4));
- if (!ret) {
- wilc_debug(N_ERR, "ERR block TX of VMM table.\n");
+ if (!ret)
break;
- }
- ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_VMM_CTL,
- 0x2);
- if (!ret) {
- wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n");
+ ret = wilc->hif_func->hif_write_reg(wilc,
+ WILC_HOST_VMM_CTL,
+ 0x2);
+ if (!ret)
break;
- }
do {
ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®);
- if (!ret) {
- wilc_debug(N_ERR, "[wilc txq]: fail can't read reg host_vmm_ctl..\n");
+ if (!ret)
break;
- }
if ((reg >> 2) & 0x1) {
entries = ((reg >> 3) & 0x3f);
break;
} else {
release_bus(wilc, RELEASE_ALLOW_SLEEP);
- usleep_range(3000, 3000);
- acquire_bus(wilc, ACQUIRE_AND_WAKEUP);
- PRINT_WRN(GENERIC_DBG, "Can't get VMM entery - reg = %2x\n", reg);
}
} while (--timeout);
if (timeout <= 0) {
break;
if (entries == 0) {
- PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]]\n", reg, i, vmm_table[i - 1]);
-
ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®);
- if (!ret) {
- wilc_debug(N_ERR, "[wilc txq]: fail can't read reg WILC_HOST_TX_CTRL..\n");
+ if (!ret)
break;
- }
reg &= ~BIT(0);
ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg);
- if (!ret) {
- wilc_debug(N_ERR, "[wilc txq]: fail can't write reg WILC_HOST_TX_CTRL..\n");
+ if (!ret)
break;
- }
break;
} else {
break;
if (tqe->type == WILC_CFG_PKT) {
buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET;
} else if (tqe->type == WILC_NET_PKT) {
- char *bssid = ((struct tx_complete_data *)(tqe->priv))->pBssid;
+ char *bssid = ((struct tx_complete_data *)(tqe->priv))->bssid;
buffer_offset = ETH_ETHERNET_HDR_OFFSET;
memcpy(&txb[offset + 4], bssid, 6);
if (tqe->tx_complete_func)
tqe->tx_complete_func(tqe->priv,
tqe->status);
- #ifdef TCP_ACK_FILTER
- if (tqe->tcp_pending_ack_idx != NOT_TCP_ACK)
+ if (tqe->tcp_pending_ack_idx != NOT_TCP_ACK &&
+ tqe->tcp_pending_ack_idx < MAX_PENDING_ACKS)
pending_acks_info[tqe->tcp_pending_ack_idx].txqe = NULL;
- #endif
kfree(tqe);
} else {
break;
acquire_bus(wilc, ACQUIRE_AND_WAKEUP);
ret = wilc->hif_func->hif_clear_int_ext(wilc, ENABLE_TX_VMM);
- if (!ret) {
- wilc_debug(N_ERR, "[wilc txq]: fail can't start tx VMM ...\n");
+ if (!ret)
goto _end_;
- }
ret = wilc->hif_func->hif_block_tx_ext(wilc, 0, txb, offset);
- if (!ret) {
- wilc_debug(N_ERR, "[wilc txq]: fail can't block tx ext...\n");
+ if (!ret)
goto _end_;
- }
_end_:
up(&wilc->txq_add_to_head_cs);
wilc->txq_exit = 1;
- PRINT_D(TX_DBG, "THREAD: Exiting txq\n");
*txq_count = wilc->txq_entries;
return ret;
}
static void wilc_wlan_handle_rxq(struct wilc *wilc)
{
- int offset = 0, size, has_packet = 0;
+ int offset = 0, size;
u8 *buffer;
struct rxq_entry_t *rqe;
do {
if (wilc->quit) {
- PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function\n");
up(&wilc->cfg_event);
break;
}
rqe = wilc_wlan_rxq_remove(wilc);
- if (!rqe) {
- PRINT_D(RX_DBG, "nothing in the queue - exit 1st do-while\n");
+ if (!rqe)
break;
- }
+
buffer = rqe->buffer;
size = rqe->buffer_size;
- PRINT_D(RX_DBG, "rxQ entery Size = %d - Address = %p\n",
- size, buffer);
offset = 0;
do {
u32 pkt_len, pkt_offset, tp_len;
int is_cfg_packet;
- PRINT_D(RX_DBG, "In the 2nd do-while\n");
memcpy(&header, &buffer[offset], 4);
header = cpu_to_le32(header);
- PRINT_D(RX_DBG, "Header = %04x - Offset = %d\n",
- header, offset);
is_cfg_packet = (header >> 31) & 0x1;
pkt_offset = (header >> 22) & 0x1ff;
tp_len = (header >> 11) & 0x7ff;
pkt_len = header & 0x7ff;
- if (pkt_len == 0 || tp_len == 0) {
- wilc_debug(N_RXQ, "[wilc rxq]: data corrupt, packet len or tp_len is 0 [%d][%d]\n", pkt_len, tp_len);
+ if (pkt_len == 0 || tp_len == 0)
break;
- }
#define IS_MANAGMEMENT 0x100
#define IS_MANAGMEMENT_CALLBACK 0x080
&buffer[offset],
pkt_len,
pkt_offset);
- has_packet = 1;
}
} else {
struct wilc_cfg_rsp rsp;
wilc_wlan_cfg_indicate_rx(wilc, &buffer[pkt_offset + offset], pkt_len, &rsp);
if (rsp.type == WILC_CFG_RSP) {
- PRINT_D(RX_DBG, "wilc->cfg_seq_no = %d - rsp.seq_no = %d\n", wilc->cfg_seq_no, rsp.seq_no);
if (wilc->cfg_seq_no == rsp.seq_no)
up(&wilc->cfg_event);
} else if (rsp.type == WILC_CFG_RSP_STATUS) {
break;
} while (1);
kfree(rqe);
-
- if (has_packet)
- wilc_rx_complete(wilc);
-
} while (1);
wilc->rxq_exit = 1;
- PRINT_D(RX_DBG, "THREAD: Exiting RX thread\n");
}
static void wilc_unknown_isr_ext(struct wilc *wilc)
else
mdelay(WILC_PLL_TO_SPI);
- while (!(ISWILC1000(wilc_get_chipid(wilc, true)) && --trials)) {
- PRINT_D(TX_DBG, "PLL update retrying\n");
+ while (!(ISWILC1000(wilc_get_chipid(wilc, true)) && --trials))
mdelay(1);
- }
}
static void wilc_sleeptimer_isr_ext(struct wilc *wilc, u32 int_stats1)
{
wilc->hif_func->hif_clear_int_ext(wilc, SLEEP_INT_CLR);
-#ifndef WILC_OPTIMIZE_SLEEP_INT
- chip_ps_state = CHIP_SLEEPING_AUTO;
-#endif
}
static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status)
size = ((int_status & 0x7fff) << 2);
while (!size && retries < 10) {
- u32 time = 0;
-
- wilc_debug(N_ERR, "RX Size equal zero ... Trying to read it again for %d time\n", time++);
wilc->hif_func->hif_read_size(wilc, &size);
size = ((size & 0x7fff) << 2);
retries++;
if (LINUX_RX_SIZE - offset < size)
offset = 0;
- if (wilc->rx_buffer) {
+ if (wilc->rx_buffer)
buffer = &wilc->rx_buffer[offset];
- } else {
- wilc_debug(N_ERR, "[wilc isr]: fail Rx Buffer is NULL...drop the packets (%d)\n", size);
+ else
goto _end_;
- }
wilc->hif_func->hif_clear_int_ext(wilc,
DATA_INT_CLR | ENABLE_RX_VMM);
ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size);
- if (!ret) {
- wilc_debug(N_ERR, "[wilc isr]: fail block rx...\n");
+ if (!ret)
goto _end_;
- }
_end_:
if (ret) {
offset += size;
if (rqe) {
rqe->buffer = buffer;
rqe->buffer_size = size;
- PRINT_D(RX_DBG, "rxq entery Size= %d - Address = %p\n", rqe->buffer_size, rqe->buffer);
wilc_wlan_rxq_add(wilc, rqe);
}
}
if (int_status & PLL_INT_EXT)
wilc_pllupdate_isr_ext(wilc, int_status);
- if (int_status & DATA_INT_EXT) {
+ if (int_status & DATA_INT_EXT)
wilc_wlan_handle_isr_ext(wilc, int_status);
- #ifndef WILC_OPTIMIZE_SLEEP_INT
- chip_ps_state = CHIP_WAKEDUP;
- #endif
- }
+
if (int_status & SLEEP_INT_EXT)
wilc_sleeptimer_isr_ext(wilc, int_status);
- if (!(int_status & (ALL_INT_EXT))) {
+ if (!(int_status & (ALL_INT_EXT)))
wilc_unknown_isr_ext(wilc);
- }
+
release_bus(wilc, RELEASE_ALLOW_SLEEP);
}
EXPORT_SYMBOL_GPL(wilc_handle_isr);
-int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size)
+int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
+ u32 buffer_size)
{
u32 offset;
u32 addr, size, size2, blksz;
dma_buffer = kmalloc(blksz, GFP_KERNEL);
if (!dma_buffer) {
ret = -EIO;
- PRINT_ER("Can't allocate buffer for firmware download IO error\n ");
goto _fail_1;
}
- PRINT_D(INIT_DBG, "Downloading firmware size = %d ...\n", buffer_size);
-
offset = 0;
do {
memcpy(&addr, &buffer[offset], 4);
size2 = blksz;
memcpy(dma_buffer, &buffer[offset], size2);
- ret = wilc->hif_func->hif_block_tx(wilc, addr, dma_buffer,
- size2);
+ ret = wilc->hif_func->hif_block_tx(wilc, addr,
+ dma_buffer, size2);
if (!ret)
break;
if (!ret) {
ret = -EIO;
- PRINT_ER("Can't download firmware IO error\n ");
goto _fail_;
}
PRINT_D(INIT_DBG, "Offset = %d\n", offset);
acquire_bus(wilc, ACQUIRE_ONLY);
ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg);
if (!ret) {
- wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_cfg...\n");
release_bus(wilc, RELEASE_ONLY);
ret = -EIO;
return ret;
#ifdef WILC_EXT_PA_INV_TX_RX
reg |= WILC_HAVE_EXT_PA_INV_TX_RX;
#endif
-
+ reg |= WILC_HAVE_USE_IRQ_AS_HOST_WAKE;
reg |= WILC_HAVE_LEGACY_RF_SETTINGS;
#ifdef XTAL_24
reg |= WILC_HAVE_XTAL_24;
ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg);
if (!ret) {
- wilc_debug(N_ERR, "[wilc start]: fail write WILC_GP_REG_1 ...\n");
release_bus(wilc, RELEASE_ONLY);
ret = -EIO;
return ret;
ret = wilc->hif_func->hif_read_reg(wilc, 0x1000, &chipid);
if (!ret) {
- wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1000 ...\n");
release_bus(wilc, RELEASE_ONLY);
ret = -EIO;
return ret;
u32 reg = 0;
int ret;
u8 timeout = 10;
+
acquire_bus(wilc, ACQUIRE_AND_WAKEUP);
ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®);
if (!ret) {
- PRINT_ER("Error while reading reg\n");
release_bus(wilc, RELEASE_ALLOW_SLEEP);
return ret;
}
reg &= ~BIT(10);
ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg);
if (!ret) {
- PRINT_ER("Error while writing reg\n");
release_bus(wilc, RELEASE_ALLOW_SLEEP);
return ret;
}
do {
- ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®);
+ ret = wilc->hif_func->hif_read_reg(wilc,
+ WILC_GLB_RESET_0, ®);
if (!ret) {
- PRINT_ER("Error while reading reg\n");
release_bus(wilc, RELEASE_ALLOW_SLEEP);
return ret;
}
- PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n",
- reg, timeout);
if ((reg & BIT(10))) {
- PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n",
- timeout);
reg &= ~BIT(10);
- ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0,
- reg);
+ ret = wilc->hif_func->hif_write_reg(wilc,
+ WILC_GLB_RESET_0,
+ reg);
timeout--;
} else {
- PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n",
- timeout);
- ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0,
- ®);
+ ret = wilc->hif_func->hif_read_reg(wilc,
+ WILC_GLB_RESET_0,
+ ®);
if (!ret) {
- PRINT_ER("Error while reading reg\n");
release_bus(wilc, RELEASE_ALLOW_SLEEP);
return ret;
}
- PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n",
- reg, timeout);
break;
}
acquire_bus(wilc, ACQUIRE_AND_WAKEUP);
ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®);
- if (!ret) {
- PRINT_ER("Error while reading reg\n");
+ if (!ret)
release_bus(wilc, RELEASE_ALLOW_SLEEP);
- }
- PRINT_ER("Writing ABORT reg\n");
+
ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0,
(reg | ABORT_INT));
- if (!ret) {
- PRINT_ER("Error while writing reg\n");
+ if (!ret)
release_bus(wilc, RELEASE_ALLOW_SLEEP);
- }
+
release_bus(wilc, RELEASE_ALLOW_SLEEP);
wilc->hif_func->hif_deinit(NULL);
}
-static int wilc_wlan_cfg_commit(struct wilc *wilc, int type, u32 drv_handler)
+static int wilc_wlan_cfg_commit(struct wilc_vif *vif, int type,
+ u32 drv_handler)
{
+ struct wilc *wilc = vif->wilc;
struct wilc_cfg_frame *cfg = &wilc->cfg_frame;
int total_len = wilc->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE;
int seq_no = wilc->cfg_seq_no % 256;
cfg->wid_header[7] = (u8)(driver_handler >> 24);
wilc->cfg_seq_no = seq_no;
- if (!wilc_wlan_txq_add_cfg_pkt(wilc, &cfg->wid_header[0], total_len))
+ if (!wilc_wlan_txq_add_cfg_pkt(vif, &cfg->wid_header[0], total_len))
return -1;
return 0;
}
-int wilc_wlan_cfg_set(struct wilc *wilc, int start, u32 wid, u8 *buffer,
+int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u32 wid, u8 *buffer,
u32 buffer_size, int commit, u32 drv_handler)
{
u32 offset;
int ret_size;
+ struct wilc *wilc = vif->wilc;
if (wilc->cfg_frame_in_use)
return 0;
wilc->cfg_frame_offset = offset;
if (commit) {
- PRINT_D(TX_DBG, "[WILC]PACKET Commit with sequence number %d\n",
- wilc->cfg_seq_no);
- PRINT_D(RX_DBG, "Processing cfg_set()\n");
+ netdev_dbg(vif->ndev,
+ "[WILC]PACKET Commit with sequence number %d\n",
+ wilc->cfg_seq_no);
+ netdev_dbg(vif->ndev, "Processing cfg_set()\n");
wilc->cfg_frame_in_use = 1;
- if (wilc_wlan_cfg_commit(wilc, WILC_CFG_SET, drv_handler))
+ if (wilc_wlan_cfg_commit(vif, WILC_CFG_SET, drv_handler))
ret_size = 0;
if (wilc_lock_timeout(wilc, &wilc->cfg_event,
CFG_PKTS_TIMEOUT)) {
- PRINT_D(TX_DBG, "Set Timed Out\n");
+ netdev_dbg(vif->ndev, "Set Timed Out\n");
ret_size = 0;
}
wilc->cfg_frame_in_use = 0;
return ret_size;
}
-int wilc_wlan_cfg_get(struct wilc *wilc, int start, u32 wid, int commit,
+int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit,
u32 drv_handler)
{
u32 offset;
int ret_size;
+ struct wilc *wilc = vif->wilc;
if (wilc->cfg_frame_in_use)
return 0;
if (commit) {
wilc->cfg_frame_in_use = 1;
- if (wilc_wlan_cfg_commit(wilc, WILC_CFG_QUERY, drv_handler))
+ if (wilc_wlan_cfg_commit(vif, WILC_CFG_QUERY, drv_handler))
ret_size = 0;
if (wilc_lock_timeout(wilc, &wilc->cfg_event,
CFG_PKTS_TIMEOUT)) {
- PRINT_D(TX_DBG, "Get Timed Out\n");
+ netdev_dbg(vif->ndev, "Get Timed Out\n");
ret_size = 0;
}
- PRINT_D(GENERIC_DBG, "[WILC]Get Response received\n");
wilc->cfg_frame_in_use = 0;
wilc->cfg_frame_offset = 0;
wilc->cfg_seq_no += 1;
return ret;
}
+s32 wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
+ u32 count, u32 drv)
+{
+ s32 counter = 0, ret = 0;
+
+ if (mode == GET_CFG) {
+ for (counter = 0; counter < count; counter++) {
+ if (!wilc_wlan_cfg_get(vif, !counter,
+ wids[counter].id,
+ (counter == count - 1),
+ drv)) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+ }
+ counter = 0;
+ for (counter = 0; counter < count; counter++) {
+ wids[counter].size = wilc_wlan_cfg_get_val(
+ wids[counter].id,
+ wids[counter].val,
+ wids[counter].size);
+ }
+ } else if (mode == SET_CFG) {
+ for (counter = 0; counter < count; counter++) {
+ if (!wilc_wlan_cfg_set(vif, !counter,
+ wids[counter].id,
+ wids[counter].val,
+ wids[counter].size,
+ (counter == count - 1),
+ drv)) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
static u32 init_chip(struct net_device *dev)
{
u32 chipid;
return ret;
}
-u32 wilc_get_chipid(struct wilc *wilc, u8 update)
+u32 wilc_get_chipid(struct wilc *wilc, bool update)
{
static u32 chipid;
u32 tempchipid = 0;
- u32 rfrevid;
+ u32 rfrevid = 0;
- if (chipid == 0 || update != 0) {
+ if (chipid == 0 || update) {
wilc->hif_func->hif_read_reg(wilc, 0x1000, &tempchipid);
wilc->hif_func->hif_read_reg(wilc, 0x13f4, &rfrevid);
if (!ISWILC1000(tempchipid)) {
chipid = 0;
- goto _fail_;
+ return chipid;
}
if (tempchipid == 0x1002a0) {
- if (rfrevid == 0x1) {
- } else {
+ if (rfrevid != 0x1)
tempchipid = 0x1002a1;
- }
} else if (tempchipid == 0x1002b0) {
- if (rfrevid == 3) {
- } else if (rfrevid == 4) {
+ if (rfrevid == 0x4)
tempchipid = 0x1002b1;
- } else {
+ else if (rfrevid != 0x3)
tempchipid = 0x1002b2;
- }
}
chipid = tempchipid;
}
-_fail_:
return chipid;
}
PRINT_D(INIT_DBG, "Initializing WILC_Wlan ...\n");
- if (!wilc->hif_func->hif_init(wilc)) {
+ wilc->quit = 0;
+
+ if (!wilc->hif_func->hif_init(wilc, false)) {
ret = -EIO;
goto _fail_;
}
if (!wilc->tx_buffer)
wilc->tx_buffer = kmalloc(LINUX_TX_SIZE, GFP_KERNEL);
- PRINT_D(TX_DBG, "wilc->tx_buffer = %p\n", wilc->tx_buffer);
if (!wilc->tx_buffer) {
ret = -ENOBUFS;
if (!wilc->rx_buffer)
wilc->rx_buffer = kmalloc(LINUX_RX_SIZE, GFP_KERNEL);
- PRINT_D(TX_DBG, "wilc->rx_buffer =%p\n", wilc->rx_buffer);
+
if (!wilc->rx_buffer) {
ret = -ENOBUFS;
PRINT_ER("Can't allocate Rx Buffer");
ret = -EIO;
goto _fail_;
}
-#ifdef TCP_ACK_FILTER
init_tcp_tracking();
-#endif
return 1;
return ret;
}
-
-u16 wilc_set_machw_change_vir_if(struct net_device *dev, bool value)
-{
- u16 ret;
- u32 reg;
- struct wilc_vif *vif;
- struct wilc *wilc;
-
- vif = netdev_priv(dev);
- wilc = vif->wilc;
-
- mutex_lock(&wilc->hif_cs);
- ret = wilc->hif_func->hif_read_reg(wilc, WILC_CHANGING_VIR_IF,
- ®);
- if (!ret)
- PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n");
-
- if (value)
- reg |= BIT(31);
- else
- reg &= ~BIT(31);
-
- ret = wilc->hif_func->hif_write_reg(wilc, WILC_CHANGING_VIR_IF,
- reg);
-
- if (!ret)
- PRINT_ER("Error while writing reg WILC_CHANGING_VIR_IF\n");
-
- mutex_unlock(&wilc->hif_cs);
-
- return ret;
-}
#define WILC_HAVE_LEGACY_RF_SETTINGS BIT(5)
#define WILC_HAVE_XTAL_24 BIT(6)
#define WILC_HAVE_DISABLE_WILC_UART BIT(7)
+#define WILC_HAVE_USE_IRQ_AS_HOST_WAKE BIT(8)
/********************************************
*
********************************************/
struct wilc;
struct wilc_hif_func {
- int (*hif_init)(struct wilc *);
+ int (*hif_init)(struct wilc *, bool resume);
int (*hif_deinit)(struct wilc *);
int (*hif_read_reg)(struct wilc *, u32, u32 *);
int (*hif_write_reg)(struct wilc *, u32, u32);
};
struct wilc;
+struct wilc_vif;
-int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size);
+int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
+ u32 buffer_size);
int wilc_wlan_start(struct wilc *);
int wilc_wlan_stop(struct wilc *);
int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count);
void wilc_handle_isr(struct wilc *wilc);
void wilc_wlan_cleanup(struct net_device *dev);
-int wilc_wlan_cfg_set(struct wilc *wilc, int start, u32 wid, u8 *buffer,
+int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u32 wid, u8 *buffer,
u32 buffer_size, int commit, u32 drv_handler);
-int wilc_wlan_cfg_get(struct wilc *wilc, int start, u32 wid, int commit,
+int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit,
u32 drv_handler);
int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size);
int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
int wilc_mac_open(struct net_device *ndev);
int wilc_mac_close(struct net_device *ndev);
-int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *pBSSID);
void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size);
-
+void host_wakeup_notify(struct wilc *wilc);
+void host_sleep_notify(struct wilc *wilc);
extern bool wilc_enable_ps;
-
+void chip_allow_sleep(struct wilc *wilc);
+void chip_wakeup(struct wilc *wilc);
+s32 wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
+ u32 count, u32 drv);
#endif
static void wilc_wlan_parse_response_frame(u8 *info, int size)
{
u32 wid, len = 0, i = 0;
- static int seq;
while (size > 0) {
i = 0;
wid = info[0] | (info[1] << 8);
wid = cpu_to_le32(wid);
- PRINT_INFO(GENERIC_DBG, "Processing response for %d seq %d\n", wid, seq++);
+
switch ((wid >> 12) & 0x7) {
case WID_CHAR:
do {
if (wid == WID_SITE_SURVEY_RESULTS) {
static int toggle;
- PRINT_INFO(GENERIC_DBG, "Site survey results received[%d]\n",
- size);
-
- PRINT_INFO(GENERIC_DBG, "Site survey results value[%d]toggle[%d]\n", size, toggle);
i += toggle;
toggle ^= 1;
}
wid = info[0] | (info[1] << 8);
len = info[2];
- PRINT_INFO(GENERIC_DBG, "Status Len = %d Id= %d\n", len, wid);
+
if ((len == 1) && (wid == WID_STATUS)) {
pd->mac_status = info[3];
type = WILC_CFG_RSP_STATUS;
if (g_cfg_str[i].id == WID_SITE_SURVEY_RESULTS) {
static int toggle;
- PRINT_INFO(GENERIC_DBG, "Site survey results value[%d]\n",
- size);
i += toggle;
toggle ^= 1;
rsp->type = wilc_wlan_parse_info_frame(frame, size);
rsp->seq_no = msg_id;
/*call host interface info parse as well*/
- PRINT_INFO(RX_DBG, "Info message received\n");
wilc_gnrl_async_info_received(wilc, frame - 4, size + 4);
break;
break;
case 'S':
- PRINT_INFO(RX_DBG, "Scan Notification Received\n");
wilc_scan_complete_received(wilc, frame - 4, size + 4);
break;
default:
- PRINT_INFO(RX_DBG, "Receive unknown message type[%d-%d-%d-%d-%d-%d-%d-%d]\n",
- frame[0], frame[1], frame[2], frame[3], frame[4],
- frame[5], frame[6], frame[7]);
rsp->type = 0;
rsp->seq_no = msg_id;
ret = 0;
struct tx_complete_data {
int size;
void *buff;
- u8 *pBssid;
+ u8 *bssid;
struct sk_buff *skb;
};
WID_TYPE_FORCE_32BIT = 0xFFFFFFFF
};
+struct wid {
+ u16 id;
+ enum wid_type type;
+ s32 size;
+ s8 *val;
+};
+
typedef enum {
WID_NIL = 0xffff,
WID_DEL_BEACON = 0x00CA,
WID_LOGTerminal_Switch = 0x00CD,
+ WID_TX_POWER = 0x00CE,
/* EMAC Short WID list */
/* RTS Threshold */
/*
/* Custom Integer WID list */
WID_GET_INACTIVE_TIME = 0x2084,
- WID_SET_DRV_HANDLER = 0X2085,
WID_SET_OPERATION_MODE = 0X2086,
/* EMAC String WID list */
WID_SSID = 0x3000,
WID_MODEL_NAME = 0x3027, /*Added for CAPI tool */
WID_MODEL_NUM = 0x3028, /*Added for CAPI tool */
WID_DEVICE_NAME = 0x3029, /*Added for CAPI tool */
+ WID_SET_DRV_HANDLER = 0x3030,
/* NMAC String WID list */
WID_11N_P_ACTION_REQ = 0x3080,
int wilc_wlan_init(struct net_device *dev);
void wilc_bus_set_max_speed(void);
void wilc_bus_set_default_speed(void);
-u32 wilc_get_chipid(struct wilc *wilc, u8 update);
+u32 wilc_get_chipid(struct wilc *wilc, bool update);
#endif
{
struct p80211msg_dot11req_mibset msg;
p80211item_uint32_t *mibitem =
- (p80211item_uint32_t *) &msg.mibattribute.data;
+ (p80211item_uint32_t *)&msg.mibattribute.data;
msg.msgcode = DIDmsg_dot11req_mibset;
mibitem->did = did;
mibitem->data = data;
- return p80211req_dorequest(wlandev, (u8 *) &msg);
+ return p80211req_dorequest(wlandev, (u8 *)&msg);
}
static int prism2_domibset_pstr32(wlandevice_t *wlandev,
{
struct p80211msg_dot11req_mibset msg;
p80211item_pstr32_t *mibitem =
- (p80211item_pstr32_t *) &msg.mibattribute.data;
+ (p80211item_pstr32_t *)&msg.mibattribute.data;
msg.msgcode = DIDmsg_dot11req_mibset;
mibitem->did = did;
mibitem->data.len = len;
memcpy(mibitem->data.data, data, len);
- return p80211req_dorequest(wlandev, (u8 *) &msg);
+ return p80211req_dorequest(wlandev, (u8 *)&msg);
}
/* The interface functions, called by the cfg80211 layer */
int result = 0;
/* There is no direct way in the hardware (AFAIK) of removing
- a key, so we will cheat by setting the key to a bogus value */
+ * a key, so we will cheat by setting the key to a bogus value
+ */
+
/* send key to driver */
switch (key_index) {
case 0:
if (wlandev->mlmerequest == NULL)
return -EOPNOTSUPP;
- result = wlandev->mlmerequest(wlandev, (struct p80211msg *) &quality);
+ result = wlandev->mlmerequest(wlandev, (struct p80211msg *)&quality);
if (result == 0) {
sinfo->txrate.legacy = quality.txrate.data;
msg1.maxchanneltime.data = 250;
msg1.minchanneltime.data = 200;
- result = p80211req_dorequest(wlandev, (u8 *) &msg1);
+ result = p80211req_dorequest(wlandev, (u8 *)&msg1);
if (result) {
err = prism2_result2err(msg1.resultcode.data);
goto exit;
msg2.msgcode = DIDmsg_dot11req_scan_results;
msg2.bssindex.data = i;
- result = p80211req_dorequest(wlandev, (u8 *) &msg2);
+ result = p80211req_dorequest(wlandev, (u8 *)&msg2);
if ((result != 0) ||
(msg2.resultcode.data != P80211ENUM_resultcode_success)) {
break;
bss = cfg80211_inform_bss(wiphy,
ieee80211_get_channel(wiphy, freq),
CFG80211_BSS_FTYPE_UNKNOWN,
- (const u8 *) &(msg2.bssid.data.data),
+ (const u8 *)&(msg2.bssid.data.data),
msg2.timestamp.data, msg2.capinfo.data,
msg2.beaconperiod.data,
ie_buf,
(u8 *)sme->key);
if (result)
goto exit;
-
}
/* Assume we should set privacy invoked and exclude unencrypted
- We could possibly use sme->privacy here, but the assumption
- seems reasonable anyway */
+ * We could possible use sme->privacy here, but the assumption
+ * seems reasonable anyways
+ */
result = prism2_domibset_uint32(wlandev,
DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
P80211ENUM_truth_true);
} else {
/* Assume we should unset privacy invoked
- and exclude unencrypted */
+ * and exclude unencrypted
+ */
result = prism2_domibset_uint32(wlandev,
DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked,
P80211ENUM_truth_false);
P80211ENUM_truth_false);
if (result)
goto exit;
-
}
/* Now do the actual join. Note there is no way that I can
- see to request a specific bssid */
+ * see to request a specific bssid
+ */
msg_join.msgcode = DIDmsg_lnxreq_autojoin;
memcpy(msg_join.ssid.data.data, sme->ssid, length);
msg_join.ssid.data.len = length;
- result = p80211req_dorequest(wlandev, (u8 *) &msg_join);
+ result = p80211req_dorequest(wlandev, (u8 *)&msg_join);
exit:
if (result)
memcpy(msg_join.ssid.data.data, "---", 3);
msg_join.ssid.data.len = 3;
- result = p80211req_dorequest(wlandev, (u8 *) &msg_join);
+ result = p80211req_dorequest(wlandev, (u8 *)&msg_join);
if (result)
err = -EFAULT;
int result;
int err = 0;
- mibitem = (p80211item_uint32_t *) &msg.mibattribute.data;
+ mibitem = (p80211item_uint32_t *)&msg.mibattribute.data;
msg.msgcode = DIDmsg_dot11req_mibget;
mibitem->did =
DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
- result = p80211req_dorequest(wlandev, (u8 *) &msg);
+ result = p80211req_dorequest(wlandev, (u8 *)&msg);
if (result) {
err = -EFAULT;
DOASYNC
};
-#define THROTTLE_JIFFIES (HZ/8)
+#define THROTTLE_JIFFIES (HZ / 8)
#define URB_ASYNC_UNLINK 0
#define USB_QUEUE_BULK 0
-#define ROUNDUP64(a) (((a)+63)&~63)
+#define ROUNDUP64(a) (((a) + 63) & ~63)
#ifdef DEBUG_USB
static void dbprint_urb(struct urb *urb);
----------------------------------------------------------------*/
int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport)
{
- int result = 0;
hfa384x_metacmd_t cmd;
cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_DISABLE) |
cmd.parm1 = 0;
cmd.parm2 = 0;
- result = hfa384x_docmd_wait(hw, &cmd);
-
- return result;
+ return hfa384x_docmd_wait(hw, &cmd);
}
/*----------------------------------------------------------------
----------------------------------------------------------------*/
int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport)
{
- int result = 0;
hfa384x_metacmd_t cmd;
cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) |
cmd.parm1 = 0;
cmd.parm2 = 0;
- result = hfa384x_docmd_wait(hw, &cmd);
-
- return result;
+ return hfa384x_docmd_wait(hw, &cmd);
}
/*----------------------------------------------------------------
----------------------------------------------------------------*/
int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable)
{
- int result = 0;
hfa384x_metacmd_t cmd;
cmd.cmd = HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_MONITOR) |
cmd.parm1 = 0;
cmd.parm2 = 0;
- result = hfa384x_docmd_wait(hw, &cmd);
-
- return result;
+ return hfa384x_docmd_wait(hw, &cmd);
}
/*----------------------------------------------------------------
int hfa384x_cmd_download(hfa384x_t *hw, u16 mode, u16 lowaddr,
u16 highaddr, u16 codelen)
{
- int result = 0;
hfa384x_metacmd_t cmd;
pr_debug("mode=%d, lowaddr=0x%04x, highaddr=0x%04x, codelen=%d\n",
cmd.parm1 = highaddr;
cmd.parm2 = codelen;
- result = hfa384x_docmd_wait(hw, &cmd);
-
- return result;
+ return hfa384x_docmd_wait(hw, &cmd);
}
/*----------------------------------------------------------------
static void hfa384x_usbctlx_reaper_task(unsigned long data)
{
hfa384x_t *hw = (hfa384x_t *)data;
- struct list_head *entry;
- struct list_head *temp;
+ hfa384x_usbctlx_t *ctlx, *temp;
unsigned long flags;
spin_lock_irqsave(&hw->ctlxq.lock, flags);
/* This list is guaranteed to be empty if someone
* has unplugged the adapter.
*/
- list_for_each_safe(entry, temp, &hw->ctlxq.reapable) {
- hfa384x_usbctlx_t *ctlx;
-
- ctlx = list_entry(entry, hfa384x_usbctlx_t, list);
+ list_for_each_entry_safe(ctlx, temp, &hw->ctlxq.reapable, list) {
list_del(&ctlx->list);
kfree(ctlx);
}
static void hfa384x_usbctlx_completion_task(unsigned long data)
{
hfa384x_t *hw = (hfa384x_t *)data;
- struct list_head *entry;
- struct list_head *temp;
+ hfa384x_usbctlx_t *ctlx, *temp;
unsigned long flags;
int reap = 0;
/* This list is guaranteed to be empty if someone
* has unplugged the adapter ...
*/
- list_for_each_safe(entry, temp, &hw->ctlxq.completing) {
- hfa384x_usbctlx_t *ctlx;
-
- ctlx = list_entry(entry, hfa384x_usbctlx_t, list);
-
+ list_for_each_entry_safe(ctlx, temp, &hw->ctlxq.completing, list) {
/* Call the completion function that this
* command was assigned, assuming it has one.
*/
pr_debug("flags=0x%lx\n", hw->usb_flags);
if (!hw->wlandev->hwremoved &&
((test_and_clear_bit(THROTTLE_RX, &hw->usb_flags) &&
- !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags))
- |
+ !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags)) |
(test_and_clear_bit(THROTTLE_TX, &hw->usb_flags) &&
!test_and_set_bit(WORK_TX_RESUME, &hw->usb_flags))
)) {
*
* --------------------------------------------------------------------
*
-*================================================================ */
+*================================================================
+*/
#include <linux/module.h>
#include <linux/kernel.h>
*
* Call context:
* May be called in interrupt or non-interrupt context
-----------------------------------------------------------------*/
+*----------------------------------------------------------------
+*/
int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv,
struct sk_buff *skb, union p80211_hdr *p80211_hdr,
struct p80211_metawep *p80211_wep)
{
-
__le16 fc;
u16 proto;
struct wlan_ethhdr e_hdr;
/* tack on SNAP */
e_snap =
- (struct wlan_snap *) skb_push(skb,
+ (struct wlan_snap *)skb_push(skb,
sizeof(struct wlan_snap));
e_snap->type = htons(proto);
- if (ethconv == WLAN_ETHCONV_8021h
- && p80211_stt_findproto(proto)) {
+ if (ethconv == WLAN_ETHCONV_8021h &&
+ p80211_stt_findproto(proto)) {
memcpy(e_snap->oui, oui_8021h,
WLAN_IEEE_OUI_LEN);
} else {
/* tack on llc */
e_llc =
- (struct wlan_llc *) skb_push(skb,
+ (struct wlan_llc *)skb_push(skb,
sizeof(struct wlan_llc));
e_llc->dsap = 0xAA; /* SNAP, see IEEE 802 */
e_llc->ssap = 0xAA;
e_llc->ctl = 0x03;
-
}
}
p80211_wep->data = NULL;
- if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
- && (wlandev->hostwep & HOSTWEP_ENCRYPT)) {
+ if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) &&
+ (wlandev->hostwep & HOSTWEP_ENCRYPT)) {
/* XXXX need to pick keynum other than default? */
p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC);
p80211_wep->iv, p80211_wep->icv);
if (foo) {
netdev_warn(wlandev->netdev,
- "Host en-WEP failed, dropping frame (%d).\n",
- foo);
+ "Host en-WEP failed, dropping frame (%d).\n",
+ foo);
return 2;
}
fc |= cpu_to_le16(WLAN_SET_FC_ISWEP(1));
int i;
/* Gather wireless spy statistics: for each packet, compare the
- * source address with out list, and if match, get the stats... */
+ * source address with out list, and if match, get the stats...
+ */
for (i = 0; i < wlandev->spy_number; i++) {
-
if (!memcmp(wlandev->spy_address[i], mac, ETH_ALEN)) {
memcpy(wlandev->spy_address[i], mac, ETH_ALEN);
wlandev->spy_stat[i].level = rxmeta->signal;
*
* Call context:
* May be called in interrupt or non-interrupt context
-----------------------------------------------------------------*/
+*----------------------------------------------------------------
+*/
int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv,
struct sk_buff *skb)
{
payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN;
payload_offset = WLAN_HDR_A3_LEN;
- w_hdr = (union p80211_hdr *) skb->data;
+ w_hdr = (union p80211_hdr *)skb->data;
/* setup some vars for convenience */
fc = le16_to_cpu(w_hdr->a3.fc);
if ((WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0)) {
ether_addr_copy(daddr, w_hdr->a3.a1);
ether_addr_copy(saddr, w_hdr->a3.a2);
- } else if ((WLAN_GET_FC_TODS(fc) == 0)
- && (WLAN_GET_FC_FROMDS(fc) == 1)) {
+ } else if ((WLAN_GET_FC_TODS(fc) == 0) &&
+ (WLAN_GET_FC_FROMDS(fc) == 1)) {
ether_addr_copy(daddr, w_hdr->a3.a1);
ether_addr_copy(saddr, w_hdr->a3.a3);
- } else if ((WLAN_GET_FC_TODS(fc) == 1)
- && (WLAN_GET_FC_FROMDS(fc) == 0)) {
+ } else if ((WLAN_GET_FC_TODS(fc) == 1) &&
+ (WLAN_GET_FC_FROMDS(fc) == 0)) {
ether_addr_copy(daddr, w_hdr->a3.a3);
ether_addr_copy(saddr, w_hdr->a3.a2);
} else {
}
/* perform de-wep if necessary.. */
- if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc)
- && (wlandev->hostwep & HOSTWEP_DECRYPT)) {
+ if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) &&
+ WLAN_GET_FC_ISWEP(fc) &&
+ (wlandev->hostwep & HOSTWEP_DECRYPT)) {
if (payload_length <= 8) {
netdev_err(netdev,
"WEP frame too short (%u).\n", skb->len);
return 1;
}
foo = wep_decrypt(wlandev, skb->data + payload_offset + 4,
- payload_length - 8, -1,
- skb->data + payload_offset,
- skb->data + payload_offset +
- payload_length - 4);
+ payload_length - 8, -1,
+ skb->data + payload_offset,
+ skb->data + payload_offset +
+ payload_length - 4);
if (foo) {
/* de-wep failed, drop skb. */
pr_debug("Host de-WEP failed, dropping frame (%d).\n",
wlandev->rx.decrypt++;
}
- e_hdr = (struct wlan_ethhdr *) (skb->data + payload_offset);
+ e_hdr = (struct wlan_ethhdr *)(skb->data + payload_offset);
- e_llc = (struct wlan_llc *) (skb->data + payload_offset);
+ e_llc = (struct wlan_llc *)(skb->data + payload_offset);
e_snap =
- (struct wlan_snap *) (skb->data + payload_offset +
+ (struct wlan_snap *)(skb->data + payload_offset +
sizeof(struct wlan_llc));
/* Test for the various encodings */
/* A bogus length ethfrm has been encap'd. */
/* Is someone trying an oflow attack? */
netdev_err(netdev, "ENCAP frame too large (%d > %d)\n",
- payload_length, netdev->mtu + ETH_HLEN);
+ payload_length, netdev->mtu + ETH_HLEN);
return 1;
}
skb_trim(skb, skb->len - WLAN_CRC_LEN);
} else if ((payload_length >= sizeof(struct wlan_llc) +
- sizeof(struct wlan_snap))
- && (e_llc->dsap == 0xaa)
- && (e_llc->ssap == 0xaa)
- && (e_llc->ctl == 0x03)
- &&
- (((memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) == 0)
- && (ethconv == WLAN_ETHCONV_8021h)
- && (p80211_stt_findproto(le16_to_cpu(e_snap->type))))
- || (memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) !=
+ sizeof(struct wlan_snap)) &&
+ (e_llc->dsap == 0xaa) &&
+ (e_llc->ssap == 0xaa) &&
+ (e_llc->ctl == 0x03) &&
+ (((memcmp(e_snap->oui, oui_rfc1042,
+ WLAN_IEEE_OUI_LEN) == 0) &&
+ (ethconv == WLAN_ETHCONV_8021h) &&
+ (p80211_stt_findproto(le16_to_cpu(e_snap->type)))) ||
+ (memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) !=
0))) {
pr_debug("SNAP+RFC1042 len: %d\n", payload_length);
/* it's a SNAP + RFC1042 frame && protocol is in STT */
/* A bogus length ethfrm has been sent. */
/* Is someone trying an oflow attack? */
netdev_err(netdev, "SNAP frame too large (%d > %d)\n",
- payload_length, netdev->mtu);
+ payload_length, netdev->mtu);
return 1;
}
skb_trim(skb, skb->len - WLAN_CRC_LEN);
} else if ((payload_length >= sizeof(struct wlan_llc) +
- sizeof(struct wlan_snap))
- && (e_llc->dsap == 0xaa)
- && (e_llc->ssap == 0xaa)
- && (e_llc->ctl == 0x03)) {
+ sizeof(struct wlan_snap)) &&
+ (e_llc->dsap == 0xaa) &&
+ (e_llc->ssap == 0xaa) &&
+ (e_llc->ctl == 0x03)) {
pr_debug("802.1h/RFC1042 len: %d\n", payload_length);
/* it's an 802.1h frame || (an RFC1042 && protocol not in STT)
- build a DIXII + RFC894 */
+ * build a DIXII + RFC894
+ */
/* Test for an overlength frame */
if ((payload_length - sizeof(struct wlan_llc) -
/* A bogus length ethfrm has been sent. */
/* Is someone trying an oflow attack? */
netdev_err(netdev, "DIXII frame too large (%ld > %d)\n",
- (long int)(payload_length -
- sizeof(struct wlan_llc) -
- sizeof(struct wlan_snap)), netdev->mtu);
+ (long int)(payload_length -
+ sizeof(struct wlan_llc) -
+ sizeof(struct wlan_snap)), netdev->mtu);
return 1;
}
/* A bogus length ethfrm has been sent. */
/* Is someone trying an oflow attack? */
netdev_err(netdev, "OTHER frame too large (%d > %d)\n",
- payload_length, netdev->mtu);
+ payload_length, netdev->mtu);
return 1;
}
/* chop off the 802.11 CRC */
skb_trim(skb, skb->len - WLAN_CRC_LEN);
-
}
/*
*
* Call context:
* May be called in interrupt or non-interrupt context
-----------------------------------------------------------------*/
+*----------------------------------------------------------------
+*/
int p80211_stt_findproto(u16 proto)
{
/* Always return found for now. This is the behavior used by the */
- /* Zoom Win95 driver when 802.1h mode is selected */
+ /* Zoom Win95 driver when 802.1h mode is selected */
/* TODO: If necessary, add an actual search we'll probably
- need this to match the CMAC's way of doing things.
- Need to do some testing to confirm.
+ * need this to match the CMAC's way of doing things.
+ * Need to do some testing to confirm.
*/
if (proto == ETH_P_AARP) /* APPLETALK */
*
* Call context:
* May be called in interrupt or non-interrupt context
-----------------------------------------------------------------*/
+*----------------------------------------------------------------
+*/
void p80211skb_rxmeta_detach(struct sk_buff *skb)
{
struct p80211_rxmeta *rxmeta;
struct p80211_frmmeta *frmmeta;
/* Sanity checks */
- if (skb == NULL) { /* bad skb */
+ if (!skb) { /* bad skb */
pr_debug("Called w/ null skb.\n");
return;
}
frmmeta = P80211SKB_FRMMETA(skb);
- if (frmmeta == NULL) { /* no magic */
+ if (!frmmeta) { /* no magic */
pr_debug("Called w/ bad frmmeta magic.\n");
return;
}
rxmeta = frmmeta->rx;
- if (rxmeta == NULL) { /* bad meta ptr */
+ if (!rxmeta) { /* bad meta ptr */
pr_debug("Called w/ bad rxmeta ptr.\n");
return;
}
*
* Call context:
* May be called in interrupt or non-interrupt context
-----------------------------------------------------------------*/
+*----------------------------------------------------------------
+*/
int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb)
{
int result = 0;
struct p80211_frmmeta *frmmeta;
/* If these already have metadata, we error out! */
- if (P80211SKB_RXMETA(skb) != NULL) {
+ if (P80211SKB_RXMETA(skb)) {
netdev_err(wlandev->netdev,
"%s: RXmeta already attached!\n", wlandev->name);
result = 0;
/* Allocate the rxmeta */
rxmeta = kzalloc(sizeof(struct p80211_rxmeta), GFP_ATOMIC);
- if (rxmeta == NULL) {
+ if (!rxmeta) {
netdev_err(wlandev->netdev,
"%s: Failed to allocate rxmeta.\n", wlandev->name);
result = 1;
/* Overlay a frmmeta_t onto skb->cb */
memset(skb->cb, 0, sizeof(struct p80211_frmmeta));
- frmmeta = (struct p80211_frmmeta *) (skb->cb);
+ frmmeta = (struct p80211_frmmeta *)(skb->cb);
frmmeta->magic = P80211_FRMMETA_MAGIC;
frmmeta->rx = rxmeta;
exit:
*
* Call context:
* May be called in interrupt or non-interrupt context
-----------------------------------------------------------------*/
+*----------------------------------------------------------------
+*/
void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb)
{
struct p80211_frmmeta *meta;
}
/*
- 4-byte IV at start of buffer, 4-byte ICV at end of buffer.
- if successful, buf start is payload begin, length -= 8;
+ * 4-byte IV at start of buffer, 4-byte ICV at end of buffer.
+ * if successful, buf start is payload begin, length -= 8;
*/
int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override,
u8 *iv, u8 *icv)
wlandev = (wlandevice_t *)usb_get_intfdata(interface);
if (wlandev != NULL) {
LIST_HEAD(cleanlist);
- struct list_head *entry;
- struct list_head *temp;
+ hfa384x_usbctlx_t *ctlx, *temp;
unsigned long flags;
hfa384x_t *hw = wlandev->priv;
* and tell everyone who is waiting for their
* responses that we have shut down.
*/
- list_for_each(entry, &cleanlist) {
- hfa384x_usbctlx_t *ctlx;
-
- ctlx = list_entry(entry, hfa384x_usbctlx_t, list);
+ list_for_each_entry(ctlx, &cleanlist, list)
complete(&ctlx->done);
- }
/* Give any outstanding synchronous commands
* a chance to complete. All they need to do
msleep(100);
/* Now delete the CTLXs, because no-one else can now. */
- list_for_each_safe(entry, temp, &cleanlist) {
- hfa384x_usbctlx_t *ctlx;
-
- ctlx = list_entry(entry, hfa384x_usbctlx_t, list);
+ list_for_each_entry_safe(ctlx, temp, &cleanlist, list)
kfree(ctlx);
- }
/* Unhook the wlandev */
unregister_wlandev(wlandev);
.remove = xgifb_remove
};
-
-
/*****************************************************/
/* MODULE */
/*****************************************************/
/* of Linear VGA memory */
unsigned long ulVideoMemorySize; /* size, in bytes, of the
- memory on the board */
+ * memory on the board
+ */
unsigned char jChipType; /* Used to Identify Graphics Chip */
/* defined in the data structure type */
/* "XGI_CHIP_TYPE" */
unsigned char jChipRevision; /* Used to Identify Graphics
- Chip Revision */
+ * Chip Revision
+ */
unsigned char ujVBChipID; /* the ID of video bridge */
/* defined in the data structure type */
/* Additional IOCTL for communication xgifb <> X driver */
/* If changing this, xgifb.h must also be changed (for xgifb) */
#endif
-
unsigned long flags;
ktime_t timestamp;
int status;
+ struct list_head child_list;
+ struct list_head active_list;
};
enum fence_flag_bits {
* @addr: address of the register.
* @mask_int1: mask to enable/disable IRQ on INT1 pin.
* @mask_int2: mask to enable/disable IRQ on INT2 pin.
+ * @addr_ihl: address to enable/disable active low on the INT lines.
+ * @mask_ihl: mask to enable/disable active low on the INT lines.
* struct ig1 - represents the Interrupt Generator 1 of sensors.
* @en_addr: address of the enable ig1 register.
* @en_mask: mask to write the on/off value for enable.
u8 addr;
u8 mask_int1;
u8 mask_int2;
+ u8 addr_ihl;
+ u8 mask_ihl;
struct {
u8 en_addr;
u8 en_mask;
DOMAIN_BUS_PCI_MSI,
DOMAIN_BUS_PLATFORM_MSI,
DOMAIN_BUS_NEXUS,
+ DOMAIN_BUS_FSL_MC_MSI,
};
/**
u16 msi_index;
};
+/**
+ * fsl_mc_msi_desc - FSL-MC device specific msi descriptor data
+ * @msi_index: The index of the MSI descriptor
+ */
+struct fsl_mc_msi_desc {
+ u16 msi_index;
+};
+
/**
* struct msi_desc - Descriptor structure for MSI based interrupts
* @list: List head for management
* tree wide cleanup.
*/
struct platform_msi_desc platform;
+ struct fsl_mc_msi_desc fsl_mc;
};
};
--- /dev/null
+/*
+ * AD5721, AD5721R, AD5761, AD5761R, Voltage Output Digital to Analog Converter
+ *
+ * Copyright 2016 Qtechnology A/S
+ * 2016 Ricardo Ribalda <ricardo.ribalda@gmail.com>
+ *
+ * Licensed under the GPL-2.
+ */
+#ifndef __LINUX_PLATFORM_DATA_AD5761_H__
+#define __LINUX_PLATFORM_DATA_AD5761_H__
+
+/**
+ * enum ad5761_voltage_range - Voltage range the AD5761 is configured for.
+ * @AD5761_VOLTAGE_RANGE_M10V_10V: -10V to 10V
+ * @AD5761_VOLTAGE_RANGE_0V_10V: 0V to 10V
+ * @AD5761_VOLTAGE_RANGE_M5V_5V: -5V to 5V
+ * @AD5761_VOLTAGE_RANGE_0V_5V: 0V to 5V
+ * @AD5761_VOLTAGE_RANGE_M2V5_7V5: -2.5V to 7.5V
+ * @AD5761_VOLTAGE_RANGE_M3V_3V: -3V to 3V
+ * @AD5761_VOLTAGE_RANGE_0V_16V: 0V to 16V
+ * @AD5761_VOLTAGE_RANGE_0V_20V: 0V to 20V
+ */
+
+enum ad5761_voltage_range {
+ AD5761_VOLTAGE_RANGE_M10V_10V,
+ AD5761_VOLTAGE_RANGE_0V_10V,
+ AD5761_VOLTAGE_RANGE_M5V_5V,
+ AD5761_VOLTAGE_RANGE_0V_5V,
+ AD5761_VOLTAGE_RANGE_M2V5_7V5,
+ AD5761_VOLTAGE_RANGE_M3V_3V,
+ AD5761_VOLTAGE_RANGE_0V_16V,
+ AD5761_VOLTAGE_RANGE_0V_20V,
+};
+
+/**
+ * struct ad5761_platform_data - AD5761 DAC driver platform data
+ * @voltage_range: Voltage range the AD5761 is configured for
+ */
+
+struct ad5761_platform_data {
+ enum ad5761_voltage_range voltage_range;
+};
+
+#endif
IIO_VELOCITY,
IIO_CONCENTRATION,
IIO_RESISTANCE,
+ IIO_PH,
};
enum iio_modifier {